LabHub
学习 学习路径 课程

CKA — Kubernetes 管理员

谁在造 Pod,谁在挑节点

在 LabHub 中继续学习

一句话总结

Deployment 不创建 Pod。它创建 ReplicaSet,ReplicaSet 创建 Pod,scheduler 选择节点,kubelet 执行。**每一层只看自己下面的一层。**理解这条链,就能按层拆分诊断 rollout 与 scheduling 问题。

Pod 生成链——Deployment 控制器创建 ReplicaSet,ReplicaSet 控制器创建 Pod;nodeName 为空的 Pod 处于 Pending,scheduler 填入该字段后,对应节点的 kubelet 执行它。五个主体不直接相互调用,而是全部经过 apiserver

概念图: 每一层只看自己下面的一层。 · 再创建一个新 ReplicaSet · 副本数 0 的状态保留 · nodeSelector

为什么需要它

为什么 Deployment 不直接创建 Pod?因为要进行 rolling update。

修改镜像后,Deployment 会再创建一个新 ReplicaSet,一边增加新实例,一边减少旧实例。maxSurgemaxUnavailable 决定增减速度。

参数 含义 replicas=4 时
maxSurge: 2 最多能比目标数量多启动多少 rolling 期间最多 6 个
maxUnavailable: 0 最多允许比目标数量少多少 始终至少 4 个 Ready

两者都设为 0,更新将无法移动。maxUnavailable: 0 表示无中断,但需要富余资源;maxSurge: 0 节省资源,却会短暂降低容量。

能够回滚也是因为这种结构。旧 ReplicaSet 不会被删除,而会以副本数 0 的状态保留,数量由 revisionHistoryLimit 决定。rollout undo 只是重新扩大那个旧 ReplicaSet。把该值设为 0 就无法回滚。

它如何运作

指挥 scheduler 放置工作负载主要有七种手柄。

经常出错的一点是,topologySpread 的候选 domain 集合由通过 Pod nodeAffinity/nodeSelector 的节点构成,taint 默认却会被忽略。因此 cordon 或被 taint 的节点仍可能作为 Pod 数为 0 的 domain,扩大偏差;若设为 DoNotSchedule,其他 Pod 就会 Pending。

在实际工作中会遇到的情况

**案例 1——Pending 未必是错误。**家庭实验室刚用 kubeadm 1.34 + Cilium 重建后,在仅有一个节点时,hubble-relay 与 hubble-ui 保持 Pending。

Warning  FailedScheduling  0/1 nodes are available: 1 node(s) had untolerated taint(s).

控制平面节点带有 node-role.kubernetes.io/control-plane:NoSchedule taint,hubble 组件不是 DaemonSet,而是 Deployment,因此没有容忍它。CoreDNS 则有默认 toleration,能够正常启动。同一集群、同一节点、不同结果,差别只有一个 toleration。worker 加入后问题立即消失。这不是 bug,而是正常行为。

**案例 2——一个 GPU 不等于另一个 GPU。**同一家庭实验室有 4 块 GPU:RTX 3090 24GB、RTX 5090 32GB、两块 RTX 4070 Laptop 8GB。Pod 如果只请求 nvidia.com/gpu: 1,**需要 32GB 的训练任务可能被放到 8GB 笔记本 GPU 上。**因为对 scheduler 来说,扩展资源只是数量,两者同为一个 GPU。

GPU Feature Discovery 添加的 gpu.memory 标签是字符串,无法使用“24GB 以上”这样的比较 selector。因此需要自行添加语义标签。

gpu.homelab/tier=xlarge  gpu.homelab/vram=32g   # 5090
gpu.homelab/tier=large   gpu.homelab/vram=24g   # 3090
gpu.homelab/tier=small   gpu.homelab/vram=8g    # 4070 Laptop x2

现在 workload 可以用 nodeSelector: {gpu.homelab/tier: xlarge} 选择自身等级。scheduling 归根结底是资源名称定义得有多准确的问题。

再举一个目标选择示例:同一集群安装 GPU Operator 后,NFD worker 出现在全部 5 个节点,其余 GPU 组件只出现在 4 个 GPU 节点,因为其他 DaemonSet 会通过 nodeSelector 查看 NFD 添加的标签。

后续实验要做什么

第一个实验将创建并扩缩 Deployment,调整 rolling 参数后实际 rollout 和回滚,还会创建 DaemonSet 与 StatefulSet。第二个实验会依次使用从 nodeSelector 到 topologySpreadConstraints 的七种手柄。最后一题只有记住前面被 cordon 和 taint 的节点状态才能解决。