4. ReplicaSet 与 Deployment 自愈机制:期望状态与当前状态协调、滚动更新与回滚中的自愈行为
4.1 核心自愈模型:期望状态与当前状态的协调循环
Kubernetes 中所有控制器(Controller)都遵循一个核心设计模式:期望状态(Desired State)与当前状态(Current State)的持续协调。ReplicaSet 和 Deployment 的自愈能力正是这一模式的直接体现。
当用户通过 YAML 声明一个期望的 Pod 副本数(例如 replicas: 3)后,控制器管理器中的 ReplicaSet Controller 或 Deployment Controller 会启动一个永不停止的协调循环(Reconciliation Loop)。该循环通过 Informer 机制监听 API Server 上的资源变化,一旦检测到当前状态与期望状态出现偏差,立即触发自愈动作。
协调循环的核心逻辑:
- 观察(Observe):从 API Server 获取当前 ReplicaSet 的 Pod 列表及状态。
- 比较(Compare):计算当前可用 Pod 数量与期望副本数的差值。
- 行动(Act):如果 Pod 数不足,则创建 Pod;如果 Pod 数过多,则删除多余的 Pod;如果 Pod 状态异常(如 CrashLoopBackOff),则等待或重建。
自愈的本质:自愈不是“修复”一个损坏的 Pod,而是通过删除异常 Pod 并创建新 Pod 来恢复期望的副本数。Pod 本身是“不可变”的,自愈发生在控制器层面。
4.2 ReplicaSet 的自愈行为
ReplicaSet 是 Kubernetes 中最基础的 Pod 副本管理控制器。它的自愈行为直接且高效:
| 故障场景 | 当前状态 | 期望状态 | 自愈动作 |
|---|---|---|---|
| Pod 被手动删除 | 2 个 Pod | 3 个 Pod | 立即创建 1 个新 Pod |
| Pod 所在 Node 宕机 | 2 个 Pod(1 个不可达) | 3 个 Pod | 在健康 Node 上创建 1 个新 Pod |
| Pod 进入 CrashLoopBackOff | 3 个 Pod(1 个异常) | 3 个 Pod | 等待重启策略;若持续失败,保留异常 Pod 但不再创建新 Pod(副本数已满足) |
| Node 资源不足 | 2 个 Pod(调度失败) | 3 个 Pod | 持续重试调度,直到资源释放或 Pod 被驱逐 |
注意:ReplicaSet 只保证副本数量,不保证 Pod 的健康状态。如果 Pod 处于 CrashLoopBackOff 但数量满足期望值,ReplicaSet 不会主动删除该 Pod。这是 Deployment 在 ReplicaSet 之上提供的增强自愈能力。
4.3 Deployment 的自愈机制:滚动更新与回滚
Deployment 在 ReplicaSet 的基础上增加了版本管理和声明式更新能力。当 Pod 模板(如镜像版本)发生变化时,Deployment 会触发滚动更新(Rolling Update),并在更新过程中持续自愈。
4.3.1 滚动更新中的自愈行为
滚动更新不是一次性替换所有 Pod,而是逐步创建新版本 Pod,同时销毁旧版本 Pod。在这个过程中,自愈机制依然在运行:
- 新 Pod 启动失败:如果新版本 Pod 无法通过 Readiness Probe,Deployment 会暂停滚动更新,保留旧版本 Pod 继续服务,直到问题解决。
- 旧 Pod 被意外删除:在滚动更新期间,如果某个旧 Pod 被意外删除,ReplicaSet 会立即创建新的旧版本 Pod 来维持期望副本数,直到该 ReplicaSet 被缩容到 0。
- Node 故障:滚动更新过程中如果 Node 宕机,Deployment 会重新调度受影响的 Pod,无论是新版本还是旧版本。
滚动更新参数控制自愈行为:
maxSurge:更新期间允许超出期望副本数的最大 Pod 数(默认 25%)。值越大,更新速度越快,但资源消耗也越大。maxUnavailable:更新期间允许不可用 Pod 的最大数量(默认 25%)。值越小,服务可用性越高,但更新速度越慢。
4.3.2 回滚中的自愈行为
当滚动更新导致服务异常时,Deployment 支持回滚(Rollback)到之前的稳定版本。回滚本身也是一种自愈行为:
| 回滚触发条件 | 自愈动作 | 关键参数 |
|---|---|---|
| 新版本 Pod 持续 CrashLoopBackOff | 自动回滚到上一个 ReplicaSet 版本 | --record 记录变更原因 |
| Readiness Probe 连续失败 | 滚动更新暂停,等待人工介入或自动回滚 | progressDeadlineSeconds(默认 600s) |
手动执行 kubectl rollout undo |
立即触发回滚,创建旧版本 ReplicaSet | --to-revision 指定回滚版本 |
回滚的自愈原理:回滚本质上是创建一个新的 ReplicaSet(使用旧版本的 Pod 模板),然后执行一次反向的滚动更新。Deployment 的 Revision History 保留了最多
revisionHistoryLimit 个版本(默认 10),确保可以回滚到任意历史版本。
4.4 自愈行为对比:ReplicaSet vs Deployment
| 特性 | ReplicaSet | Deployment |
|---|---|---|
| 副本数自愈 | ✅ 立即创建/删除 Pod | ✅ 通过 ReplicaSet 实现 |
| Pod 模板更新 | ❌ 不支持(需手动删除重建) | ✅ 滚动更新 |
| 版本回滚 | ❌ 不支持 | ✅ 支持多版本回滚 |
| 更新暂停/恢复 | ❌ 不支持 | ✅ kubectl rollout pause/resume |
| 进度超时自愈 | ❌ 不适用 | ✅ progressDeadlineSeconds 超时后自动回滚 |
| Pod 健康检查联动 | ❌ 仅保证数量 | ✅ 结合 Readiness Probe 控制流量 |
4.5 实战验证:观察自愈行为
以下命令可以帮助你实时观察 ReplicaSet 和 Deployment 的自愈过程:
# 1. 创建一个 Deployment
kubectl create deployment nginx --image=nginx:1.25 --replicas=3
# 2. 观察 Pod 创建过程
kubectl get pods -w
# 3. 手动删除一个 Pod,观察自愈
kubectl delete pod <pod-name>
# 你会看到 ReplicaSet 立即创建一个新 Pod
# 4. 触发滚动更新
kubectl set image deployment/nginx nginx=nginx:1.26
# 5. 观察滚动更新过程
kubectl rollout status deployment/nginx
# 6. 模拟更新失败(使用不存在的镜像)
kubectl set image deployment/nginx nginx=nginx:bad-image
# 7. 观察 Deployment 暂停并回滚
kubectl rollout undo deployment/nginx
生产建议:
- 始终为 Deployment 配置
progressDeadlineSeconds,避免更新卡死。 - 使用
maxSurge=25%和maxUnavailable=25%作为默认值,平衡速度与可用性。 - 启用
--record记录变更原因,方便回滚时追溯。
4.6 本章小结
- ReplicaSet 和 Deployment 的自愈基于期望状态与当前状态的协调循环,这是一个永不停止的反馈系统。
- ReplicaSet 提供副本数自愈,但无法处理 Pod 模板变更和版本管理。
- Deployment 在 ReplicaSet 之上提供滚动更新和回滚能力,更新过程中自愈机制持续生效。
- 滚动更新通过
maxSurge和maxUnavailable控制自愈行为,progressDeadlineSeconds提供超时自愈保障。 - 回滚是 Deployment 最重要的自愈手段之一,能够快速恢复服务到稳定版本。