本活动在微信公众号【个人小碗汤】上举行,有送书活动!这里参与答题不能参与到送书活动哦!
经过命令行,使用nginx镜像建立一个pod并手动调度到节点名为node1121节点上,Pod的名称为cka-1121,答题最好附上,所用命令、建立Pod所需最精简的yaml;若是评论有限制,请把注意点列出,主要需列出手动调度怎么作?
注意:手动调度是指不须要通过kube-scheduler去调度。
将名称为cka-1121的Pod,调度到节点node1121:java
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/co...
调度器命令行参数:
https://kubernetes.io/docs/re...node
调度器kube-scheduler分为预选、优选、pod优先级抢占、bind阶段;nginx
预选:从podQueue的待调度队列中弹出须要调度的pod,先进入预选阶段,预选函数来判断每一个节点是否适合被该Pod调度。golang
优选:从预选筛选出的知足的节点中选择出最优的节点。docker
pod优先级抢占:若是预选和优选调度失败,则会尝试将优先级低的pod剔除,让优先级高的pod调度成功。shell
bind:上述步骤完成后,调度器会更新本地缓存,但最后须要将绑定结果提交到etcd中,须要调用Apiserver的Bind接口完成。segmentfault
如下k8s源码版本为1.13.2
咱们去查看kube-scheduler源码,调度器经过list-watch机制,监听集群内Pod的新增、更新、删除事件,调用回调函数。指定nodeName后将不会放入到未调度的podQueue队列中,也就不会走上面这几个阶段。具体能够来到pkgschedulerfactoryfactory.go源码中的NewConfigFactory函数中:
其中在构建pod资源对象新增、更新、删除的回调函数时,分已被调度的和未被调度的回调。api
已被调度的回调:
已被调度的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, }, }, )
手动调度适用场景:
扩展点:
昨天的留言中,有人提到static Pod,这种其实也属于节点固定,但这种Pod局限很大,好比:不能挂载configmaps和secrets等,这个由Admission Controllers控制。
下面简单说一下静态Pod:
静态Pod官网说明:
https://kubernetes.io/docs/ta...
静态 pod指在特定的节点上直接经过 kubelet守护进程进行管理,APIServer没法管理。它没有跟任何的控制器进行关联,kubelet 守护进程对它进行监控,若是崩溃了,kubelet 守护进程会重启它。Kubelet 经过APIServer为每一个静态 pod 建立 镜像 pod,这些镜像 pod 对于 APIServer是可见的(即kubectl能够查询到这些Pod),可是不受APIServer控制。
具体static pod yaml文件放到哪里,须要在kubelet配置中指定,先找到kubelet配置文件:
systemctl status kubelet
找到config.yaml文件:
里面指定了staticPodPath:
kubeadm安装的集群,master节点上的kube-apiserver、kube-scheduler、kube-controller-manager、etcd就是经过static Pod方式部署的:
经过命令行,建立两个deployment。
- 须要集群中有2个节点 ;
- 第1个deployment名称为cka-1122-01,使用nginx镜像,有2个pod,并配置该deployment自身的pod之间在节点级别反亲和;
- 第2个deployment名称为cka-1122-02,使用nginx镜像,有2个pod,并配置该deployment的pod与第1个deployment的pod在节点级别亲和;
最好提交最精简的deployment yaml,若是评论被限制,请提交反亲和性配置块yaml,也可屡次评论提交
做者:小碗汤,一位热爱、认真写做的小伙,目前维护原创公众号:『个人小碗汤』,专一于写golang、docker、kubernetes等知识等提高硬实力的文章,期待你的关注。转载说明:务必注明来源(注明:来源于公众号:个人小碗汤, 做者:小碗汤)
做者:小碗汤,一位热爱、认真写做的小伙,目前维护原创公众号:『个人小碗汤』,专一于写go语言、docker、kubernetes、java等开发、运维知识等提高硬实力的文章,期待你的关注。转载说明:务必注明来源(注明:来源于公众号:个人小碗汤,做者:小碗汤)