This commit is contained in:
huanqing.shao
2019-11-25 23:14:51 +08:00
parent a296ea4821
commit 72702d0d3a
19 changed files with 285 additions and 6 deletions

View File

@@ -46,4 +46,6 @@ CKA证书的含金量如何考不考这个证完全取决于个人因为
[CKA每日一题 - Day 3](./daily/003.html)
[CKA每日一题 - Day 4](./daily/004.html)
<JoinCKACommunity/>

View File

@@ -70,3 +70,9 @@ External Attacher 组件负责Attach阶段。Mount阶段由kubelet里的VolumeMa
</b-card>
</b-collapse>
> CKA 考试每日一题系列,全部内容由 [我的小碗汤](https://mp.weixin.qq.com/s/5tYgb_eSzHz_TMsi0U32gw) 创作,本站仅做转载
<JoinCKACommunity/>

View File

@@ -94,11 +94,11 @@ cronjob.batch/pi created
**kubectl run执行后到底发生了什么**有必要看看kubectl源码入口函数在$GOPATH\src\k8s.io\kubernetes\cmd\clicheck\checkcliconventions.go中
![image-20191123192840601](./003.assets/image-20191123192840601.png)
![CKA每日一题_Day3](./003.assets/image-20191123192840601.png)
其中cmd.NewKubectlCommand为构建kubectl以及其子命令行参数。最终的执行业务逻辑的代码都在pkg\kubectl包下面。不同的子命令apply、run、create入口对应的在pkg\kubectl\cmd下面
![image-20191123192926509](./003.assets/image-20191123192926509.png)
![CKA每日一题_Day3](./003.assets/image-20191123192926509.png)
最重要的o.Run(f, cmd, args)中会对kubectl run传入的参数进行一系列校验填充默认值。
@@ -106,11 +106,11 @@ cronjob.batch/pi created
如果设置了expose为true在372行同样的调用o.createGeneratedObject生成并创建service。
![image-20191123192959494](./003.assets/image-20191123192959494.png)
![CKA每日一题_Day3](./003.assets/image-20191123192959494.png)
方法第649行根据不同的generator实现生成不同的资源对象。
![image-20191123193035704](./003.assets/image-20191123193035704.png)
![CKA每日一题_Day3](./003.assets/image-20191123193035704.png)
run命令对应的generator实现有以下几种代码位于pkg\kubectl\generate\versioned\generator.go中的DefaultGenerators函数。
@@ -130,7 +130,7 @@ case"run":
o.createGeneratedObject方法第689行对生成的资源对象向APIServer发送http创建请求。
![image-20191123193109039](./003.assets/image-20191123193109039.png)
![CKA每日一题_Day3](./003.assets/image-20191123193109039.png)
具体的kubectl run命令的代码感兴趣的同学可以进一步深挖我也会在后续的源码分析系列文章中进行更详细的解析。
@@ -138,3 +138,8 @@ o.createGeneratedObject方法第689行对生成的资源对象向APIServer发送
</b-card>
</b-collapse>
> CKA 考试每日一题系列,全部内容由 [我的小碗汤](https://mp.weixin.qq.com/s/5tYgb_eSzHz_TMsi0U32gw) 创作,本站仅做转载
<JoinCKACommunity/>

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 438 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 256 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

195
t/cka/daily/004.md Normal file
View File

@@ -0,0 +1,195 @@
---
vssueId: 166
# layout: StepLayout
sharingTitle: CKA备考打卡 - 每日一题 - Day 4
description: CKA备考打卡 - 每日一题 - Day 4
meta:
- name: keywords
content: Kubernetes,K8S,CKA,Certified Kubernetes Administrator
---
# CKA每日一题 --- Day 4
<AdSenseTitle/>
::: tip 考题
通过命令行使用nginx镜像创建一个pod并手动调度到节点名为node1121节点上Pod的名称为cka-1121答题最好附上所用命令、创建Pod所需最精简的yaml如果评论有限制请把注意点列出主要需列出手动调度怎么做
> 注意手动调度是指不需要经过kube-scheduler去调度。
:::
<b-button v-b-toggle.collapse-join-error variant="danger" size="sm" style="margin-top: 1rem;" v-on:click="$sendGaEvent('cka-daily', 'cka-daily', 'CKA每日一题003')">答案及解析</b-button>
<b-collapse id="collapse-join-error" class="mt-2">
<b-card style="background-color: rgb(254, 240, 240); border: solid 1px #F56C6C;">
### 答案
将名称为cka-1121的Pod调度到节点node1121
``` yaml
apiVersion: v1
kind: Pod
metadata:
name: cka-1121
labels:
app: cka-1121
spec:
containers:
- name: cka-1121
image: busybox
command: ['sh', '-c', 'echo Hello CKA! && sleep 3600']
nodeName: node1121
```
### 解析
## 昨日解析
**官网中调度器地址:**
https://kubernetes.io/docs/concepts/scheduling/kube-scheduler/
中文地址: [https://kuboard.cn/learning/k8s-advanced/schedule/](https://kuboard.cn/learning/k8s-advanced/schedule/)
**调度器命令行参数:**
https://kubernetes.io/docs/reference/command-line-tools-reference/kube-scheduler/
**调度器kube-scheduler分为预选、优选、pod优先级抢占、bind阶段**
**预选**从podQueue的待调度队列中弹出需要调度的pod先进入预选阶段预选函数来判断每个节点是否适合被该Pod调度。
**优选**:从预选筛选出的满足的节点中选择出最优的节点。
**pod优先级抢占**如果预选和优选调度失败则会尝试将优先级低的pod剔除让优先级高的pod调度成功。
**bind**上述步骤完成后调度器会更新本地缓存但最后需要将绑定结果提交到etcd中需要调用Apiserver的Bind接口完成。
> 以下k8s源码版本为1.13.2
我们去查看kube-scheduler源码调度器通过list-watch机制监听集群内Pod的新增、更新、删除事件调用回调函数。指定nodeName后将不会放入到未调度的podQueue队列中也就不会走上面这几个阶段。具体可以来到pkg\scheduler\factory\factory.go源码中的NewConfigFactory函数中
![CKA每日一题_Day4](./004.assets/image-20191125195308865.png)
其中在构建pod资源对象新增、更新、删除的回调函数时分已被调度的和未被调度的回调。
**已被调度的回调:**
已被调度的pod根据FilterFunc中定义的逻辑过滤nodeName不为空返回true时将会走Handler中定义的AddFunc、UpdateFunc、DeleteFunc这个其实最终不会加入到podQueue中但需要加入到本地缓存中因为调度器会维护一份节点上pod列表的缓存。
```go
// scheduled pod cache 已被调度的
args.PodInformer.Informer().AddEventHandler(
cache.FilteringResourceEventHandler{
FilterFunc: func(obj interface{}) bool{
switch t := obj.(type) {
case*v1.Pod://nodeName不为空,返回true;且返回true时将被走AddFunc、UpdateFunc、DeleteFunc,这个其实最终不会加入到podQueue中
return assignedPod(t)
case cache.DeletedFinalStateUnknown:
if pod, ok := t.Obj.(*v1.Pod); ok {
return assignedPod(pod)
}
runtime.HandleError(fmt.Errorf("unable to convert object %T to *v1.Pod in %T", obj, c))
return false
default:
runtime.HandleError(fmt.Errorf("unable to handle object in %T: %T", c, obj))
return false
}
},
Handler: cache.ResourceEventHandlerFuncs{
AddFunc: c.addPodToCache,
UpdateFunc: c.updatePodInCache,
DeleteFunc: c.deletePodFromCache,
},
},
)
```
**未被调度的回调:**
未被调度的pod根据FilterFunc中定义的逻辑过滤nodeName为空且pod的SchedulerName和该调度器的名称一致时返回true返回true时将会走Handler中定义的AddFunc、UpdateFunc、DeleteFunc这个最终会加入到podQueue中。
```go
// unscheduled pod queue 没有被调度的
args.PodInformer.Informer().AddEventHandler(
cache.FilteringResourceEventHandler{
FilterFunc: func(obj interface{}) bool{
switch t := obj.(type) {
case*v1.Pod://nodeName为空且pod的SchedulerName和该调度器的名称一致时返回true;且返回true时将被加入到pod queue
return !assignedPod(t) && responsibleForPod(t, args.SchedulerName)
case cache.DeletedFinalStateUnknown:
if pod, ok := t.Obj.(*v1.Pod); ok {
return !assignedPod(pod) && responsibleForPod(pod, args.SchedulerName)
}
runtime.HandleError(fmt.Errorf("unable to convert object %T to *v1.Pod in %T", obj, c))
return false
default:
runtime.HandleError(fmt.Errorf("unable to handle object in %T: %T", c, obj))
return false
}
},
Handler: cache.ResourceEventHandlerFuncs{
AddFunc: c.addPodToSchedulingQueue,
UpdateFunc: c.updatePodInSchedulingQueue,
DeleteFunc: c.deletePodFromSchedulingQueue,
},
},
)
```
**手动调度适用场景:**
- 调度器不工作时可设置nodeName临时救急
- 可以封装成自己的调度器;
**扩展点:**
- 过去几个版本的Daemonset都是由controller直接指定pod的运行节点不经过调度器。
- 直到1.11版本DaemonSet的pod由scheduler调度才作为alpha特性引入
**昨天的留言中有人提到static Pod这种其实也属于节点固定但这种Pod局限很大比如不能挂载configmaps和secrets等这个由Admission Controllers控制。**
下面简单说一下静态Pod
**静态Pod官网说明**
https://kubernetes.io/docs/tasks/configure-pod-container/static-pod/
静态 pod指在特定的节点上直接通过 kubelet守护进程进行管理APIServer无法管理。它没有跟任何的控制器进行关联kubelet 守护进程对它进行监控如果崩溃了kubelet 守护进程会重启它。Kubelet 通过APIServer为每个静态 pod 创建 镜像 pod这些镜像 pod 对于 APIServer是可见的即kubectl可以查询到这些Pod但是不受APIServer控制。
具体static pod yaml文件放到哪里需要在kubelet配置中指定先找到kubelet配置文件
```
systemctl status kubelet
```
![CKA每日一题_Day4](./004.assets/image-20191125200103548.png)
找到config.yaml文件
![CKA每日一题_Day4](./004.assets/image-20191125200118155.png)
里面指定了staticPodPath
![CKA每日一题_Day4](./004.assets/image-20191125200130735.png)
kubeadm安装的集群master节点上的kube-apiserver、kube-scheduler、kube-controller-manager、etcd就是通过static Pod方式部署的
![CKA每日一题_Day4](./004.assets/640.png)
</b-card>
</b-collapse>
> CKA 考试每日一题系列,全部内容由 [我的小碗汤](https://mp.weixin.qq.com/s/5tYgb_eSzHz_TMsi0U32gw) 创作,本站仅做转载
<JoinCKACommunity/>