深色模式
发布策略:蓝绿 / 金丝雀 / 滚动
摘要:本文面向需要在 Kubernetes 上安全交付应用版本的 SRE / 平台工程师。对比滚动更新、蓝绿、金丝雀三种策略的原理与适用边界,重点拆解它们在不同流量层(原生 Service、Ingress-Nginx、服务网格)的实现差异,并覆盖回滚、失败模式与成本权衡。Argo Rollouts 作为渐进式交付控制器贯穿说明。
适用版本与前提
- Kubernetes:v1.25+(Deployment
RollingUpdate为原生能力) - 流量层:Ingress-Nginx ≥ 1.x / Istio / Linkerd / SMI(金丝雀/蓝绿依赖)
- 渐进式交付:Argo Rollouts 2.x 或 Flagger
- 前提:已配置就绪探针(readinessProbe),否则任何策略都不可靠
背景与问题
原生 Deployment 默认 RollingUpdate 只保证"不中断地换 Pod",但不控制流量比例、不能按指标自动暂停/回滚、对"新版本是否真的健康"只信 readinessProbe。在高吞吐生产环境,这意味着:新版本若有延迟或错误率问题,滚动更新会把它逐步铺开到全部流量,爆炸半径等于 100%。于是引出两类更可控的策略——蓝绿(瞬间切全部流量)与金丝雀(按百分比渐进)。
探针是前提,不是可选项
无论哪种策略,readinessProbe 决定 Pod 何时接流量,livenessProbe 决定何时重启。没有正确探针,蓝绿/金丝雀的"健康检查"形同虚设。本文假设探针已正确配置。
三种策略对比
| 维度 | 滚动更新 | 蓝绿 | 金丝雀 |
|---|---|---|---|
| 流量控制粒度 | 无(按 Pod 比例自然迁移) | 瞬间全切 | 按权重渐进 |
| 回滚速度 | 再滚动一次(慢) | 切回旧 Service(快) | 缩金丝雀(快) |
| 资源开销 | 低(1 份) | 高(2 份并行) | 中(部分双份) |
| 自动基于指标决策 | 否 | 否(需手动切) | 是(配 Analysis) |
| 爆炸半径 | 大(铺满才停) | 小(切前可测绿环境) | 最小(先小流量) |
| 实现复杂度 | 原生 | 中 | 高(需流量层支持) |
策略一:滚动更新(RollingUpdate)
原生 Deployment 的默认策略,最省资源,但控制力最弱。
yaml
apiVersion: apps/v1
kind: Deployment
spec:
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 25% # 最多超出期望的 Pod 比例
maxUnavailable: 0 # 更新期间不允许不可用(保证容量)1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
滚动更新的盲区
它只靠 readinessProbe 决定 Pod 是否"可用",无法做"延迟/错误率超阈值就停"。若新版本以低错误率劣化(而非彻底崩溃),探针仍可能通过,问题被铺满全量。这正是需要金丝雀的原因。
策略二:蓝绿(Blue-Green)
维护两套完全相同环境,绿(新)就绪后通过切换 Service 的 selector 瞬间把流量从蓝切到绿。出问题瞬间切回。
yaml
# 蓝(当前)与绿(新)是两个独立 Deployment,标签分别为 version: blue / green
# 对外 Service 选择器在切换时改 version 值
apiVersion: v1
kind: Service
metadata:
name: myapp
spec:
selector:
app: myapp
version: blue # 切换时改为 green 即完成蓝绿切换1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
实现要点:蓝绿依赖"同一 Service 选择器切到另一组 Pod"。Argo Rollouts 的 blueGreen 策略会自动管理 active/preview 两个 Service 并做自动切换。
生产危险
蓝绿切换瞬间,旧 Pod 若立即缩容,其上的长连接/在途请求会断。生产应预留"旧版本缩容宽限期"或借助连接 draining。另外,若应用有状态(如本地缓存、未共享的 session),切回蓝不一定能恢复,需保证无状态或状态外置。
策略三:金丝雀(Canary)
把新版本先暴露给一小部分流量,逐级放量,并基于指标(错误率、延迟、QPS)自动决策继续还是回滚。这是生产高变更频率场景的首选。
实现差异(关键):金丝雀的本质是"按比例切流量",而 K8s 原生 Service 是轮询负载均衡、无法按权重切流量。因此金丝雀必须借助上层流量控制:
| 流量层 | 金丝雀实现方式 | 精度/限制 |
|---|---|---|
| 原生 Service | 无法直接做按权重金丝雀(只能靠副本数近似,误差大、不可靠) | 不推荐用于真金丝雀 |
| Ingress-Nginx | 用 nginx.ingress.kubernetes.io/canary: "true" + canary-weight 注解,按请求比例分流到 canary Ingress | 基于请求数近似,HASH/会话可能不均;仅七层 HTTP |
| 服务网格(Istio / Linkerd / SMI) | 用 VirtualService / TrafficSplit 按权重精确分流,支持基于 header 的精细路由 | 最精确,支持 L7 路由、按用户/header 分流;需引入 mesh 复杂度 |
版本相关
Ingress-Nginx 的 canary 注解在 0.30+ 可用;Istio 的 VirtualService 权重分流需注入 sidecar。具体字段名随版本变化,生产前核对目标版本的 Ingress-Nginx / Istio 文档。
Argo Rollouts 金丝雀示例(用 stable/canary 两个 Service + 步骤权重):
yaml
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: myapp
spec:
replicas: 10
strategy:
canary:
stableService: myapp-stable
canaryService: myapp-canary
trafficRouting:
nginx: # 或 istio / smi,取决于你的流量层
stableIngress: myapp-ingress
steps:
- setWeight: 10 # 金丝雀占 10% 流量
- pause: { duration: 5m } # 暂停观察
- setWeight: 25
- pause: { duration: 5m }
- setWeight: 50
- pause: {} # 无限暂停,等人工确认
- setWeight: 100
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: myapp:1.2.01
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
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
Argo Rollouts 还能把 AnalysisTemplate(查询 Prometheus 等指标)挂到步骤上:指标超阈值自动 abort + 回滚,实现"无人值守渐进交付"。这与原生滚动更新"无指标决策"形成根本差异。
回滚与清理
- 滚动更新:
kubectl rollout undo deployment/myapp(再滚动一次,较慢)。 - 蓝绿:把 Service selector 切回旧版本(秒级);Argo Rollouts blueGreen 直接
kubectl argo rollouts abort。旧版本保留便于即时切回。 - 金丝雀:缩掉 canary 权重到 0(
setWeight: 0)或 abort Rollout;Argo Rollouts 在 Analysis 失败时自动回滚。
回滚不等于数据回滚
以上全是针对"应用版本"的回滚。若新版本做了不兼容的数据库 schema 变更,应用回滚后仍会读写新 schema,可能继续报错。生产必须配合向后兼容的 schema 演进(expand/contract)或 feature flag,避免"版本能回滚、数据回不去"。
失败模式
- 探针误判:readinessProbe 过松,坏版本被判定健康,金丝雀指标未触发就已放量。
- 流量层不一致:Ingress-Nginx canary 是基于请求数的近似,若客户端长连接或 sticky session,权重失真。
- 状态未外置:蓝绿/金丝雀假设无状态;若有本地状态,切流/回滚会导致数据丢失或错乱。
- 指标盲区:只监控错误率没监控延迟/饱和度,慢版本被放过。
成本与权衡
- 蓝绿资源峰值接近 2 倍(双份全量),但回滚最快、最安全,适合低频大版本。
- 金丝雀资源随权重线性增加(如 10% 金丝雀只需约 1.1 倍),且能控爆炸半径,适合高频迭代。
- 滚动更新最省资源但最不可控,适合内部/低风险服务或配合完善探针的非核心链路。
选型经验判断
核心链路、高频发布 → 金丝雀(配 Argo Rollouts + 指标 Analysis);低频重大版本、追求秒级回滚 → 蓝绿;内部工具、低风险 → 原生滚动更新。不要为所有服务一刀切上最复杂的方案,复杂度本身也是运维成本。
FAQ
Q:原生 Service 能做金丝雀吗? A:不能精确做。Service 是轮询、无权重;所谓"调副本数近似"误差大且不可控。真正的金丝雀必须依赖 Ingress-Nginx canary 注解或服务网格的流量权重。
Q:金丝雀和蓝绿能组合吗? A:可以。常见模式是"先金丝雀放量验证,再蓝绿式全量切换",Argo Rollouts 的 blueGreen + Analysis 即可实现"绿环境先接少量流量验证再全切"。
参考资料
- Argo Rollouts Concepts: BlueGreen / Canary(官方文档),访问日期:2026-10-08。
- Ingress-Nginx Canary Annotations(官方文档),访问日期:2026-10-08。
- Kubernetes Deployment Strategies(官方文档),访问日期:2026-10-08。
- Argo Rollout and Deployment Strategies(Dzone 实践综述),访问日期:2026-10-08。