灰度发布策略(一):蓝绿部署
说到灰度发布,蓝绿部署是我最常用的策略之一。简单来说,它就像给系统准备了两套独立的环境——一套蓝色(当前运行的老版本),一套绿色(你要发布的新版本)。两套环境并存,但同一时刻只有一套在承接用户流量。
核心思想:一次切换,而非逐步放量。你完全可以在绿色环境上验证好,然后瞬间把流量从蓝色切到绿色。
蓝绿部署的原理
我个人习惯把蓝绿部署看作是「全量切换」的一种优雅实现。它的架构其实很清晰:
- 蓝色环境(Blue):当前的生产环境,运行着旧版本。
- 绿色环境(Green):预配好的新版本环境,与蓝色环境完全隔离。
- 负载均衡器/路由层:流量切换的核心开关。
你可能会问,那这两套环境怎么共享数据?嗯,这里要注意,数据库和持久化存储通常是共享的。所以,新版本在数据库 schema 上的兼容性就变得非常关键。我在项目中遇到过,就是因为没处理好数据库迁移,导致切到绿色环境后发现数据对不上,不得不紧急回滚。
避坑指南:我曾经接手过一个项目,蓝绿环境各自连了独立的数据库,结果切换后发现数据断层了。记住,蓝绿环境通常共享数据层,应用层才是隔离的。
蓝绿部署的优点
说白了,蓝绿部署最大的好处就是「快」和「安全」。我罗列几个关键点:
- 切换极快:全量切换只是路由层改个配置,几秒钟就完成了。
- 回滚秒级:出问题了?把路由切回蓝色环境就行。本质上就是一次「反向切换」。
- 两套环境独立验证:绿色环境可以提前部署好,QA 团队可以提前在上面跑完整的回归测试。
- 零停机发布:切换瞬间用户几乎无感知。
蓝绿部署的缺点
当然,没有银弹。蓝绿部署也有明显的短板,我来分享一下我的真实体会:
- 资源成本翻倍: 你要同时维护两套一模一样的环境,硬件或云资源开销几乎翻倍。我建议只在关键业务上使用,或者通过 K8s 弹性缩容来降低成本。
- 数据库兼容性风险: 如果新版改了数据库 schema,切换时很难保证平滑。我曾经就踩过这个坑,回滚时发现老版本读不了新数据,不得不做数据回滚,整个过程非常痛苦。
- 不适合逐步观察: 它不能像金丝雀发布那样,先放 1% 的流量观察一段时间。说白了,蓝绿是「全部切换」或「全部不切换」,没有中间状态。
适用场景
根据我的经验,蓝绿部署在下面这些场景特别有用:
| 适用场景 | 原因 |
|---|---|
| 前端静态资源 / Serverless 服务 | 切换快,回滚极简单,几乎没有有状态依赖。 |
| 无状态微服务 | 只要数据层兼容,随便切。 |
| 重大版本发布 | 需要做全量回归测试和预发布验证。 |
| 有严格合规要求的场景 | 需要完整的审计日志和可追溯的切换动作。 |
回滚实现:这是重点
蓝绿部署的回滚,在我看来也是它最出彩的地方。回滚其实就是「把流量切回蓝色环境」。你想想看,绿色环境出了问题,我们只要把路由器的目标地址指向蓝色环境就行。
具体来说,我一般这么做:
# 假设你用 Nginx 做负载均衡器
# 当前 flow 指向 green
upstream myapp {
server green-cluster.example.com:8080;
}
# 回滚时,只需要把配置文件改回 blue
upstream myapp {
server blue-cluster.example.com:8080;
}
# 然后重新加载 Nginx
nginx -s reload
注意:如果你在 CI/CD 里自动化回滚,我建议把回滚作为一个独立 Pipeline。比如,在 Pipeline 里加一个 Rollback 按钮。我曾经见过有人手动改配置,结果改错了把两个环境都搞崩了。
在 CI 工具(比如 Jenkins 或 GitLab CI)里,回滚 Pipeline 可以是这样的:
stages:
- deploy_blue
- deploy_green
- switch_to_green
- rollback_to_blue # 独立的回滚阶段
rollback_to_blue:
stage: rollback_to_blue
script:
- echo "开始回滚到蓝色环境..."
- kubectl set image deployment/myapp-v1 -n production myapp=myapp:v1.2
- kubectl patch service myapp -n production -p '{"spec":{"selector":{"version":"v1.2"}}}'
when: manual # 手动触发,避免误操作
CI 分层支持实战
在 CI 里支持蓝绿部署,我建议做到 3 层:
- 构建层: 每次代码合并 → 自动构建两套环境的镜像(蓝/绿)。绿色镜像打上
v2.0标签,蓝色镜像保持stable标签。 - 部署层: 自动部署到绿色环境,并触发自动化冒烟测试。
- 切换层: 只有负责人手动确认后,Pipeline 才会执行流量切换。
个人经验:我一般会在切换层之前加一个「Post-deploy health check」步骤。比如,检查绿色环境的 /healthz 接口是否返回 200,并且响应时间在正常范围内。如果不达标,自动中止切换,并通知相关人员。
# 在 pipeline 中加一个简单的健康检查步骤
check_health:
stage: verification
script:
- for i in 1 2 3 4 5; do
STATUS=$(curl -s -o /dev/null -w "%{http_code}" http://green-cluster.example.com/healthz);
if [ "$STATUS" -eq 200 ]; then
echo "Green 环境健康检查通过";
exit 0;
fi;
sleep 5;
done;
- echo "Green 环境健康检查失败,自动中止发布";
- exit 1;
这样三层下来,每次发布都像走一条标准流程。出错?一键回滚到蓝色环境,蓝绿部署的这份安全感,真的很踏实。