Kubernetes 调度过程

Kubernetes调度器的核心,是两个相互独立的控制循环

  • Informer Path
  • Scheduling Path

Informer 负责监听 etcd 中的 Pod、Node、Service 等与调度相关的API对象的变化。

Scheduling 是负责调度的主循环,主要功能是不断地从调度队列里提取Pod,然后根据 从从Scheduler Cache中或得的 节点信息 对节点进行打分 0-10,得分最高的节点作为这次调度的结果

调度算法完成之后,调度器将Pod对象的NodeName字段值修改为上述节点的名字,称作 bind

先Predicates(预选)再Priorities(优选)

Kubernetes 中默认的调度策略有以下4种

  1. GeneralPredicates

最基本的调度策略,例如计算cpu和内存资源是否够用

2. Volume相关的过滤规则

检查PV是否冲突等

3. 宿主机相关的规律规则

检查Node污点等

4. Pod相关过滤规则

检查Pod亲和性等

以上4种策略作为Filter,用来确定一个节点是否可以运行待调度的Pod的基本策略

为了不在关键调度路径中远程访问 API Server,Kubernetes 在默认调度器在Bind阶段只会更新 Scheduler Cache里的 Pod 和 Node 的信息。这种基于乐观假设的API对象更新方式叫做 Assume。

Assume完成之后,调度器才会创建一个Goroutine来异步地向API Server发起更新Pod的请求,来真正完成Bind操作。如果异步请求失败,等Scheduler Cache同步之后一切就会恢复正常。

在异步Bind结束之后,新的Pod真正被调度之前,该节点上的Kubelet海辉通过一个叫做admit的操作来再次验证该Pod是否可以在该节点上运行,也就是把GeneralPredicates的基本调度算法(资源是否可用、端口是否冲突)等再执行一遍,作为Kubelet的二次确认。

优选策略的工作是为这些节点打分

优选策略最长使用的打分规则是 LeastRequestedPriority

score = (cpu((capacity-sum(requested))10/capacity) + memory((capacity-sum(requested))10/capacity

与 LeastRequestedPriority 一起发挥作用的还有 BalancedResourceAllocation

score = 10 - variance(cpuFraction,memoryFraction,volumeFraction)*10

每种资源的 Fraction 的定义是 Pod 请求的资源/节点上的可用资源,variance算法的作用是计算每两种资源Fraction之间的“距离”,最后选择的是资源Fraction差距最小的节点。

BalancedResourceAllocation 选择的是所有节点里各种资源分配最均衡的那个节点,从而避免一个节点上CPU被大量分配,而内存大量剩余的情况

此外还有3种优选策略:NodeAffinityPriority、TaintTolerationPriority 和 InterPodAffinityPriority,作为优选策略,一个节点满足上述规则的字段数目越多,它的得分就会越高

在默认的优选策略里,还有一个叫做 ImageLocalPriority 的策略。它是在Kubernetes v1.12 里提供的调度规则,即如果待调度的Pod需要使用很大的镜像,并且已经存在于某些节点上,那么这些节点的得分会比较高

当然为了避免调度堆叠,调度器在计算得分时还会根据镜像的分布进行优化,即如果大镜像分布的节点数目很少,那么这些节点的权重会被调低,从而 对冲 引起调度堆叠的风险。

Send a Message