Deployment 的滚动更新 (Rolling Update) 机制
Deployment 的滚动更新 (Rolling Update) 是 Kubernetes 中最常用、也是默认的部署更新策略。它的核心目标是在不中断服务(Zero Downtime)的情况下,将应用从一个版本平滑过渡到另一个版本。
以下是关于滚动更新机制的深度解析,包括原理、关键参数、流程以及注意事项。
1. 核心原理
滚动更新通过逐步替换的方式进行更新。Deployment 控制器会创建一个新的 ReplicaSet(副本集),然后逐步增加新 ReplicaSet 的 Pod 数量,同时逐步减少旧 ReplicaSet 的 Pod 数量,直到旧版本 Pod 全部消失,新版本 Pod 达到期望数量。
简单概括:
- 启动一个新的 Pod (v2)。
- 等待新 Pod 变为
Ready(就绪) 状态。 - 销毁一个旧的 Pod (v1)。
- 重复上述步骤,直到所有 Pod 更新完毕。
2. 关键配置参数 (strategy)
在 Deployment 的 YAML 文件中,spec.strategy 字段控制更新行为。
yaml
spec:
replicas: 10
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 25% # 最大激增数
maxUnavailable: 25% # 最大不可用数
这两个参数决定了更新的速度和稳定性:
A. maxSurge (最大激增数)
- 含义:在更新过程中,允许存在的 Pod 总数量超过
spec.replicas(期望副本数) 的最大值。 - 值:可以是绝对数字(如
2)或百分比(如25%)。 - 作用:决定了 K8s 可以“提前”创建多少个新 Pod。值越大,更新越快,但消耗的资源(CPU/内存)越多。
- 计算:如果 replicas=10, maxSurge=2,则更新期间最多可以有 12 个 Pod 同时运行。
B. maxUnavailable (最大不可用数)
- 含义:在更新过程中,允许处于“不可用”状态的 Pod 的最大数量。
- 值:可以是绝对数字(如
1)或百分比(如25%)。 - 作用:决定了在更新期间,最少有多少个 Pod 必须是可用的。值越小,服务越稳定,但更新速度可能变慢。
- 计算:如果 replicas=10, maxUnavailable=2,则更新期间至少要有 8 个可用的 Pod (10 - 2)。
3. 滚动更新的详细流程
假设我们有一个 Deployment:
replicas: 3maxSurge: 1maxUnavailable: 0(为了保证服务绝对稳定,不允许任何 Pod 不可用)
流程如下:
- 初始状态:ReplicaSet-V1 有 3 个 Pod,全部 Running。
- 触发更新:用户修改镜像版本。
- 创建新 RS:Deployment 创建 ReplicaSet-V2,初始副本数为 0。
- Scale Up (扩容):因为
maxSurge=1,Deployment 允许总数达到 4。ReplicaSet-V2 副本数变为 1。系统启动第 1 个新 Pod。 - Readiness Check (就绪检查):K8s 等待新 Pod 通过 Readiness Probe。
- Scale Down (缩容):一旦新 Pod 就绪,总可用 Pod 变成了 4 个。Deployment 将 ReplicaSet-V1 的副本数减为 2。销毁 1 个旧 Pod。
- 循环:
- RS-V2 扩容到 2 -> 等待就绪 -> RS-V1 缩容到 1。
- RS-V2 扩容到 3 -> 等待就绪 -> RS-V1 缩容到 0。
- 完成:ReplicaSet-V1 即使为 0 也会被保留(用于回滚),ReplicaSet-V2 成为主力。
4. 至关重要的配合机制:Readiness Probe
这是滚动更新不中断服务的关键!
如果没有配置 Readiness Probe (就绪探针),Kubernetes 会认为 Pod 一旦启动(Running 状态)就是可用的。
- 后果:如果你的应用启动需要 30 秒加载数据,但 K8s 在 Pod 启动第 1 秒就认为它 Ready 了,并立即杀掉旧 Pod,流量打到新 Pod 上就会报错(502/Connection Refused),导致服务中断。
正确做法:配置 Readiness Probe,确保新 Pod 真正能够处理流量后,K8s 才会继续滚动更新。
yaml
readinessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
此外,配合 minReadySeconds 字段使用效果更佳:
minReadySeconds: 10:Pod 变为 Ready 后,必须保持 Ready 状态 10 秒,才被视为真正的“可用”。这可以防止“启动即崩溃”的循环重启问题。
5. 常用命令操作
触发更新:
bashkubectl set image deployment/my-app nginx=nginx:1.16 # 或者直接 edit / apply yaml查看进度:
bashkubectl rollout status deployment/my-app暂停/恢复更新(用于金丝雀发布场景):
bashkubectl rollout pause deployment/my-app # 更新一部分后暂停,观察流量 kubectl rollout resume deployment/my-app # 没问题继续回滚(如果新版本有问题):
bashkubectl rollout undo deployment/my-app # 回滚到特定版本 kubectl rollout undo deployment/my-app --to-revision=2
6. 优缺点分析
优点
- 零停机:服务一直在线。
- 原生支持:无需额外工具,K8s 内置。
- 风险可控:通过
maxUnavailable和maxSurge控制更新节奏。
缺点
- 版本共存:在更新期间,集群中会同时存在 v1 和 v2 两个版本的应用。
- 注意:如果 v2 修改了数据库 Schema 且不向后兼容,可能会导致 v1 的 Pod 报错。应用必须设计为向后兼容。
- 流量控制弱:无法像 Istio 那样精确控制 1% 的流量去新版本,它是基于 Pod 数量的粗粒度负载均衡。
- 回滚慢:如果新版本有 Bug,回滚本质上是一次“反向的滚动更新”,需要时间。
总结
Kubernetes Deployment 的滚动更新通过双 ReplicaSet 控制和就绪探针(Readiness Probe)的配合,实现了平滑的版本迭代。理解 maxSurge 和 maxUnavailable 是调优更新速度和稳定性的关键。