CI、持续交付和持续部署经常被统称为 CI/CD,但三者解决的问题不同。设计流水线前先明确边界,才能避免“有 Jenkins 就算 DevOps”或“自动部署等于持续交付”的误区。
## 1. 持续集成(Continuous Integration)
持续集成强调开发者频繁把小变更合入共享主干,并通过自动化尽早发现问题。一个基本 CI 流程包括:
1. 拉取确定的源代码提交。
2. 恢复锁定版本的依赖。
3. 编译或构建。
4. 执行单元测试和静态检查。
5. 执行安全与许可证扫描。
6. 生成带唯一版本的产物。
7. 保存测试报告、构建元数据和产物摘要。
CI 的关键不是定时跑一次任务,而是反馈足够快。主干失败后应优先修复,而不是让更多变更继续叠加。
## 2. 持续交付(Continuous Delivery)
持续交付保证通过验证的软件始终处于可发布状态。生产发布可以由业务或变更负责人按需触发,但从产物到部署的过程已经自动化、可审计且可重复。
持续交付需要:
- 可重复构建和不可变产物。
- 自动化测试与质量门禁。
- 环境配置分离。
- 部署、验证和回滚自动化。
- 清晰的生产审批与权限边界。
- 从提交到生产的完整追踪关系。
## 3. 持续部署(Continuous Deployment)
持续部署在持续交付基础上更进一步:每个通过全部门禁的变更自动进入生产,不再等待人工发布决定。
它适合自动化成熟、测试可靠、架构可独立部署且有强可观测性的团队。强监管、高风险或需要业务择时的系统也可以采用持续交付,而不必追求全自动生产部署。
## 4. 最重要的原则:只构建一次
同一个源代码提交不应在测试、预发和生产分别重新编译。正确流程是:
```text
Commit
→ Build once
→ Test artifact
→ Publish artifact
→ Deploy to test
→ Promote same digest to staging
→ Promote same digest to production
```
重新构建会引入编译器、依赖、时间、基础镜像和网络仓库差异,导致“测试过的并不是最终上线的产物”。
容器镜像应使用摘要或不可变标签晋级:
```text
registry.example.com/app@sha256:...
```
不要把 latest 当作生产发布版本。
## 5. 环境差异如何处理
产物保持一致,环境差异通过受控配置注入:
- Config、Secret 和连接地址不写入镜像。
- 不同环境使用相同部署模板,仅替换明确的参数。
- 数据库变更使用版本化迁移脚本。
- 基础设施和策略配置进入版本控制。
- Secret 从专用系统动态获取,流水线日志不得打印明文。
“相同部署方式”不代表测试和生产资源完全相同,而是执行逻辑、模板和验证标准一致。
## 6. 一条推荐流水线
### 提交阶段
- 格式检查、单元测试、静态分析。
- Secret 检测、依赖与许可证扫描。
- 生成构建版本和变更记录。
### 构建阶段
- 在隔离、可复现环境中构建。
- 固定基础镜像和依赖版本。
- 生成 SBOM、签名和摘要。
- 上传制品库,不依赖工作目录继续流转。
### 验证阶段
- 使用真实产物执行集成、契约和端到端测试。
- 检查数据库迁移的向前与回滚路径。
- 扫描镜像和基础设施配置。
### 部署阶段
- 先部署到测试和预发。
- 执行 smoke test 与关键业务验证。
- 生产采用滚动、蓝绿或金丝雀策略。
- 根据错误率、延迟和业务指标决定继续或回滚。
## 7. 流水线既要统一,也要灵活
统一应集中在安全和可追踪的底线:
- 版本命名与产物元数据。
- 必需的安全、质量和合规门禁。
- 部署身份与权限控制。
- 日志、指标和审计格式。
- 回滚与变更记录。
灵活性则体现在语言、测试框架、构建器和部署目标。平台团队可提供 Java、Go、Python、前端和容器等模板,由应用团队在受控范围内扩展。
## 8. 失败处理
流水线失败必须留下清晰证据:阶段、提交、产物、环境、执行身份和错误摘要。可重试步骤应保证幂等,避免重复执行导致创建两份资源或重复数据库迁移。
推荐规则:
- 构建失败:不产生可晋级版本。
- 测试失败:保留报告,阻止后续环境。
- 部署失败:停止扩散并自动收集诊断信息。
- 健康指标恶化:自动暂停或回滚。
- 回滚失败:升级为事件响应并按预案处置。
## 9. 常见反模式
- 在生产服务器上拉代码并编译。
- 测试和生产使用不同脚本。
- 手工修改已部署配置,版本库没有记录。
- 多个 Job 重复实现凭证和部署逻辑。
- 只看 Job 绿色,不验证用户功能。
- 把密码写进参数、镜像或构建日志。
- 流水线只有成功路径,没有暂停和回滚。
## 10. 验收清单
一条成熟流水线应能回答:
- 这个版本来自哪个提交和评审?
- 使用了哪些依赖、工具链和基础镜像?
- 哪些测试与安全检查通过?
- 当前环境运行的产物摘要是什么?
- 谁在何时批准或触发了生产发布?
- 哪些指标证明发布健康?
- 如何在几分钟内回到上一个稳定版本?
## 参考资料
- https://dora.dev/capabilities/continuous-delivery/
- https://sre.google/sre-book/release-engineering/
- https://sre.google/workbook/canarying-releases/