Kubernetes 滚动更新通过在更新过程中逐步替换旧版本 Pod,结合就绪探针(Readiness Probe)和 PodDisruptionBudget(PDB)等机制,确保始终有足够数量的实例处理请求,从而实现真正意义上的不停机发布新版本。
滚动更新如何保持服务不中断:核心机制解析
滚动更新的本质是让新版本 Pod 像波浪一样依次替换旧版本,整个过程对用户请求完全透明,要做到这一点,需要几个关键组件协同工作。
ReplicaSet 与 Pod 的逐步替换
每个 Deployment 背后管理着一个或多个 ReplicaSet,当你发起滚动更新时,控制器会创建一个新版本的 ReplicaSet,然后逐步增加新 Pod 副本数,同时减少旧 ReplicaSet 的副本数,这个节奏由 maxSurge 和 maxUnavailable 两个参数控制,业内专家指出,默认情况下这两个参数都设置为 25%,意味着更新过程中最多允许超出期望副本数 25%,同时最多允许 25% 的 Pod 不可用,这种配置在大多数场景下能平衡速度与稳定性。
就绪探针与存活探针的协作
滚动更新依赖的就绪探针(Readiness Probe)是真正决定流量切换的关键,新 Pod 启动后,只有通过就绪探针检测,才会被加入 Service 的 Endpoint 列表接收流量,旧 Pod 在终止前也会等待一段时间,确保正在处理的请求完成,存活探针(Liveness Probe)则负责检测 Pod 是否正常运行,如果探测失败,控制器会重启 Pod,避免因代码问题导致整个更新卡住。
PodDisruptionBudget 保证最小可用副本数
PodDisruptionBudget(PDB)是滚动更新时的保护层,它定义了一个集合中最小可用或最大不可用的 Pod 数量,你可以设置 minAvailable: 3,确保在任何时刻至少有三个 Pod 处于运行状态,当滚动更新配合 PDB 时,控制器会主动放慢退出旧 Pod 的速度,避免因一次性终止过多 Pod 导致服务降级,据统计,在生产环境中配置 PDB 的团队,更新失败率显著低于未配置的团队。
生产环境滚动更新配置:从参数到最佳实践
理解了机制后,我们直接看如何配置一个安全高效的滚动更新策略,很多新手容易忽略参数间的相互影响,导致更新时出现短暂中断。
maxSurge 与 maxUnavailable 参数详解
这两个参数决定滚动更新的速度与资源占用。
- maxSurge:更新时允许超出期望副本数的最大 Pod 数,可以是绝对数字或百分比,
25%或2,如果设置过大,可能瞬间创建过多 Pod,加大集群资源压力。 - maxUnavailable:更新时允许同时不可用的最大 Pod 数,同样支持百分比,设置过小会导致更新过程拖长,但能保证更稳定的服务容量。
常见实践是将 maxSurge 和 maxUnavailable 都设置为 1,尤其对于有状态服务或关键业务,这样可以确保每次只更新一个 Pod,最大限度降低风险,对于无状态、弹性好的服务,可以适当提高比例以加快发布速度。

