4. Ingress-Nginx 的 Canary 特性:注解详解与流量切分
Ingress-Nginx 的 Canary 特性通过一组专用的 nginx.ingress.kubernetes.io/canary-* 注解,在不修改主 Ingress 资源的前提下,动态创建一条灰度流量规则。其核心设计遵循“主规则 + 灰度规则”的叠加模型:主 Ingress 承载稳定版本,Canary Ingress 承载灰度版本,两者通过注解建立关联。
4.1 核心注解清单与功能
| 注解名称 | 类型 | 说明 |
|---|---|---|
nginx.ingress.kubernetes.io/canary |
布尔 | 启用 Canary 规则,必须设为 "true" |
nginx.ingress.kubernetes.io/canary-weight |
整数 (0–100) | 基于权重的流量切分,百分比 |
nginx.ingress.kubernetes.io/canary-by-header |
字符串 | 基于请求头的流量匹配,值可为 always / never |
nginx.ingress.kubernetes.io/canary-by-header-value |
字符串 | 配合 canary-by-header,指定精确匹配值 |
nginx.ingress.kubernetes.io/canary-by-cookie |
字符串 | 基于 Cookie 的流量匹配,值 always 进入灰度 |
关键约束:Canary Ingress 的 host、path 必须与主 Ingress 完全一致,否则灰度规则不会生效。多个 Canary 规则同时存在时,优先级为:
canary-by-header > canary-by-cookie > canary-weight。
4.2 基于权重的流量切分
权重模式是最直观的灰度策略。通过 canary-weight 指定进入灰度版本的流量百分比,剩余流量全部转发至主版本。适用于小流量验证、性能基准对比等场景。
# 主 Ingress(稳定版)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app-main
spec:
ingressClassName: nginx
rules:
- host: demo.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: app-stable
port:
number: 80
---
# Canary Ingress(灰度版,承接 10% 流量)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app-canary
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-weight: "10"
spec:
ingressClassName: nginx
rules:
- host: demo.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: app-canary-svc
port:
number: 80
权重切分行为:当
canary-weight 设为 10 时,约 10% 的请求被随机路由到灰度服务 app-canary-svc,其余 90% 仍由 app-stable 处理。权重总和不得超过 100,多个 Canary Ingress 共享同一主 Ingress 时,权重按比例分配。
4.3 基于 Header 的流量切分
Header 模式允许通过 HTTP 请求头精确控制灰度流量,适用于内部测试、QA 验证、A/B 测试等场景。该模式不依赖随机概率,而是由客户端显式声明。
| 注解组合 | 匹配逻辑 | 典型用途 |
|---|---|---|
canary-by-header: X-Canary |
Header 值为 always 时进入灰度 |
内部 QA 手动标记请求 |
canary-by-header: X-Canary+ canary-by-header-value: v2 |
Header 值精确匹配 v2 时进入灰度 |
A/B 测试分组 |
canary-by-header: X-Canary+ canary-by-header-value: never |
Header 值为 never 时强制走主版本 |
绕过灰度,回退稳定版 |
# Canary Ingress(基于 Header 精确匹配)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app-canary-header
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-by-header: "X-Canary"
nginx.ingress.kubernetes.io/canary-by-header-value: "v2"
spec:
ingressClassName: nginx
rules:
- host: demo.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: app-canary-svc
port:
number: 80
Header 优先级陷阱:当同时配置
canary-weight 和 canary-by-header 时,Header 匹配优先。即:如果请求携带了匹配的 Header,无论权重设置多少,该请求都会进入灰度版本。设计灰度策略时需注意此优先级,避免权重失效。
4.4 流量切分决策流程
下图展示了 Ingress-Nginx 在处理请求时,如何根据 Canary 注解依次判断并路由流量:
4.5 多规则组合策略
在实际生产环境中,通常将权重与 Header 组合使用,形成“内部灰度 + 外部小流量”的混合策略:
- 内部测试通道:通过
canary-by-header: X-Canary为 QA 团队提供固定灰度入口,不受权重影响。 - 渐进式放量:权重从 1% 开始,逐步增加至 5%、10%、20%,配合监控指标决定是否继续放量。
- 紧急回退:通过
canary-by-header-value: never让特定请求强制走主版本,用于快速绕过灰度问题。
最佳实践:在自动化流水线中,Canary Ingress 的创建与权重调整应作为部署流水线的一个独立阶段。建议使用
kubectl annotate 动态调整权重,避免频繁修改 YAML 文件。例如:kubectl annotate ingress app-canary nginx.ingress.kubernetes.io/canary-weight=20 --overwrite。