本节摘要:持续集成(CI)频繁合并并自动验证代码;持续交付(CD)确保制品随时可发布;持续部署(CDP)在门禁通过时自动触达生产。本节用三条可运行的 GitHub Actions 最小流水线对比三者边界,并说明加速发布、提高质量、降低风险等总体目标。
阅读完本节,你应当能够:
动手优先:下面三段 yaml 的唯一差别是生产部署是否自动。建议 fork 到你的仓库,观察 Actions 页各 job 的绿/红状态。
流水线 A — 纯 CI(到测试为止)
name: ci-only on: [push] jobs: build-test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - run: pip install -r requirements.txt pytest - run: pytest -q
流水线 B — 持续交付(制品可发布,生产手动)
name: cd-manual-prod on: push: branches: [main] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - run: docker build -t myapp:${{ github.sha }} . - run: docker push registry.example.com/myapp:${{ github.sha }} deploy-prod: needs: build runs-on: ubuntu-latest environment: production # 需人工 approve steps: - run: kubectl set image deploy/myapp app=registry.example.com/myapp:${{ github.sha }}
流水线 C — 持续部署(main 合并即上生产)
name: cdp-auto on: push: branches: [main] jobs: build-deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - run: docker build -t myapp:${{ github.sha }} . - run: kubectl apply -f k8s/ - run: kubectl rollout status deploy/myapp --timeout=300s
跑完对照:A 停在测试;B 在 environment: production 处等人点 approve;C 无人工 gate,rollout 失败即红线。
CI 要求开发者每天多次将代码集成到共享主干,每次集成都触发自动化构建与测试。Martin Fowler 2006 年归纳的核心思想:尽早、频繁集成,快速发现冲突。
| 实践 | 流水线体现 |
|---|---|
| 频繁提交 | trunk-based,短生命周期分支 |
| 自动化构建 | Maven package、npm build |
| 自动化测试 | 单元+集成,PR 必过 |
| 快速反馈 | 10 分钟内出结果 |
CD 在 CI 之上保证:任意时刻都能可靠部署到生产。是否实际部署由业务决定——通常是手动触发或审批 gate。Jez Humble 强调「可发布状态」而非「已发布状态」。
CDP 将 CD 的自动化延伸到生产:通过所有门禁的变更自动上线。Amazon、Netflix 等高频发布团队接近此模式,前提是测试覆盖率、监控与回滚能力足够强。
| 目标 | 可度量指标 | 典型工具信号 |
|---|---|---|
| 加速发布周期 | 部署频率、Lead Time | DORA 四项指标 |
| 提高软件质量 | 缺陷逃逸率、覆盖率 | SonarQube、pytest-cov |
| 降低发布风险 | 变更失败率、MTTR | PagerDuty、Rollout 状态 |
| 增强协作 | PR 评审周期 | GitHub/GitLab MR 统计 |
| 提升效率 | 手工部署次数 | 部署工单量 |
| 更快反馈 | commit 到红灯时间 | CI 平均时长 |
⚠️ 常见坑:把 CD 和 CDP 混为一谈向管理层承诺「全自动上线」——金融、医疗等行业常需人工审批,应明确为 CD 而非 CDP。
💡 关键直觉:三者是自动化深度的递进,不是互斥选型。很多团队对内部服务做 CDP、对核心账务做 CD,并行不悖。
| 因素 | 倾向 CD | 倾向 CDP |
|---|---|---|
| 监管审批 | 必须 | 不适用 |
| 测试覆盖率 | 60–80% | 85%+ 且 flaky 极低 |
| 回滚能力 | 30 分钟内 | 5 分钟内自动 |
| 用户基数 | 千万级 | 可灰度小流量 |
| 团队规模 | 10–50 人 | 50+ 有 SRE |
pipeline { agent any stages { stage('Build') { steps { sh 'mvn -B package -DskipTests' } } stage('Test') { steps { sh 'mvn test' } } } post { failure { mail to: 'team@corp.com', subject: "Build ${env.BUILD_NUMBER} FAILED" } } }
与 GitHub Actions 的 on: [push] 同理:提交即触发,失败即邮件——这是 CI 的「心跳」。
问: nightly build 算 CI 吗?
答:频率太低。CI 强调至少每日多次集成;nightly 只能算定时构建,集成冲突发现太晚。
问:只有 Docker 构建没有测试算 CI 吗?
答:算「弱 CI」。没有测试门禁,主干健康度不可验证,CD 无从谈起。
Google DORA(DevOps Research and Assessment)团队通过数万次调研归纳四项关键指标,成为衡量 CI/CD 成熟度的行业基准:
| DORA 指标 | 精英团队 | 低绩效团队 | 与 CI/CD 关系 |
|---|---|---|---|
| 部署频率 | 按需多次/天 | 月~季 | CDP 直接提升 |
| 变更前置时间 | < 1 小时 | 1~6 月 | CI 缩短构建测试 |
| 变更失败率 | 0~15% | 46~60% | 测试门禁降低 |
| 服务恢复时间 MTTR | < 1 小时 | 1 周~1 月 | 自动回滚缩短 |
我们服务过的一家 SaaS 团队:部署频率从每月两次提到每天八次后,单次变更行数中位数从 800 行降到 60 行——不是开发变懒,而是 CI 让「小步提交」成为阻力最小的路径。变更失败率从 22% 降到 6%,主要得益于 PR 必过 pytest 与 staging E2E,而非「更小心」。
违反第三条最常见:全量 E2E 塞进 CI 导致 45 分钟 pipeline,团队开始 git push --no-verify。正确做法是把 E2E 移到 CD staging stage,CI 只保留 unit+integration。
英文里 Continuous Delivery 和 Continuous Deployment 都叫 「CD」,中文教程有时混译。记忆法:Delivery = 交付能力(可发布),Deployment = 部署动作(已发布)。Jez Humble《Continuous Delivery》书名用的是 Delivery——强调「随时能发」而非「已经发了」。
Azure Pipelines 用 stages 划分 CI/CD:
stages: - stage: CI jobs: [{ job: build_test, steps: [...] }] - stage: CD dependsOn: CI condition: succeeded() jobs: [{ job: deploy, steps: [...] }]
CircleCI 用 workflow 串 job——概念相同,语法不同。选型时看现有生态:GitHub 项目优先 Actions,自建 K8s 跑 GitLab Runner 常见,银行遗留系统 Jenkins 仍多。
下一节 1.2 我们讨论 DevOps 文化与 CI/CD 的关系——为什么光有 yaml 不够,还需要协作方式变革。