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 注解依次判断并路由流量:

Ingress-Nginx Canary 流量决策流程 请求到达 检查 canary-by-header 注解 Header 值匹配? 匹配 灰度版本 不匹配 检查 Cookie 匹配 Cookie 值匹配? 匹配 灰度版本 权重随机判定 命中 灰度版本 主版本(稳定)

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。