Skip to content

CI/CD 发布复盘

这篇记录不是单纯讲“怎么发布”,而是讲发布为什么会在某一步卡住,以及怎样把这条链路变得更可靠。CI/CD 最怕的不是慢,而是链路里某一段变成了黑盒:看不到、说不清、也回不去。

事故背景

某次发布过程中,构建、推送镜像和部署动作看起来都执行成功了,但服务就是没有按预期更新。最开始容易怀疑的是应用本身,但往往真正的问题在流程中间层:

  • 镜像 tag 没有更新
  • 拉取到了旧镜像
  • 部署脚本没有等待 rollout 完成
  • 环境变量被错误覆盖
  • 健康检查没有正确反映新版本状态

这类问题最麻烦的地方在于,流水线“绿了”,但用户看到的还是旧状态。

流水线结构

一个比较清楚的发布链路通常会拆成几段:

  1. 代码检查
  2. 构建测试
  3. 镜像打包
  4. 推送制品
  5. 部署到目标环境
  6. 验证新版本

如果每一步都只是执行命令,而没有明确产物和状态,后面排障时会非常难回看。

这次的问题

排查时先看的是最末端症状:

  • 发布成功但页面没有变化
  • 容器没有重建
  • 新镜像没有被拉取
  • 回滚逻辑也没有触发

这个时候最重要的是不要急着重跑流水线,而是先确认发布对象到底有没有被更新。很多时候问题不是“部署没执行”,而是“执行了但没换到新版本”。

镜像和标签

最常见的坑就是镜像标签策略太宽松。比如固定使用 latest,或者 tag 复用太频繁,就很难判断当前线上到底跑的是哪个版本。

更稳妥的方式是:

  • 每次构建生成唯一 tag
  • tag 里带上 commit 或构建号
  • 部署时明确指定版本
  • 发布后记录实际运行中的镜像 ID
bash
docker images | head
kubectl get deploy -o wide
kubectl describe pod <pod-name>

部署同步问题

如果流水线没有等待部署完成,就会出现“脚本成功,但服务还没切换完”的错觉。这个问题在 Kubernetes 和 Docker Compose 里都会出现,只是表现不同。

在 Kubernetes 中,建议至少等待:

bash
kubectl rollout status deploy/app -n app

在 Docker Compose 场景中,则至少要确认:

bash
docker compose ps
docker compose logs -f app

如果不看状态就直接认为发布成功,后面一旦出现短暂失败,排查会非常困难。

验证策略

发布后的验证最好分成两层:

技术验证

  • 容器或 Pod 是否起来
  • 健康检查是否通过
  • 日志是否有异常
  • 新版本镜像是否已生效

业务验证

  • 首页是否正常打开
  • 核心 API 是否可用
  • 页面资源是否完整
  • 延迟和错误率是否正常

技术验证只能说明“系统启动了”,业务验证才能说明“真的对外可用了”。

复盘后修正

这次复盘后,最值得改的不是单点命令,而是整个发布链路的可观察性:

  • 每次发布记录版本号
  • 部署后强制做一次健康检查
  • 出问题时自动保留最近日志
  • 回滚命令写入固定脚本
  • 发布完成后输出明确结果

如果流程足够清晰,后面就算是临时值班的人接手,也不会因为找不到上下文而手忙脚乱。

结论

CI/CD 的成熟程度,往往不是看它自动化了多少步骤,而是看每一步失败时能不能快速定位。真正好用的流水线,应该让发布变成一件可观察、可解释、可回退的事情。

Focused notes for DevOps, Linux and Kubernetes.