蓝绿/灰度/金丝雀发布:流量切换、回滚、A/B 测试
上线新版本不是「全量推送」那么简单——四种发布策略各有取舍。这篇是蓝绿 / 灰度 / 金丝雀 / A/B 测试的架构、流量切换机制、回滚方案,以及 Feature Flag、Argo Rollouts、LaunchDarkly 工具实战。
四种发布策略对比
策略
流量切换
回滚速度
风险
适用
蓝绿
100% 一次性
秒级(切回蓝)
高
大版本
金丝雀
1% → 5% → 25% → 100%
分钟级(切流量)
低
通用
灰度(Feature Flag)
按用户/特征分流
秒级(改 flag)
低
新功能
A/B 测试
按用户分组对比
改动大
低
实验
策略 1:蓝绿发布(Blue/Green) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 @startuml title "Blue/Green Deployment" actor "Users" as Users participant "Load Balancer" as LB participant "Blue Env\n(v1.0)" as Blue participant "Green Env\n(v2.0)" as Green database "Blue DB" as BlueDB database "Green DB" as GreenDB == 部署 v2.0 到 Green == Users -> LB : ① 100% 流量 LB -> Blue : ② 路由到 Blue Blue -> BlueDB : ③ 读 v1.0 BlueDB --> Blue : ④ 数据 note over Green 部署 v2.0 到 Green 不接流量 内部测试 end note Green -> GreenDB : ⑤ 数据迁移 / 双写测试 note over LB : 切换流量 LB -> Green : ⑥ 100% 流量切到 Green Green -> GreenDB : ⑦ 读 v2.0 == 回滚(秒级) == LB -> Blue : ⑧ 一秒切回 Blue(紧急情况) note right of LB DNS / nginx upstream / k8s service selector 一行命令切换 end note @enduml
蓝绿部署要点 :
两套完整环境 — 资源 ×2
共享数据库 — 两版本兼容同一 schema
切换瞬时 — DNS / LB 一行命令
回滚秒级 — 切回蓝即可
策略 2:金丝雀发布(Canary) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 @startuml title "Canary Deployment - Gradual Rollout" actor "Users" as Users participant "Load Balancer\n(istio / nginx)" as LB participant "v1.0 (95% traffic)" as V1 participant "v2.0 (5% traffic)" as V2 database "DB" as DB == Step 1: 1% canary == Users -> LB : ① 1000 用户访问 LB -> V2 : ② 1% → 10 用户到 v2.0 LB -> V1 : ③ 99% → 990 用户到 v1.0 note over V2 监控 v2.0: - 错误率 < 1%? - p99 延迟 < 500ms? - CPU 正常? end note V2 -> DB : ④ 读写 V1 -> DB : ④ 读写 DB --> V2 : ⑤ 数据 DB --> V1 : ⑤ 数据 == Step 2: 增加流量 == LB -> V2 : ⑥ 5% (50 用户) LB -> V1 : ⑦ 95% (950 用户) note over LB 监控稳定持续 10 分钟 流量提升到 25% end note == Step 3: 25% canary == LB -> V2 : ⑧ 25% (250 用户) LB -> V1 : ⑨ 75% (750 用户) == Step 4: 100% 全量 == LB -> V2 : ⑩ 100% 切到 v2.0 V1 --> [*] : ⑪ 旧版本下线 note over LB 异常时: LB -> V1 : 紧急切回 100% v1.0 秒级回滚 end note @enduml
金丝雀关键 :
渐进流量提升 — 1% → 5% → 25% → 50% → 100%
监控对比 — v1.0 vs v2.0 错误率/延迟/CPU
快速回滚 — 切流量即可,不动 pod
策略 3:Feature Flag(灰度) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 @startuml title "Feature Flag Toggling" actor "User A" as UA actor "User B" as UB actor "User C" as UC participant "App" as App participant "Feature Flag Service" as FF database "Flag Config" as Config UA -> App : ① 请求 UB -> App : ② 请求 UC -> App : ③ 请求 App -> FF : ④ evaluate "new_checkout" FF -> Config : ⑤ 查规则 note right of FF 规则: - User A,B → enabled - User C → disabled - 灰度 50% end note Config --> FF : ⑥ 规则 FF --> App : ⑦ User A: enabled FF --> App : ⑧ User B: enabled FF --> App : ⑨ User C: disabled App -> App : ⑩ User A 走新 checkout (v2 代码路径) App -> App : ⑪ User B 走新 checkout App -> App : ⑫ User C 走老 checkout (v1) @enduml
Feature Flag 类型 :
Boolean flag — 全开 / 全关
用户白名单 — 内部员工 / beta 用户
百分比灰度 — 50% 用户
按特征 — 国家 / 设备 / 订阅等级
A/B 实验 — 不同变体
LaunchDarkly / Unleash 实战 :
1 2 3 4 5 6 7 8 9 10 11 12 const LaunchDarkly = require ('ldclient-node' );const ldClient = LaunchDarkly .init ('sdk-key-xxx' );ldClient.identify ({ key : userId, email : user.email }); const enabled = await ldClient.variation ('new-checkout' , user, false );if (enabled) { return newCheckoutFlow (cart); } else { return oldCheckoutFlow (cart); }
策略 4:A/B 测试 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 @startuml title "A/B Test Experiment Flow" actor "User" as U participant "App" as App participant "Experiment Service" as Exp database "Experiment Config" as Conf participant "Analytics" as Ana U -> App : ① 访问 App -> Exp : ② get variant "checkout_color" Exp -> Conf : ③ 查实验配置 note right 实验: - 50% → variant A (蓝色按钮) - 50% → variant B (绿色按钮) 跟踪指标: - 点击率 - 转化率 end note Conf --> Exp : ④ 规则 Exp --> App : ⑤ variant = "B" App -> App : ⑥ 渲染绿色按钮 (variant B) U -> App : ⑦ 点击绿色按钮 App -> Ana : ⑧ 事件 {variant:B, event:click} note over Ana : 7 天后分析 Ana -> Ana : ⑨ 统计: B 转化率 +15% (p<0.01) @enduml
A/B 测试要点 :
对照组 — variant A(原版)
实验组 — variant B(新设计)
样本量计算 — 要 p<0.05 显著性,需要足够流量
单一变量 — 只改一个东西,否则归因不清
跟踪指标 — 主指标 + 副指标 + 护栏指标
蓝绿 vs 金丝雀 vs Feature Flag 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 @startuml title "Strategy Selection Decision" start :新版本需要发布; if (改动是否兼容数据库 schema) if (兼容) :继续; else :先做 schema 迁移(expand-migrate-contract); end end :新功能 vs 性能修复?; if (新功能) if (用户范围) if (内部测试) :Feature Flag (白名单); else if (5% 灰度) :Feature Flag (5%); else if (全量) :Feature Flag (100%) + 直接发布; end end else if (高风险改动) :蓝绿(测试完整流量); else :金丝雀(1% → 5% → 25% → 100%); end end :监控指标稳定后完成; stop @enduml
Argo Rollouts 金丝雀实战 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 apiVersion: argoproj.io/v1alpha1 kind: Rollout metadata: name: user-service spec: replicas: 10 selector: matchLabels: app: user-service strategy: canary: steps: - setWeight: 5 - pause: {duration: 5m } - setWeight: 25 - pause: {duration: 5m } - setWeight: 50 - pause: {duration: 10m } - setWeight: 100 - pause: {duration: 5m } canaryService: user-service-canary stableService: user-service-stable trafficRouting: istio: virtualService: name: user-service-vs analysis: templates: - templateName: success-rate - templateName: latency startingStep: 2 args: - name: service-name value: user-service template: metadata: labels: app: user-service spec: containers: - name: user-service image: user-service:v2.0 --- apiVersion: argoproj.io/v1alpha1 kind: AnalysisTemplate metadata: name: success-rate spec: metrics: - name: success-rate interval: 30s successCondition: result[0] >= 0.95 failureLimit: 3 provider: prometheus: address: https://prometheus.internal query: | sum(rate(http_requests_total{status!~"5..",service="user-service"}[5m])) / sum(rate(http_requests_total{service="user-service"}[5m]))
Argo Rollouts 行为 :
部署 v2 到 canary pod
调整 Istio VirtualService 流量
每步暂停 N 分钟
跑 Prometheus 分析
失败自动 abort,回滚到 v1
成功自动 next step
数据库 schema 兼容性 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 @startuml title "Backward-Compatible Schema Migration" database "DB v1.0" as V1 database "DB v1.5 (compatible)" as V15 database "DB v2.0" as V2 == Step 1: 添加新列(不删旧列) == V1 -> V15 : ① ALTER TABLE ADD COLUMN new_field VARCHAR(50) note right v1.0 应用: 读 old_field v2.0 应用: 读 new_field (fallback to old_field) end note == Step 2: 双写 == V15 -> V15 : ② 应用双写 old_field + new_field note right v2.0 写 new_field 旧应用仍读 old_field end note == Step 3: 回填 == V15 -> V15 : ③ UPDATE SET new_field = old_field note right 历史数据 new_field 也填上 end note == Step 4: 切换读取 == V15 -> V15 : ④ v2.0 读 new_field == Step 5: 清理 == V15 -> V2 : ⑤ DROP COLUMN old_field note right 安全删除,旧版本不再用 end note @enduml
核心原则 :永远先加后删 ——v2.0 部署时仍兼容 v1.0 的代码。
回滚决策树 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 @startuml title "Rollback Decision Tree" start :监控告警; if (错误率 > 5%) :立即回滚(蓝绿切回); stop elseif (错误率 1-5%) :暂停灰度; if (10 分钟内恢复) :继续; else :回滚; end elseif (错误率 < 1% 但延迟高) :检查是否有上游依赖问题; if (上游问题) :上游恢复后继续; else :暂停或回滚; end elseif (业务指标异常) :检查是否实验组问题; if (新版本引入) :Feature Flag 关闭; else :不回滚; end end stop @enduml
实战踩坑
数据库 schema 不兼容 — v2.0 部署时 v1.0 代码连不上。强制 expand-migrate-contract 流程 。
金丝雀 pod 没接流量 — Istio VirtualService 没配对。canaryService / stableService 都要配 。
Feature Flag 没清理 — 100% 启用后 flag 还在代码里。定期审计 + 工具强制清理 。
A/B 测试样本不够 — 流量小,结果不显著。用 power analysis 算最低样本量 。
回滚太慢 — 金丝雀每步手动操作。用 Argo Rollouts 自动回滚 。
回滚导致数据不一致 — v2.0 写了数据,v1.0 读不到新字段。双写兼容期 。
监控盲区 — 只看 HTTP 状态码,看不到业务错误。业务埋点 + 错误聚合 。
Feature Flag 服务挂了 — 整个 app 加载 flag 超时。fallback 到默认值 + 本地缓存 。
决策树 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 要发布什么? ├─ 全量发布新版本 → 蓝绿(高风险) / 金丝雀(标准) ├─ 灰度新功能 → Feature Flag ├─ 实验验证 → A/B 测试 └─ 紧急修复 → 蓝绿 + 立即切回 风险等级? ├─ 低(纯前端 / 性能优化) → Feature Flag 直接启用 ├─ 中(后端逻辑) → 金丝雀 └─ 高(数据库迁移 / 架构改动) → 蓝绿 + 完整测试 回滚要求? ├─ 秒级 → 蓝绿 ├─ 分钟级 → 金丝雀 + 自动化 └─ 可延迟回滚 → Feature Flag(下次发布清理)
最小可行 :Feature Flag (Unleash 自部署) + 金丝雀手动。生产级 :Argo Rollouts + Prometheus 分析 + LaunchDarkly(商业)。
记住 :没有零风险发布 ,只有低风险发布 + 快速回滚 。监控 + 自动化 + 数据兼容 是三个核心。新版本上线当天盯监控 2 小时 ,别只发完就走。