1、从"周五晚上的惊魂上线"说起

老式发布流程长这样:半夜所有人待命,运维手工敲命令,代码从 U 盘/共享盘拷到服务器,出问题立刻手动回滚——心跳加速、全员加班、出事靠人肉。

而高效团队的状态是:每天发布几十次,发布是件平淡无奇的小事。 差别就在于自动化。本课讲:持续交付(CD)与环境、流水线、灰度/蓝绿发布。

2、三种"持续":CI / CD / CD

这三个缩写容易混,用一句话分清:

持续集成 CI(Continuous Integration)
  代码一提交就自动构建 + 测试,早发现冲突
        ↓
持续交付 CD(Continuous Delivery)
  在 CI 基础上,自动把制品推到「可随时上线」的状态,
  但「上线」这一步由人**按按钮**触发
        ↓
持续部署 CD(Continuous Deployment)
  连「上线」也自动化,测试通过即自动上生产

关键区分:

  • CI 解决"代码能不能合"。
  • 持续交付:随时可发布,发布与否是业务决策。
  • 持续部署:自动发布,需要极强的测试与监控信心。
多数团队先做到持续交付(人工点最后一下),再逐步走向持续部署。

3、环境:代码流过的地方

一个规范的环境链路:

开发环境(Dev) → 测试环境(Test/QA) → 预发环境(Staging) → 生产环境(Prod)
   写代码          功能验证            模拟生产             真实用户

环境管理铁律:

原则说明
环境一致性各环境配置尽量一致(用 IaC/容器),否则"预发没问题、生产炸"
配置外置环境差异(数据库地址、密钥)放配置/环境变量,不进代码
预发≈生产预发要尽可能像生产(数据量、拓扑、配置),才有预演价值
生产最小权限生产访问严格管控、审计留痕

十二要素应用(12-Factor App) 里最相关的一条:在环境中存储配置——同样的制品,靠环境变量适配不同环境。

4、部署流水线(Pipeline)

一条完整的 CD 流水线长这样:

提交代码
   │
   ▼
① 构建 → ② 单元测试 → ③ 集成测试 → ④ 制品入库
   │
   ▼
⑤ 部署到测试环境 → ⑥ 自动化验收/E2E
   │
   ▼
⑦ 部署到预发 → ⑧ 人工审批 ──▶ ⑨ 部署到生产
                                    │
                                    ▼
                              ⑩ 健康检查/冒烟测试
                                    │
                        失败 ◀──────┴──────▶ 成功
                          │                    │
                          ▼                    ▼
                       自动回滚             观察监控
# GitHub Actions 示例(简版)
name: CD Pipeline
on:
  push:
    branches: [main]
jobs:
  build-test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: pip install -r requirements.txt
      - run: pytest                    # 测试不过,后面全不执行
      - run: docker build -t myapp:${{ github.sha }} .
      - run: docker push registry/myapp:${{ github.sha }}

  deploy-staging:
    needs: build-test                  # 依赖上一步成功
    environment: staging
    steps:
      - run: ./deploy.sh staging ${{ github.sha }}

  deploy-prod:
    needs: deploy-staging
    environment: production            # 配了人工审批
    steps:
      - run: ./deploy.sh production ${{ github.sha }}

流水线设计原则:

  • 快速失败:前面的门(构建/测试)先拦住问题,别把坏制品往后传。
  • 每一步可观察:谁失败、为什么失败,一眼可见。
  • 可重复:同一版本,重跑流水线结果一致。

5、发布策略:怎么把风险降到最低

直接替换(停机发布):简单,但有服务中断,不适合高可用系统。

蓝绿发布(Blue-Green):两套环境,切换流量:

        ┌── Blue(当前生产,v1)◀── 全部流量
负载均衡┤
        └── Green(新版本 v2,先部署好,测好)

切换:把流量从 Blue 切到 Green → 出问题秒切回 Blue
  • ✅ 秒级切换、秒级回滚。
  • ❌ 需要双倍资源。

灰度/金丝雀发布(Canary):先放一小撮流量给新版本:

v1(旧) ◀── 95% 流量
v2(新) ◀──  5% 流量   ← 观察错误率/延迟
        ↓ 观察期没问题
v1 ◀── 50%    v2 ◀── 50%
        ↓
v1 ◀── 0%     v2 ◀── 100%
  • ✅ 小范围试错,影响面可控;可按用户/地域/设备分批。
  • ❌ 需要流量切分能力与精细监控。

滚动发布(Rolling):逐台替换实例,不停服。

实例: [v1][v1][v1][v1]
   →  [v2][v1][v1][v1]   (替换一台,健康后再下一台)
   →  [v2][v2][v2][v2]

发布策略选择:

策略回滚速度资源成本适用
直接替换慢低内部小系统
蓝绿秒级高(双倍)关键系统、需快速回滚
灰度快(切流量)中用户量大的线上服务
滚动中低容器化集群

6、发布与回滚必须成对设计

任何没有回滚预案的发布都是赌博。

发布前:明确"怎么算成功"(健康检查、核心指标)
       明确"什么情况回滚"(错误率 > x%、P95 > y ms)
       明确"怎么回滚"(切流量 / 回滚镜像 / 数据库兼容)
发布后:冒烟测试 → 观察指标 → 确认稳定

数据库回滚是最难的部分:代码能秒回,数据迁移往往不可逆。

解法:让 schema 变更向后兼容。加字段先加可空的、改字段分两步(先双写、再切读)、删除字段延后到确认无人用。这样新旧代码能共存,回滚随时可行(第 31 课细讲)。

7、常见误区

误区问题正解
手工部署易错、不可复现流水线自动化
各环境制品不同"测过的"≠"上线的"同一制品走完全程
配置写死在代码里换环境就炸配置外置(环境变量)
没有回滚方案出事只能硬扛发布必配回滚
直接全量上线问题影响所有用户蓝绿/灰度/滚动
数据库变更不留退路回滚就丢数据向后兼容的迁移

8、动手实验 🎯

任务:为贯穿项目「团队任务清单」搭一条持续交付流水线。

  1. 分环境配置:用环境变量管理数据库地址等差异,让同一镜像能跑在不同环境。
  2. 写流水线(GitHub Actions / GitLab CI):提交 → 测试 → 构建 → 推制品,测试失败则阻断。
  3. 加人工审批门:生产部署设为需人工确认(environment protection)。
  4. 实现灰度发布:用一个反向代理(如 Nginx)把 10% 流量导向新版本,5 分钟后全量。
  5. 设计回滚:写一个 rollback.sh,一条命令切回上一版本;实测一次。
  6. 做一次向后兼容的迁移:给任务表加一个字段(先可空),验证新旧代码都能跑。
  7. 反思:如果发布根本不需要开"发布大会",你的团队还需要哪些能力?

下一课:上线发布:计划、回滚与变更管理。

9、今天你带走的三句话

  1. CI 管"能不能合",持续交付管"随时可发",持续部署管"自动发"。
  2. 同一制品走遍所有环境,配置外置,环境尽量一致。
  3. 发布与回滚成对设计;用蓝绿/灰度/滚动降低风险,数据库变更要向后兼容。

下一课:上线发布:计划、回滚与变更管理。

标签: 软件工程, 项目管理, 开发流程

添加新评论