滚动更新操作的完整命令示例
假设你有一个名为 nginx-web 的 Deployment,想将镜像版本从 19 升级到 21。
# 触发滚动更新 kubectl set image deployment/nginx-web nginx=nginx:1.21 # 实时查看更新状态 kubectl rollout status deployment/nginx-web # 如果更新出现问题,立即暂停 kubectl rollout pause deployment/nginx-web # 问题解决后恢复 kubectl rollout resume deployment/nginx-web # 查看历史修订版本 kubectl rollout history deployment/nginx-web # 回滚到上一个版本 kubectl rollout undo deployment/nginx-web
在执行 set image 后,Deployment 会自动开始滚动更新,无需手动操作 Pod 创建或删除。
如何验证滚动更新是否成功
验证不仅仅是看 Pod 状态,还需要确认流量是否正常切换到新版本。
- 检查 Pod 状态:
kubectl get pods -w观察新旧 Pod 的创建和终止过程。 - 检查 Endpoint 变化:
kubectl get endpoints <service-name>确保新 Pod 的 IP 被正确加入,旧 Pod 的 IP 逐步移除。 - 模拟请求测试:用 curl 或压测工具访问 Service,观察响应是否正常,以及版本号是否更新。
- 查看日志:
kubectl logs -l app=<app-name> --tail=50对比新旧 Pod 的日志输出,确认新版本代码没有报错。
滚动更新与蓝绿部署:场景化选择指南
在选型时,不少团队会在滚动更新和蓝绿部署之间犹豫,两者各有优劣,适合不同场景。
两种部署策略的核心差异
- 滚动更新:逐步替换,新旧版本共存一段时间,资源消耗平稳,但无法保证所有流量瞬间切换到新版本。
- 蓝绿部署:维护两套完整环境,切换时一次性将流量从旧环境(蓝)导向新环境(绿),切换瞬间完成,但需要双倍资源。
适用场景对比:流量特征与资源成本
| 维度 | 滚动更新 | 蓝绿部署 |
|---|---|---|
| 资源成本 | 低,仅需额外 25% 左右资源 | 高,需要两套完整集群 |
| 回滚速度 | 较慢,需逐步回退 | 极快,直接切换回旧环境 |
| 流量切换粒度 | 逐个 Pod 迁移 | 一次性全量切换 |
| 适合业务 | 无状态、对延迟不敏感 | 有状态、需要全量验证 |
对于大多数 Web 应用和微服务,滚动更新是更经济的选择,而一旦涉及数据库 Schema 变更或需要灰度观察,蓝绿部署或结合流量路由的滚动更新会更合适。
混合使用:滚动更新+蓝绿部署的进阶方案

部分团队会在 Kubernetes 中通过 Ingress 或 Service Mesh 实现混合策略,利用 Istio 的流量权重管理,先创建新版本的全部 Pod,但只切分 10% 流量到新版本,类似蓝绿部署的缓慢切换,这种方式既保留了滚动更新的资源效率,又获得了蓝绿部署的灰度能力,这需要额外引入服务网格组件,复杂度较高。
滚动更新常见问题与回滚策略:如何应对更新失败
不管你准备得多充分,更新失败的可能性始终存在,掌握快速诊断和回滚的方法,是生产环境运维的必备技能。
更新卡住或 Pod 无法启动的处理
滚动更新卡住通常由以下原因导致:
- 就绪探针配置错误:新 Pod 始终无法通过检测,导致 ReplicaSet 一直等待,此时可以检查探针的路径、端口和超时时间。
- 资源不足:集群无法调度新 Pod,更新停滞。
kubectl describe pod <pod-name>可以查看调度失败原因。 - 镜像拉取失败:新镜像不存在或不可访问,检查镜像仓库地址和凭据。
- PDB 限制:PDB 设置过紧,旧 Pod 无法被删除,新 Pod 无法创建,可以临时调整 PDB 或暂停更新。
遇到卡住时,最安全的方式是先用 kubectl rollout pause 暂停更新,然后逐一排查原因,修复后再恢复。
回滚操作的标准流程
回滚是发布失败的兜底手段,Kubernetes 默认保留最近 10 个修订版本,你可以随时回退到任意版本。
# 查看历史版本 kubectl rollout history deployment/nginx-web # 回滚到上一个版本 kubectl rollout undo deployment/nginx-web # 回滚到指定版本 kubectl rollout undo deployment/nginx-web --to-revision=2
执行 undo 后,Deployment 会重新创建一个旧的 ReplicaSet,并开始反向滚动更新,整个过程与正向更新类似,同样受到 maxSurge 和 maxUnavailable 约束,因此回滚也是平滑的。
利用 kubectl rollout 命令管理发布历史
除了 history 和 undo,rollout 子命令组还提供了 status 和 restart 等实用功能。
kubectl rollout status:持续输出更新进度,直到成功或失败。kubectl rollout restart:不更新镜像,直接重启所有 Pod,常用于重载配置或清理异常状态。kubectl rollout history --revision=<n>:查看某个版本的详细信息,包括镜像版本和配置。
建议在 CI/CD 流水线中集成 rollout status 的等待逻辑,确保发布流程在自动化场景下也能感知更新结果。
不同云环境下的滚动更新实践差异
虽然 Kubernetes 本身是标准化的,但各大云服务商在托管集群中的实现细节有所不同,需要根据实际环境调整配置。
简米云 ACK:自动注入 sidecar 与滚动更新

