LabHub
学习 学习路径 课程

CKA — Kubernetes 管理员

控制调度

在 LabHub 中继续学习

目标

使用全部七种决定 Pod 将运行在哪个节点上的方法,最后结合前面步骤形成的集群状态(被 cordon 的节点、带 taint 的节点)来设计调度方案。

为什么这很重要

调度在 CKA 中分值不算高,但一半的故障排查题实际上都是调度问题。看到 Pending Pod 时,必须能够判断它在 filter 阶段的哪个条件上被阻止。

尤其是 topologySpreadConstraints,经常被误解。计算偏差时使用的候选域,是能够通过 Pod nodeAffinity/nodeSelector 的节点。taint 默认会被忽略,仍参与计算。因此,Pod 实际无法使用的节点可能作为一个含 0 个 Pod 的域留下,增大偏差;当设置为 DoNotSchedule 时,其余 Pod 可能全部保持 Pending。理解 node affinity 是缩小候选范围的关键,正是本实验的核心。

步骤

  1. 创建 namespace cka-sched。为 lab-node-0 添加标签 topology.kubernetes.io/zone=zone-a,为 lab-node-1 添加 zone-b,为 lab-node-2 添加 zone-c,并额外为 lab-node-0 添加 disktype=ssd。然后创建 Pod ssd-pod(镜像 nginx:1.27),使用 nodeSelector disktype=ssd 将其调度到 lab-node-0
  2. lab-node-2 添加标签 disktype=hdd,将 Pod affinity-required 只使用 required node affinity(disktype In [hdd]) 调度到 lab-node-2。不要使用 nodeSelector。
  3. 创建 Deployment pref(副本数 2,镜像 nginx:1.27),并添加 preferred node affinity。weight 为 50,条件为 disktype In [ssd]
  4. 创建 Deployment spread(副本数 3,Pod 标签 app=spread),并添加 required Pod anti-affinity。labelSelector 为 app=spread,topologyKey 为 topology.kubernetes.io/zone
  5. 创建 Deployment drain-demo(副本数 2,镜像 nginx:1.27),然后 cordon 并 drain lab-node-1,将其完全清空。drain-demo 应在其他节点上恢复到 2/2。
  6. lab-node-2 添加 taint workload=batch:NoSchedule。为 Pod batch-pod 设置能够容忍该 taint 的 toleration 和 nodeSelector disktype=hdd,将其调度到 lab-node-2
  7. 创建 PriorityClass cka-high。value 为 100000,globalDefault 为 false,preemptionPolicy 为 PreemptLowerPriority。让 Pod important 使用该类。
  8. 创建 Deployment evenly(副本数 4,Pod 标签 app=evenly)。topologySpreadConstraints 设置为 maxSkew 1、topologyKey topology.kubernetes.io/zone、whenUnsatisfiable DoNotSchedule、labelSelector app=evenly。同时添加 required node affinity disktype In [ssd, hdd] 和对 workload=batch:NoSchedule 的 toleration,使 4 个 Pod 在两个 zone 中按 2:2 分布。

参考

节点标签与 nodeSelector

创建 namespace cka-sched。为 lab-node-0 添加标签 topology.kubernetes.io/zone=zone-a,为 lab-node-1 添加 zone-b,为 lab-node-2 添加 zone-c,并额外为 lab-node-0 添加 disktype=ssd。然后创建 Pod ssd-pod(镜像 nginx:1.27),使用 nodeSelector disktype=ssd 将其调度到 lab-node-0

nodeSelector 是位于 Pod spec 顶层的 map。标签必须精确匹配,且不能使用表达式。

required node affinity

lab-node-2 添加标签 disktype=hdd,将 Pod affinity-required 只使用 required node affinity(disktype In [hdd]) 调度到 lab-node-2。不要使用 nodeSelector。

affinity.nodeAffinity 下的 requiredDuringSchedulingIgnoredDuringExecution 中包含 nodeSelectorTerms 数组。matchExpressions 的 operator 为 In。不要使用 nodeSelector。

preferred node affinity

创建 Deployment pref(副本数 2,镜像 nginx:1.27),并添加 preferred node affinity。weight 为 50,条件为 disktype In [ssd]

preferred 部分是数组,每一项都包含 weight 和 preference。即使无法满足也仍可调度,因此评分不检查具体落在哪个节点。

使用 Pod anti-affinity 分散部署

创建 Deployment spread(副本数 3,Pod 标签 app=spread),并添加 required Pod anti-affinity。labelSelector 为 app=spread,topologyKey 为 topology.kubernetes.io/zone

podAntiAffinity 的条目包含 labelSelector 和 topologyKey。由于每个节点的 zone 标签不同,按 zone 分散最终也会分布到不同节点。

清空节点

创建 Deployment drain-demo(副本数 2,镜像 nginx:1.27),然后 cordon 并 drain lab-node-1,将其完全清空。drain-demo 应在其他节点上恢复到 2/2。

cordon 只阻止新 Pod,已运行的 Pod 会保留。要真正清空节点,必须执行 drain,并加入 DaemonSet 和 emptyDir 相关选项才能继续。

taint 与 toleration

lab-node-2 添加 taint workload=batch:NoSchedule。为 Pod batch-pod 设置能够容忍该 taint 的 toleration 和 nodeSelector disktype=hdd,将其调度到 lab-node-2

taint 格式为 key=value:effect。toleration 的 operator 应设为 Equal,value 也必须匹配。具体调度到哪个节点还需要另行指定。

应用 PriorityClass

创建 PriorityClass cka-high。value 为 100000,globalDefault 为 false,preemptionPolicy 为 PreemptLowerPriority。让 Pod important 使用该类。

PriorityClass 是集群作用域资源。若将 globalDefault 设为 true,会影响集群中的所有 Pod,请谨慎。Pod 中只需填写名称,spec.priority 会自动设置。

综合:在剩余节点间均匀分布

创建 Deployment evenly(副本数 4,Pod 标签 app=evenly)。topologySpreadConstraints 设置为 maxSkew 1、topologyKey topology.kubernetes.io/zone、whenUnsatisfiable DoNotSchedule、labelSelector app=evenly。同时添加 required node affinity disktype In [ssd, hdd] 和对 workload=batch:NoSchedule 的 toleration,使 4 个 Pod 在两个 zone 中按 2:2 分布。

先数一数当前集群中有多少节点能够接收 Pod。被 cordon 的节点必须排除在候选之外,带 taint 的节点只有在存在 toleration 时才能使用。缩小候选范围的关键是 node affinity。