一、金丝雀发布概述
1.1 什么是金丝雀发布?
金丝雀发布(Canary Release)是一种渐进式部署策略,通过逐步将生产流量从旧版本迁移至新版本,结合实时指标验证,在最小化风险的前提下完成版本迭代。其核心逻辑如下:
-
流量分层:初始阶段仅将小比例流量(如 5%)路由至新版本,剩余流量仍由旧版本处理。
-
指标验证:监控新版本的关键指标(成功率、延迟、错误率),确认符合预期后逐步扩大流量比例。
-
自动化决策:基于预设阈值自动推进或回滚,降低人工干预成本。
技术价值:
-
风险可控:异常仅影响部分用户,快速隔离问题。
-
精准验证:结合业务指标(如交易成功率)而非单纯基础设施健康状态。
-
资源高效:无需双版本全量部署,节省计算资源。
1.2 金丝雀发布与蓝绿发布的差异
金丝雀发布适合高风险迭代、核心业务认证。蓝绿发布适合简单应用快速全量发布。
二、Argo Rollouts 能力解析
接下来我们聚焦 Argo Rollouts,是如何落地金丝雀发布策略并提供增强能力的。
2.1 核心能力
1.精细化流量控制
-
百分比权重控制:支持渐进式流量分配(如 5% → 50% → 100%),确保发布过程平滑过渡。
-
基于请求头的精准路由:可按特定 Header(如 X-User: beta)实现灰度测试,满足特定用户群验证需求。
2.多维监控与自动化决策
-
内置监控集成:支持与 Prometheus、Datadog 等主流监控系统无缝集成。
-
指标阈值配置:可定义关键业务指标,(如错误率 < 1%、响应时间 < 500ms)
-
自动回滚机制:当指标超出阈值时,自动触发回滚。
3.分阶段发布策略
可配置多步骤验证流程(示例):
steps:
- setWeight: 20 # 第一阶段:20%流量
- pause: {} # 手动确认后继续
- setWeight: 50 # 第二阶段:50%流量
- pause: {duration: 30s} # 自动暂停监控
- setWeight: 100 # 全量发布
2.2 与原生 Deployment 的差异
三、金丝雀发布实战
使用 Argo Rollouts 搭配 Ingress-NGINX 实现金丝雀发布,实现流量按比例逐步迁移、暂停验证、自动推进的渐进式发布策略。
多维度验证目标
-
流量按照预设比例,逐步分流至新旧版本
-
支持通过请求 Header 实现精准流量控制
-
通过可视化 Dashboard 实时跟踪发布状态
环境准备 可以看其他K8S基础介绍的相关文章
3.1 项目结构
canary-deploy/
├── canary-rollout.yaml # 定义金丝雀策略
├── service-stable.yaml # 稳定版 Service(全流量入口)
├── service-canary.yaml # 金丝雀版 Service(灰度流量入口)
└── ingress-nginx.yaml # Ingress 权重路由配置
文件说明:
canary-rollout.yaml
使用 Argo Rollouts 定义金丝雀发布流程,包括流量权重控制、阶段发布和暂停机制。
service-stable.yaml
稳定版服务,默认承载全流量。
service-canary.yaml
金丝雀版服务,按权重接收灰度流量。
ingress-nginx.yaml
定义入口规则,配合 Argo Rollouts 实现流量路由与控制。
3.2 配置文件
1.Rollout 配置
canary-rollout.yaml
核心作用:定义金丝雀发布的阶段策略、流量权重等,及与 Ingress 的联动配置。是实现渐进式流量控制的核心资源对象。
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: canary-demo
labels:
app: canary-demo
spec:
replicas: 1 # 启动一个副本用于测试
selector:
matchLabels:
app: canary-demo
template:
metadata:
labels:
app: canary-demo
spec:
containers:
- name: canary-demo
image: argoproj/rollouts-demo:blue # 示例镜像,可替换为业务镜像
imagePullPolicy: Always
ports:
- name: http
containerPort: 8080
protocol: TCP
resources:
requests:
memory: 32Mi
cpu: 5m
strategy:
canary: # 金丝雀发布策略
canaryService: service-canary # 金丝雀服务
stableService: service-stable # 稳定服务
canaryMetadata:
labels:
deployment: canary # 金丝雀版本的标签
stableMetadata:
labels:
deployment: stable # 稳定版本的标签
trafficRouting:
nginx:
stableIngress: canary-demo # 关联 ingress-nginx.yaml 中的 Ingress
additionalIngressAnnotations:
canary-by-header: X-Canary # 支持按 Header 精准控制流量
steps: # 金丝雀发布阶段控制
- setWeight: 20 # 第一阶段:20% 流量进入金丝雀
- pause: {} # 暂停,需要手动操作继续
- setWeight: 50 # 第二阶段:50% 流量
- pause:
duration: 30s # 暂停 30 秒进行监控验证
- setWeight: 100 # 第三阶段:100% 流量
- pause:
duration: 30s # 最后验证后全量切换
说明:
通过 Argo Rollouts 定义了金丝雀发布流程,包括:
每个阶段的流量比例,如 20%、50%。
阶段性暂停(手动或定时)用于人工确认或指标验证。
配置 canaryService 和 stable-Service,结合 Ingress 控制流量分流。
启用 Header(如 X-Canary)进行精细化流量控制。
2.Service 配置
设计逻辑:通过独立 Service 隔离新旧版本流量,结合 Ingress 权重控制实现渐进式迁移。
稳定版 Service
service-stable.yaml
apiVersion: v1
kind: Service
metadata:
name: service-stable
labels:
app: canary-demo
spec:
selector:
app: canary-demo
ports:
- port: 80
targetPort: http
protocol: TCP
name: http
金丝雀版 Service
service-canary.yaml
apiVersion: v1
kind: Service
metadata:
name: service-canary
labels:
app: canary-demo
spec:
selector:
app: canary-demo
ports:
- port: 80
targetPort: http
protocol: TCP
name: http
3.Ingress 配置
ingress-nginx.yaml
核心作用:负责入口流量的转发配置,并配合 Argo Rollouts 实现动态流量切分。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: canary-demo
labels:
app: canary-demo
annotations:
kubernetes.io/ingress.class: nginx # 指定使用 nginx ingress
spec:
rules:
- host: canary.auto # 访问域名
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: service-stable # 默认指向稳定版 Service
port:
name: http
3.3 部署与验证
步骤1:初始版本部署
1.创建命名空间并进入目录
# 创建独立命名空间
kubectl create ns canary-test
cd canary-deploy/ # 进入项目目录
2.应用资源配置
# 批量应用所有配置文件(Service/Ingress/Rollout)
kubectl apply -f . -n canary-test
步骤2:验证初始部署状态
# 检查资源创建状态(确保所有资源 READY)
kubectl get rollout,svc,ingress,pods -n canary-test
输出: 资源已被正确创建
NAME STATUS AVAILABLE AGE
rollout.argoproj.io/canary-demo ✔ Healthy 1/1 2m
NAME TYPE CLUSTER-IP PORT(S) AGE
service/service-canary ClusterIP 10.96.132.45 80/TCP 2m
service/service-stable ClusterIP 10.96.131.207 80/TCP 2m
NAME CLASS HOSTS ADDRESS PORTS AGE
ingress.networking.k8s.io/canary-demo nginx canary.auto 192.168.49.2 80 2m
NAME READY STATUS RESTARTS AGE
pod/canary-demo-7d5f8c6c9d-abcde 1/1 Running 0 2m
步骤3:浏览器验证初始版本
获取访问入口信息
# 获取 Ingress 对外 IP 和端口(如果是云环境,使用 EXTERNAL-IP;本地集群如 minikube 使用 IP)
INGRESS_IP=$(kubectl get ingress canary-demo -n canary-test -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
echo "访问地址: http://$INGRESS_IP"
访问网页
配置本地 hosts 文件:
127.0.0.1 canary.auto
浏览器访问:
http://canary.auto
初始页面为蓝色版本。类似如下
步骤4:触发金丝雀发布
模拟版本更新
# 通过镜像更新触发发布流程(从 blue 切换到 green 版本)
kubectl argo rollouts set image canary-demo \
canary-demo=argoproj/rollouts-demo:green -n canary-test
也可直接修改 canary-rollout.yaml 中镜像版本从blue 到 green,之后通过apply命令应用到集群。
步骤5:验证金丝雀发布(第一阶段 )
1.使用 Argo Rollouts CLI 观察部署过程
# 实时观察发布状态(新开终端执行)
kubectl argo rollouts get rollout canary-demo -n canary-test --watch
输出(第一阶段暂停时):
Name: canary-demo
Namespace: canary-test
Status: ॥ Paused
Message: CanaryPauseStep
Strategy: Canary
Step: 1/6
SetWeight: 20
ActualWeight: 20
Images: argoproj/rollouts-demo:green (canary)
argoproj/rollouts-demo:blue (stable)
2.浏览器流量验证(第一阶段 20% 流量)
操作 1:批量请求测试分流比例
# 发送 20 次请求统计版本分布(Linux/MacOS 环境)
for i in {1..20}; do
curl -s "http://$INGRESS_IP" -H "Host: canary.auto" | grep "Pod Image"
done | sort | uniq -c
输出:
16 Pod Image: argoproj/rollouts-demo:blue (stable)
4 Pod Image: argoproj/rollouts-demo:green (canary) # 约 20% 流量
操作2:浏览器访问 http://canary.auto
页面呈现 80% blue 方格 ,20% green 方块(新版本),类似下图:
操作 3:Dashboard 观测
# 启动 Argo Rollouts Dashboard(新终端执行)
kubectl argo rollouts dashboard -n canary-test
浏览器访问:http://localhost:3100,查看以下关键信息:
金丝雀发布的完整步骤以及 当前所在阶段
版本健康状态指示等
类似下图:
操作 4:Header 强制路由验证
# 通过 X-Canary 头强制路由到金丝雀版本
curl -s "http://$INGRESS_IP" -H "Host: canary.auto" -H "X-Canary: always" | grep "Pod Image"
输出:
Pod Image: argoproj/rollouts-demo:green (canary)
操作5:浏览器访问 http://canary.auto
页面 100% green 方块(新版本)
步骤 5:手动推进发布流程
方法1:命令
# 继续执行下一阶段(从 20% 提升至 50%)
kubectl argo rollouts promote canary-demo -n canary-test
# 观察自动执行后续步骤(30秒后进入100%阶段)
方法2:Dashboard 上操作
按下 Promote 按钮,Argo Rollouts 会根据策略自动执行后续步骤,即开始进入 50%和 70% 流量切换等。
注:仅当 Rollout 处于 Paused 状态时,Promote 按钮才激活。
步骤 6:全量发布完成验证
流程执行到最终阶段:
# 检查最终版本状态
kubectl argo rollouts get rollout canary-demo -n canary-test
输出:全部切换到新版本 green
Name: canary-demo
Namespace: canary-test
Status: ✔ Healthy
Strategy: Canary
Step: 6/6
SetWeight: 100
ActualWeight: 100
Images: argoproj/rollouts-demo:green (stable)
最终流量验证
# 发送 10 次请求确认全量切换
for i in {1..10}; do
curl -s "http://$INGRESS_IP" -H "Host: canary.auto" | grep "Pod Image"
done
输出:
Pod Image: argoproj/rollouts-demo:green (stable) # 全部请求
关键流程示意图
graph TD
A[创建初始资源] --> B[触发金丝雀发布]
B --> C{阶段1:20%流量}
C -->|手动验证| D[人工确认后推进]
D --> E{阶段2:50%流量}
E -->|自动暂停30秒| F[监控指标检查]
F --> G{阶段3:100%流量}
G -->|自动暂停30秒| H[最终验证]
H --> I[全量发布完成]
部署验证清单
步骤7:手动回滚操作
在 Dashboard 中找到目标 Rollout 资源。
点击 Actions 下拉菜单,选择 Abort and Rollback。
效果:当前的发布进程终止,并将流量切回旧版本。
四、金丝雀发布底层原理
4.1 核心机制:组件协作与流量控制
金丝雀发布的本质是由 Argo Rollouts 控制器动态协调 Ingress、Service 和 ReplicaSet 等 Kubernetes 原生资源,实现从旧版本到新版本的渐进式流量切换与灰度控制。整个过程无需手动干预,所有操作均由控制器按策略自动执行。
1.组件角色与交互
2.分阶段解析原理
下文以第三章 实例 为例 进行解析。
如下操作均由Argo Rollouts 控制器按策略文件自动执行,无需人为干预。
阶段1:初始状态(全流量稳定版)
A[用户请求] --> B[Ingress]
B --> C[service-stable]
C --> D[旧版本Pod]
原理解析:
service-stable通过标签(如 rollouts-pod-templatehash=6f8b8d584)选择旧版本 Pod。
Ingress 默认路由规则指向 service-stable,承载 100% 流量。
阶段2:金丝雀阶段(流量渐进切换)
首先环境准备:
创建新版本 ReplicaSet(如 canary-demo-67fc7c4899)。
生成 service-canary,标签选择器指向新版本 Pod。
Ingress 动态分流 ( 如下是分流示意图)
A[用户请求] --> B[Ingress]
B -->|80%流量| C[service-stable]
B -->|20%流量| D[service-canary]
C --> E[旧版本Pod]
D --> F[新版本Pod]
分阶段推进:
权重控制:通过调整新版本 Pod 的副本比例(如 1:4 → 20%流量)。
暂停机制:每个阶段可配置人工确认或自动等待(如 pause:{duration: 30m})。
阶段3:最终切换(全量发布)
原子化操作:
更新 service-stable的标签选择器,指向新版本 Pod。
缩容旧版本 ReplicaSet 至 0 副本。
最终状态:
A[用户请求] --> B[Ingress]
B --> C[service-stable]
C --> D[新版本Pod]
4.2 流量控制的两种模式
模式 1:按权重分配(副本比例控制)
实现原理:Argo Rollouts 动态调整新版本 Pod 的副本数,Ingress 根据副本比例自动分配流量。
示例:旧版本 4 副本 + 新版本 1 副本 → 新版本接收约 20% 流量。
优势:无需侵入式修改 Ingress 配置,适配 Kubernetes 原生负载均衡逻辑。
模式 2:按请求特征匹配(精准路由)
实现方式:在 Ingress 中配置 Header 匹配规则,实现定向灰度测试:
annotations:
nginx.ingress.kubernetes.io/canary-by-header: "X-Canary"
nginx.ingress.kubernetes.io/canary-by-header-value: "beta"
典型场景:
定向邀请内测用户(如 X-Canary: beta)
A/B 测试新功能(如 X-Experiment: new-ui)
4.3 Argo Rollouts 协调逻辑流图
participant 用户
participant ArgoRollouts
participant K8sAPI
participant Ingress
用户->>ArgoRollouts: 触发发布(修改镜像)
ArgoRollouts->>K8sAPI: 创建新ReplicaSet
K8sAPI-->>ArgoRollouts: 新Pod就绪
ArgoRollouts->>K8sAPI: 调整副本比例(如20%)
Ingress->>K8sAPI: 监听Endpoint变化
Ingress->>Ingress: 按副本比例分配流量
loop 分阶段推进
ArgoRollouts->>ArgoRollouts: 等待人工确认/定时器
ArgoRollouts->>K8sAPI: 提升副本比例(如50%)
end
ArgoRollouts->>K8sAPI: 缩容旧ReplicaSet
4.4 资源生命周期管理
1.Service 管理
稳定版 Service:全程存在,发布后切换至新版本 Pod,保持服务入口稳定性。
金丝雀 Service:发布完成后闲置,需手动清理或标记为临时资源(如 env: canary-temp)。
2.ReplicaSet 管理
旧版本:缩容至 0 副本,保留配置以支持秒级回滚。
新版本:长期保留,直至下次更新。
3.最佳实践
自动化清理:
# 清理7天前的临时资源
kubectl delete rs,svc -l env=canary-temp --field-selector="metadata.creationTimestamp<$(date -d '7 days ago' +%s)"
快速回滚:
kubectl argo rollouts undo <ROLLOUT_NAME>
4.5 金丝雀原理总结
1.核心原理
动态副本控制:通过调整 Pod 副本比例实现流量权重分配。
原子化切换:最终通过更新 Service 选择器和缩容旧版本完成全量发布。
2.技术优势
精准可控:支持流量比例与用户特征双重策略。
无缝切换:旧版本保留至最终阶段,确保回滚能力。
五、总结
5.1 核心总结
本文聚焦基于 Argo Rollouts 的金丝雀发布实战,通过精细化流量控制、阶段性发布策略和 Ingress 权重路由,构建了一个可操作、可观测的渐进式发布流程。
我们深入解析了 Argo Rollouts 的底层原理,包括:
流量权重分配与阶段推进;
Header 精准路由的灰度测试;
与 Ingress-NGINX 联动,实现流量控制与流量转发的分离。
在实战中,我们构建了从配置到上线的自动化金丝雀发布全过程。