Kubernetes 滚动发布与回滚:保障 CI/CD 变更安全
滚动发布、暂停继续与回滚的标准动作,以及一次真实发布事故的完整复盘。
自动部署不等于自动成功。每次发布都要回答三个问题:怎么发、怎么确认发完了、发坏了怎么快速回来。这篇文章讲 Deployment 的 rollout 机制和我在一次真实事故里的处理过程。
#rollout 是什么:新版本怎么替换旧版本
Deployment 的 strategy.type: RollingUpdate 决定了替换节奏,两个参数:
maxUnavailable:更新过程中最多允许几个旧副本不可用。maxSurge:最多允许超出期望副本数几个新副本。
maxUnavailable: 0, maxSurge: 1 是保守配置:先起一个新 Pod,readiness 通过后才摘一个旧 Pod,循环直到全部替换。它保证容量不降,代价是更新期间资源占用翻倍;追求快就用 maxUnavailable: 1, maxSurge: 1。
#发布的标准动作:打标记、更新、等 rollout
# 1. 打 change-cause,历史里能看出每次改了什么
kubectl annotate deployment/demo-api \
kubernetes.io/change-cause="release 1.2.0: fix order rounding"
# 2. 触发更新
kubectl set image deployment/demo-api api=ghcr.io/acme/demo-api:1.2.0
# 3. 等 rollout 完成(超时即失败)
kubectl rollout status deployment/demo-api --timeout=180skubectl rollout status 会一直等到新副本全部就绪或超时。超时返回非零退出码,在 CI 里等于发布失败,这是自动化发布里最重要的一个动作。别用「sleep 30 然后查 Pod」这种笨办法,rollout status 是标准答案。
发布过程用这个命令看实时状态:
kubectl get pods -l app=demo-api -w
kubectl rollout history deployment/demo-api
# 输出里 revision 从 1 递增,CHANGE-CAUSE 显示每次的标记#暂停和继续:灰度观察的时机
kubectl rollout pause 可以在发布中间停住,让一部分流量先跑一段时间:
kubectl rollout pause deployment/demo-api
# 观察新版本 Pod 的错误率、延迟
kubectl rollout resume deployment/demo-api但 pause 的语义是「暂停 Deployment 的控制器协调」,不是「只放 10% 流量」。真正按比例灰度是 Service 多版本加权(如 Flagger/Argo Rollouts 的 canary),rollout pause 只适合「先更新一半再手动继续」的粗粒度场景。别把两者混了。
#回滚:快速回到上一版
# 回滚到上一个 revision
kubectl rollout undo deployment/demo-api
# 回滚到指定 revision(先 history 查编号)
kubectl rollout undo deployment/demo-api --to-revision=3
kubectl rollout status deployment/demo-api --timeout=180s回滚后同样要 rollout status 确认恢复。我经历过的一次真实事故流程:
- 发布 1.2.0,readiness 探针配的是新接口路径,老路径被移除。
- 上线后新版本 Pod 全部不就绪,滚动卡住(
maxUnavailable: 0保住了旧版,线上暂时没挂)。 kubectl rollout history看到 revision 5 是 1.2.0,kubectl rollout undo --to-revision=4秒回旧版。- 之后排查:
kubectl logs <旧Pod> --previous看新版本为什么没起来——原来是配置里引用了不存在的配置项。
回滚救急,但根因必须继续查。只 undo 不修根因,下次发布同一个坑还会炸。回滚后要做的事:保留当时的 Pod 日志(--previous)、记录 revision、开问题单。
#更稳妥的防线:发布前多一道校验
- Deployment 里配
progressDeadlineSeconds(默认 600s),滚动超过这个时间没完成,rollout status会报progress deadline exceeded,便于自动化捕获卡死。 - 生产环境用 GitHub Environments 审批 + 手动确认,别让「merge 即发布」直接进 prod。
- 发布窗口留足
terminationGracePeriodSeconds和 preStop,旧 Pod 优雅退出,连接不中断。
#经验
发布能力是「回滚能力」决定的。每次发布前我都会确认三件事:change-cause 打了、rollout status 有超时、undo 命令在非生产演练过。等真出事的时候,你不想第一次用 kubectl rollout undo。
写于 2026 年 8 月 6 日
- 栏目
- 技术文章
- 约
- 3 分钟
- 字数
- 2.2K
- 阅读
- 222
本文为原创记录,转载请注明出处。如果这篇替你省了时间,欢迎留言说说你踩到的坑。
同题 · related
- DevOps 运维中 AI 那些事把 AI 放进运维的真实分工:从服务器硬件、网络、GPU、内存,到虚拟化、Kubernetes、应用构建、CI/CD、可观测性、资源分配,再到 AI 自身的部署与算力调度。讲清楚哪些活它能接、边界划在哪、以及我踩过的那些坑。
- ArgoCD 实战:用 GitOps 把 CI/CD 部署搬进 Kubernetes从安装、Application 声明到 App of Apps 与 CI 配合,把 GitOps 部署体系在 Kubernetes 上落地,并复盘真实事故。
- Kubernetes Helm 配置:用 values 管理多环境发布用 Helm 管理多环境发布:模板化消除重复,values 承载差异,保持 Chart 直白可维护。
留言 · remarks
00 条还没有留言,来说点什么吧。