一起养成写作习惯!这是我参与「掘金日新计划 · 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。