kube-scheduler的2个独立控制循环
k8s release-1.15
调度周期:从NextPod到RunPermitPlugins
绑定周期:从RunPrebindPlugins到RunPostbindPlugins
调度的本质就是将Pod为空的NodeName写上相应的Node的值
第1个控制循环:Informer Path
通过Informer来List Watch API对象,把待调度Pod(nodeName字段是空的)添加进调度队列。只有对调度队列和 Scheduler Cache 操作时,才需要加锁。
第2个控制循环:Scheduling Path
不断地从调度队列里出队一个Pod。
Predicates:过滤出符合条件的所有节点
Priorities:找到最终调度的节点
设置Pod对象的nodeName。
Assume:不在关键调度路径里访问kube-apiserver,只会更新Scheduler Cache里的Pod和Node信息。
Bind:通过协程异步地向kube-apiserver更新Pod。如果这次异步过程失败了,等Scheduler Cache同步之后一切就会恢复正常。
pkg/scheduler/scheduler.go
scheduleOne函数
Admit:kubelet二次确认
Pod完成调度后,在某个节点上运行起来之前,该节点上的kubelet通过GeneralPredicates的预选调度算法来再次验证该Pod是否确实能够运行在该节点上。当kubelet二次确认时发现Pod不能在当前节点上创建时,该Pod会被kubelet向kube-apiserver发送删除请求。
pkg/kubelet/kubelet.go
syncLoopIteration函数
HandlePodAdditions函数
canAdmitPod函数
pkg/kubelet/lifecycle/interfaces.go
Admit函数
Scheduler Framework:可扩展性设计
基于Go plugin机制(在编译时选择把哪些插件编译进去,每一个绿色的箭头都是插件),在调度器生命周期的各个关键点上,暴露出扩展接口,实现用户自定义调度器的能力。