调和循环(Reconciliation Loop)是控制器的工作节律:周期性对比账本里的期望状态与 Watch 到达的现状,发现差值就执行最小动作缩小它。Deployment 与 ReplicaSet 分层协作,让"3 个副本"成为一条持续生效的守恒定律——这就是 Kubernetes 自愈能力的机制本体。
声明已完整兑现,现在看它是如何被守住的。本节回答三个问题:为什么你删不掉一个 Pod;为什么节点宕机副本会自动补齐;扩缩容时集群内部到底动了什么。机制层面的地基打好,4.2 的滚动升级与 4.3 的负载变体都能顺势推导。
控制器的世界观极简:世界只有两个状态量——期望(spec,你写的)与现状(status,集群报的),两者相等则无事发生,不等则行动。拿副本守恒做推演:
期望:replicas = 3 现状:存活副本 = 3 → 差值为零,控制器休眠 现状:存活副本 = 2 → 差值 1,按模板补建 1 个 Pod 现状:存活副本 = 4 → 差值 -1,按序号移除 1 个多余 Pod
这段伪逻辑就是部署控制器的全部内核。它的精妙在于不问原因只看差值:副本少一个,可能是被你删了、可能是 OOM 死了、可能是整台节点失联——控制器不关心,补齐就是。这种"面向差值编程"的风格换来了极强的鲁棒性:任何原因导致的偏离,都会被同一个动作修复。
1.2 节 Pod 名字里那串哈希,现在可以兑现成完整解释。一个 Deployment 实际统治着一个小王朝:
看一眼现网的王朝结构:
kubectl get replicasets -n production -l app=orders-api # NAME DESIRED CURRENT READY AGE # orders-api-6d9f7c8b5 3 3 3 5d # orders-api-5c4b9d7f2 0 0 0 12d # 第二行是上一代 1.3.9 的 ReplicaSet:0 副本但保留,4.2 节回滚全靠它 kubectl get deployment orders-api -n production -o jsonpath='{.spec.replicas} {.status.readyReplicas}' # 3 3 期望 3 就绪 3:守恒成立
"删不掉的 Pod"现象顺手验证:
# 手动删除一个副本 kubectl delete pod orders-api-6d9f7c8b5-2vxk7 -n production # pod "orders-api-6d9f7c8b5-2vxk7" deleted # 几秒后再看:同名(同哈希后缀随机)新副本已经补上 kubectl get pods -n production -l app=orders-api # NAME READY STATUS RESTARTS AGE # orders-api-6d9f7c8b5-k8w2t 1/1 Running 0 8s # orders-api-6d9f7c8b5-9mjq4 1/1 Running 0 5d # orders-api-6d9f7c8b5-x3p2q 1/1 Running 0 5d
你删掉的瞬间,ReplicaSet 控制器算出差值为 1,立刻按模板补产。想让副本真正从 3 变 2,唯一正确的路径是修改声明(改 YAML 再 apply,或 kubectl scale)——声明是唯一的遥控器,一切绕过声明的操作都会被"纠正"回去。
节点级自愈是同一机制在更大尺度上的重演:节点失联后(第2章的复盘案例),节点控制器把该节点上的 Pod 标记为待终止,账面上"存活副本"随即减 1,部署控制器看到差值、补建新 Pod、调度器把它放到健康节点。全程没有人工,也没有组件互相喊话——自愈不是某个专门功能,而是差值收敛的副产品。
背景:晚高峰将到,容量预案要求提前把 orders-api 扩到 5 副本,团队想留下完整的操作与验证记录。
操作:改声明、验证账面、压测确认——
# 第一步:把 YAML 中 replicas 3 改为 5 后提交(推荐路径,声明可追溯) kubectl apply -f orders-deploy.yaml # deployment.apps/orders-api configured # 第二步:观察滚动窗口内的账面(几秒后) kubectl get deployment orders-api -n production # NAME READY UP-TO-DATE AVAILABLE AGE # orders-api 5/5 5 5 40s # 第三步:确认新副本的分布没有堆叠 kubectl get pods -n production -l app=orders-api -o wide --field-selector=status.phase=Running # 5 个副本分布在 4 台不同节点上(3.2 节的反亲和在此生效)
结果:扩容完成,压测吞吐上限提升约六成,READY 列从 3/3 平稳过渡到 5/5,期间错误率为零。
解读:READY 列的三段式读法——左值就绪数、右值期望数、AVAILABLE 实际可用数,是观察一切工作负载健康度的仪表盘。扩容期间左值小于右值属正常过渡;长期 5/4 则说明有一个副本探针不过,该按第7章手册排查,而不是盲目再扩容。
变式:流量有昼夜节律的应用适合 HPA(水平自动扩缩):声明按 CPU 利用率或自定义指标自动调整副本数,上下限写在声明里。HPA 改变的是 Deployment 的 replicas 字段,本质仍是"改声明",机制完全同构——这也是为什么 4.1 的地基值得打牢:自动扩缩不是新魔法,只是让机器替你改同一个字段。
⚠️ 常见坑:扩容前忘了确认节点池余量。副本扩到 5,账面资源不够,新副本全部 Pending,容量预案变成调度排队。扩容与节点容量是一对连体问题,第7章的资源治理会给出门槛检查清单。
💡 关键直觉:把控制器当成一名只认账本的执事——他从不听口头通知,也从不自行发挥;账本写什么,他就让现实变成什么。
副本守恒解决了"活着"的问题,下一节解决"换新"的问题:镜像版本从 1.4.2 升到 1.5.0,集群如何在不中断服务的前提下完成整体换代——以及一旦新版本有问题,如何一条命令退回来。