Files
kuboard-press/t/cka/daily/004.md
2020-12-24 13:57:19 +08:00

192 lines
7.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
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每日一题004')">答案及解析</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/>