Files
kuboard-press/t/cka/daily/004.md
huanqing.shao ef26d62190 CKA 006、CICD
2019-11-27 22:59:16 +08:00

7.3 KiB
Raw Blame History

vssueId, sharingTitle, description, meta
vssueId sharingTitle description meta
166 CKA备考打卡 - 每日一题 - Day 4 CKA备考打卡 - 每日一题 - Day 4
name content
keywords Kubernetes,K8S,CKA,Certified Kubernetes Administrator

CKA每日一题 --- Day 4

::: tip 考题

通过命令行使用nginx镜像创建一个pod并手动调度到节点名为node1121节点上Pod的名称为cka-1121答题最好附上所用命令、创建Pod所需最精简的yaml如果评论有限制请把注意点列出主要需列出手动调度怎么做

注意手动调度是指不需要经过kube-scheduler去调度。

:::

答案及解析

答案

将名称为cka-1121的Pod调度到节点node1121

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://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

其中在构建pod资源对象新增、更新、删除的回调函数时分已被调度的和未被调度的回调。

已被调度的回调:

已被调度的pod根据FilterFunc中定义的逻辑过滤nodeName不为空返回true时将会走Handler中定义的AddFunc、UpdateFunc、DeleteFunc这个其实最终不会加入到podQueue中但需要加入到本地缓存中因为调度器会维护一份节点上pod列表的缓存。

// 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中。

// 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

找到config.yaml文件

CKA每日一题_Day4

里面指定了staticPodPath

CKA每日一题_Day4

kubeadm安装的集群master节点上的kube-apiserver、kube-scheduler、kube-controller-manager、etcd就是通过static Pod方式部署的

CKA每日一题_Day4

CKA 考试每日一题系列,全部内容由 我的小碗汤 创作,本站仅做转载