一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第9天,点击查看活动详情。
一、预选策略 (Predicates Policies)
预选策略的主要目的是过滤掉不符合条件的 Node
节点,预选策略大体上可以分为如下 4 类:
-
GeneralPredicates
:负责最基础的调度策略 -
与
Volume
相关的过滤规则:负责与容器持久化Volume
相关的调度策略 -
与
Node
相关的过滤规则:负责考察待调度Pod
是否满足Node
本身的一些条件 -
与已运行
Pod
相关的过滤规则:负责检查待调度Pod
与Node
上已有Pod
之间的亲和性关系
当开始调度 Pod
时,调度器会同时开启多个协程并发进行 Predicates
过滤,每个协程按照固定的顺序进行过滤,最后返回过滤后可以运行 Pod
的 Node
列表。
(1)GeneralPredicates
是最基础的调度策略,这个接口也会被其它组件直接调用,比如 kubelet
在启动 Pod
前会再执行一遍 GeneralPredicates
用于二次确认。
它包含的具体策略有:
PodFitsResources
:计算Node
的CPU
、内存、扩展资源(如GPU
)是否够用PodFitsHost
:检查Node
的名字是否跟Pod
的spec.nodeName
匹配PodFitsHostPorts
:检查Pod
申请的Node
端口是否冲突PodMatchNodeSelector
:检查Node
是否能匹配Pod
的nodeSelector
和nodeAffinity
(2)与 Volume 相关的过滤规则
它包含的具体策略有:
-
NoDiskConflict:检查 Node 上所有的 Pods 是否与待调度 Pod 的 Volume 有冲突,比如 AWS、GCE 的
-
Volume 不能被两个 Pod 同时使用
-
VolumeZonePredicate:检查 Pod Volume 的 zone 标签是否与节点的 zone 标签匹配,如果 Node 没有 zone 标签就认定为匹配
-
MaxPDVolumeCountPredicate:检查 Node 上某种类型的 Volume 是否已经超过指定数目
-
CSIMaxVolumeCountPredicate:检查 CSI Volume 相关的限制
-
VolumeBindingPredicate:检查 Pod 对应的 Local PV 的 nodeAffinity 字段,是否跟某个 Node 标签相匹配。如果该 Pod PVC 还没有绑定 PV,调度器要检查所有待绑定的 PV,且该 PV 的 nodeAffinity 是否与 Node 标签匹配
(3)与 Node 相关的过滤规则
它包含的具体策略有:
NodeConditionPredicate
:检查 Node
是否还未准备好或处于 NodeOutOfDisk
、NodeNetworkUnavailable
状态,或者 Node
的 spec.Unschedulable
设置为 true
,如果出现以上的情况,该 Node
都无法被调度
PodTolerateNodeTaints
:检查 Node
的 taint
(污点)机制,只有当 Pod
的 Toleration
与 Node
的 Taint
匹配时,Pod
才能调度到该 Node
上
NodeMemoryPressurePredicate
:检查 Node
的内存是否不够使用
NodeDiskPressurePredicate
:检查 Node
的磁盘是否不够使用
NodePIDPressurePredicate
:检查 Node
的 PID
是否不够使用
(4)与已运行 Pod 相关的过滤规则
它包含的具体策略主要是:PodAffinityPredicate
,用于检查待调度 Pod
与 Node
上已有 Pod
之间的亲和性与反亲和性关系。
二、优选策略 (Priorites Policies)
通过前面预选策略过滤出来的 Node
列表,会再一次使用优选策略为这些 Node
打分,最终得分最高的 Node
会作为该 Pod
的调度对象。
有多个优选策略就相当于有多个打分函数,那么总得分的计算公式为:
总分 = (打分函数 1 * 权重 1) + (打分函数 2 * 权重 2) + ... + (打分函数 3 * 权重 3),打分函数的打分范围为 0 - 10 分,0 表示非常不合适,10 表示非常合适。每个打分函数都可以配置对应的权重,默认权重值为 1,如果某个打分函数特别重要就可以增加该权重值。
常用的优选策略有:
-
LeastRequestedPriority:选出空闲资源(CPU & Memory)最多的 Node
-
BalancedResourceAllocation:主要用于资源平衡,选出各项资源分配最均衡的 Node,避免出现某些 Node CPU 被大量分配,而 Memory 大量剩余的情况
-
SelectorSpreadPriority:为了更好容灾,对属于同一个 Service 或是 RC 的多个 Pod 副本,尽量调度到多个不同的 Node 上
-
InterPodAffinityPriority:优先将 Pod 调度到相同的拓扑上(如同一个节点、Rack、Zone 等)
-
NodeAffinityPriority:优先调度到匹配 NodeAffinity 的 Node 上
-
TaintTolerationPriority:优先调度到匹配 TaintToleration 的 Node 上
-
ImageLocalityPriority:优先选择已经存在 Pod 所需 Image 的 Node(已注册但默认未使用)
-
MostRequestedPriority:优先选择已经使用过的 Node,适用于 cluster-autoscaler(已注册但默认未使用)
三、自定义调度器
除了使用集群自带的调度器,也可以编写自定义的调度器,然后在 Pod YAML
文件中通过参数 spec.schedulername
指定调度器的名称,这样在 Pod
创建时就会使用自定义的调度器而不是集群默认的调度器。
比如:
apiVersion: v1
kind: Pod
metadata:
name: Pod-example
spec:
使用自定义调度器 my-scheduler
schedulername: my-scheduler
containers:
- name: nginx
image: nginx
而自定义调度器的实现逻辑依然是:读取 API Server
中 Pod
列表,通过特定算法找到最适合的 Node
,然后把调度结果写回到 API Server
。