文章
一次构建,按 digest 晋级:可回滚的交付流水线
一条参考交付路径:在 staging 测试的制品与生产中的完全相同,回滚就是重新部署上一个 digest。
示例均为通用的说明性内容,并非取自任何客户环境:请根据您自己的系统调整阈值和配置。
按环境重复构建的问题
为每个环境重新构建应用的流水线,测试的是一个制品,发布的却是另一个。依赖解析结果不同、基础镜像变了、构建参数有差异——于是生产中的版本从未在任何地方测试过。只构建一次,给制品一个不可变的标识,然后晋级这个标识。
参考路径
一条从提交到生产的通用路径。每个阶段要么把同一个制品传下去,要么将其拦下。
- 01提交带评审和必需检查的拉取请求。
- 02构建每次提交构建一次;推送镜像并记录其 digest。
- 03验证测试、依赖与镜像扫描、签名。
- 04Staging部署该 digest;运行冒烟测试和集成测试。
- 05生产同一个 digest,渐进式发布。
- 06观察由错误预算和告警决定:继续还是回滚。
用 digest,而不是标签
latest 或 v2 这样的标签是可变的;digest(sha256:…)是镜像内容的哈希值。部署清单应引用 digest,流水线通过修改这一个值来晋级某个环境——最好以提交到部署仓库的方式进行,这样每次发布都是经过评审、可撤销的变更。
# build once and record the digest
docker buildx build --push --metadata-file meta.json \
-t registry.example.com/api:"$GIT_SHA" .
DIGEST=$(jq -r '."containerimage.digest"' meta.json)
# promote: every environment receives the same digest
kustomize edit set image api=registry.example.com/api@"$DIGEST"
数据库变更:先扩展,再收缩
只有当数据库结构仍兼容上一个版本时,回滚代码才容易。把不兼容的迁移拆成多个步骤,每一步都与正在运行的代码兼容:先添加新列或新表,部署同时写入两者的代码,回填数据,切换读取,直到后续某个版本才删除旧结构。
渐进式交付与回滚
- 先发布到一部分流量或副本,并将错误率和延迟与当前版本进行比较。
- 把决策与 SLO 绑定:发布期间出现高消耗速率会自动停止晋级。
- 回滚就是重新部署上一个 digest——走同一条已验证的路径——而不是在压力下仓促写的热修复。
- 把配置和密钥放在镜像之外,让同一个制品可以在每个环境中运行。