简米云容器服务(ACK)默认开启了集群自动注入 Sidecar 的功能,例如日志采集、监控 Agent 等,这些 Sidecar 容器会影响滚动更新的启动速度,因为就绪探针需要等待所有容器就绪,建议在 Deployment 中显式定义 readinessProbe 的 initialDelaySeconds 和 periodSeconds,为 Sidecar 初始化留出足够时间。
AWS EKS:使用 Node Group 与滚动更新的配合
在 AWS EKS 中,如果节点组需要升级,推荐先更新节点组再触发应用滚动更新,否则可能出现 Pod 被调度到新节点但旧节点还未下线的问题,EKS 的 VPC CNI 插件对 Pod 的 IP 分配有较大延迟,滚动更新时应注意 maxSurge 不要设置过大,避免 IP 耗尽导致 Pod 启动失败。
自建 Kubernetes 集群的滚动更新注意事项
自建集群通常不会自动处理负载均衡器或 DNS 的更新,你需要确保滚动更新过程中,Service 的 Endpoint 更新与后端负载均衡器、DNS 记录同步,当使用 MetalLB 暴露服务时,滚动更新后可能需要手动清理旧 Pod 的 ARP 缓存,建议在滚动更新脚本中加入 kubectl get endpoints 的等待逻辑,直到所有旧 Pod 的 IP 移除、新 Pod 的 IP 稳定后,再认为更新完成。
Kubernetes滚动更新常见问题解答
滚动更新期间如何处理长连接?
滚动更新默认不会强制中断已有连接,但旧 Pod 终止时会进入 Terminating 状态,等待 preStop 钩子执行完毕,如果你的应用处理 WebSocket 或 gRPC 长连接,建议在容器中设置 preStop 钩子,优雅关闭连接池,比如发送一个关闭信号并等待几秒,在 Service 层面使用 externalTrafficPolicy: Local 避免流量经过不健康的节点,但注意这会损失负载均衡的均匀性。
滚动更新速率如何控制?
滚动更新速率由 maxSurge 和 maxUnavailable 共同决定,但更精细的控制可以通过 progressDeadlineSeconds 实现,该参数定义在更新进度停滞多久后标记为失败,默认是 600 秒,如果你希望更新更保守,可以加大这个数值,并结合 minReadySeconds 确保新 Pod 稳定运行一段时间后才被视为就绪,设置 minReadySeconds: 30 会让新 Pod 在就绪探针成功后等待 30 秒才被用于替换旧 Pod,有效规避瞬态问题。
滚动更新与 HPA 冲突怎么办?
滚动更新时,Pod 的 CPU 和内存使用率可能短暂升高,导致 HPA 误判需要扩容,而扩容又会与滚动更新争夺资源,解决方法是确保 HPA 的 behavior 配置中 scaleDown 部分有 stabilizationWindowSeconds,避免频繁缩容,在滚动更新期间可以临时暂停 HPA 降级,或者使用 kubectl rollout pause 先暂停更新,等 HPA 稳定后再恢复,对于深度结合的 CI/CD 系统,建议在发布流水线中先暂停 HPA 自动缩放,发布完成后恢复。