← 中文资源

简体中文版本

滚动更新卡住时让部署失败

用带超时的 kubectl rollout status 作为流水线门禁,排查卡住的 ReplicaSet 并回滚,而不是让流程静默通过。

阅读英文原文

概述

kubectl apply 只等待 API Server 接受对象,不会等待 Pod 创建、调度或就绪。把 apply 当作成功的流水线可能显示绿色,而所有新 Pod 都卡在拉取镜像,服务仍运行旧版本且没有任何失败记录。kubectl rollout status 会阻塞直到 Deployment 报告完成,超时后以非零退出码结束,这正是流水线需要的信号。

步骤

  1. 在同一个步骤中应用清单并等待滚动完成:
kubectl apply -f k8s/ -n prod
kubectl rollout status deployment/payments -n prod --timeout=240s
  1. 等待失败时先收集状态与事件,再决定回滚:
kubectl describe deployment/payments -n prod | sed -n '/Conditions/,$p'
kubectl get events -n prod --sort-by=.lastTimestamp | tail -20
  1. 回滚并等待上一个 revision 就绪:
kubectl rollout undo deployment/payments -n prod
kubectl rollout status deployment/payments -n prod --timeout=240s
  1. 在触达集群前确认镜像引用存在:
docker manifest inspect ghcr.io/acme/payments:1.5.0 > /dev/null

验证

正常发布时该步骤应在启动时间内完成并返回 0;把镜像 tag 改成不存在的值后,步骤应在超时后失败,而不是继续执行后续发布。失败时 Conditions 通常直接给出 ImagePullBackOff 或副本不可用等原因,回滚后第二次 rollout status 应成功。若超时但 Pod 实际在运行,说明就绪探针未通过,应先检查探针路径与启动时间。

注意事项

  • rollout status 只保证 Deployment 完成,不保证业务流量正确,需要配合冒烟检查。
  • 超时时间应基于实测启动时间,过长会掩盖故障,过短会误判健康发布。
  • 回滚也必须在同一流水线中等待完成,否则会掩盖二次失败。
  • 镜像存在性检查可以把最常见的失败提前到 apply 之前。
  • 部署成功后仍需检查 updatedReplicas,避免新旧 Pod 混杂运行。