目 录CONTENT

文章目录

ingress高阶用法--Canary金丝雀(灰度)发布

JamKing
2025-12-15 / 0 评论 / 1 点赞 / 10 阅读 / 0 字

1、前言

1.1 金丝雀发布

核心思想: 就像矿工下井前会先放一只金丝雀进去探测有毒气体一样,金丝雀发布是指将新版本的软件先发布给一小部分用户(或服务器),让他们作为“金丝雀”来测试新版本的稳定性和性能。如果没有问题,再逐步扩大新版本的流量比例,直到最终完全替换旧版本。

工作流程:

  1. 部署新版本(V2)到生产环境,但只让一小部分流量(例如 1%)访问 V2。
  2. 绝大部分流量(99%)仍然访问旧版本(V1)。
  3. 密切监控 V2 的性能指标(错误率、延迟、CPU/内存使用率等)。
  4. 如果 V2 表现良好,逐步增加其流量比例(例如 1% -> 5% -> 20% -> 50% -> 100%)。
  5. 如果在任何一个阶段发现问题,可以立即将所有流量切回 V1,实现快速回滚。

1.2 优缺点

特性 金丝雀发布
风险控制 非常高。影响范围小,问题可以被控制在极少数用户中,对整体系统影响小。
回滚速度 较快。只需调整流量分配策略,将流量切回旧版本即可。
用户体验 平滑过渡。大部分用户不受影响,只有小部分用户可能遇到新版本的问题。
真实反馈 可以获得真实用户的行为数据。因为新版本是在真实环境中被真实用户使用。
资源成本 较低。不需要双倍的生产环境资源,只需要控制流量分配。
复杂性 。需要精密的流量控制(如 Service Mesh, Nginx)和强大的监控、自动化系统来逐步调整流量和判断版本健康度。
数据库/状态 挑战较小。新旧版本共享同一个数据库和数据状态,通常不需要特殊处理(但要求数据库 schema 向后兼容)。
发布速度 。发布过程是渐进式的,需要分阶段观察和决策,耗时较长。

1.3 发布场景

1.对稳定性和风险控制要求极高:例如金融、支付等核心系统,任何微小的故障都可能导致巨大损失。

1.需要验证新功能对用户行为的影响:当你不确定新功能是否受用户欢迎时,可以先给一小部分用户使用,收集反馈和数据。

3.系统复杂,组件众多:对于复杂的微服务架构,金丝雀发布可以更精细地控制每个服务的发布节奏。

4.资源有限,无法承担双倍的服务器成本

5.拥有成熟的监控、告警和自动化平台:能够自动分析金丝雀版本的健康状况并自动进行流量调整。

2、版本备注

2.1 环境镜像

镜像版本 deployment 备注
harbor.test.com/java-dev/demo:Canary dev-demo-canary 假设是灰度版本
harbor.test.com/java-dev/demo:Prod dev-demo 假设是正式版本

2.2 环境deployment

canary版本

apiVersion: apps/v1
kind: Deployment
metadata:
  name: dev-demo-canary
  namespace: devops
spec:
  replicas: 1
  selector:
    matchLabels:
      app: dev-demo-canary
  template:
    metadata:
      labels:
        app: dev-demo-canary
    spec:
      containers:
        - name: dev-demo-canary
          image: harbor.test.com/java-dev/demo:Canary
          volumeMounts: []
      volumes: []
      restartPolicy: Always
      dnsPolicy: ClusterFirst
---
apiVersion: v1
kind: Service
metadata:
  name: dev-demo-canary
  namespace: devops
spec:
  selector:
    app: dev-demo-canary
  ports:
    - name: dev-demo-canary-8080
      protocol: TCP
      port: 8080
      targetPort: 8080

Prod版本

apiVersion: apps/v1
kind: Deployment
metadata:
  name: dev-demo-prod
  namespace: devops
spec:
  replicas: 1
  selector:
    matchLabels:
      app: dev-demo-prod
  template:
    metadata:
      labels:
        app: dev-demo-prod
    spec:
      containers:
        - name: dev-demo-prod
          image: harbor.test.com/java-dev/demo:Prod
          volumeMounts: []
      volumes: []
      restartPolicy: Always
      dnsPolicy: ClusterFirst
---
apiVersion: v1
kind: Service
metadata:
  name: dev-demo-prod
  namespace: devops
spec:
  selector:
    app: dev-demo-prod
  ports:
    - name: dev-demo-prod-8080
      protocol: TCP
      port: 8080
      targetPort: 8080

3、Canary灰度发布

3.1 基于Header灰度发布

使用 nginx.ingress.kubernetes.io/canary 注解实现灰度流量控制。

3.1.1 prod的ingress-rule

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: dev-ingress-prod
  namespace: devops
spec:
  ingressClassName: nginx
  tls:
    - hosts:
      - mydevweb.local
      secretName: mydevweb-secret
  rules:
  - host: mydevweb.local
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: dev-demo-prod
            port:
              number: 8080

3.1.2 canary的ingress-rule

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: dev-ingress-canary
  namespace: devops
  ###canary的header注解
  annotations:
    nginx.ingress.kubernetes.io/canary: "true"
    nginx.ingress.kubernetes.io/canary-by-header: "Canary"
    nginx.ingress.kubernetes.io/canary-by-header-value: "true"
  ###以上是header注解
spec:
  ingressClassName: nginx
  tls:
    - hosts:
      - mydevweb.local
      secretName: mydevweb-secret
  rules:
  - host: mydevweb.local
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: dev-demo-canary
            port:
              number: 8080

注释

注解 作用
http://nginx.ingress.kubernetes.io/canary: "true" 表示此 Ingress 为灰度规则
http://nginx.ingress.kubernetes.io/canary-by-header 指定用于判断的 HTTP Header 名称
http://nginx.ingress.kubernetes.io/canary-by-header-value 指定 Header 的值,当匹配该值时流量进入 Canary

3.1.3 验证服务

kubectl -n devops get deploy |grep dev-demo
kubectl -n devops get svc |grep dev-demo
kubectl -n devops get ingress

image-UqFS.png

普通用户场景访问

#-k忽略证书校验
curl -k https://mydevweb.local
#或
curl -k -H "Host: mydevweb.local" https://mydevweb.local

image-wYMv.png

灰度用户访问

curl -k -H "Host: mydevweb.local" -H "Canary: true" https://mydevweb.local

image-hkHz.png

3.2 基于Cookie灰度发布

3.2.1 prod的ingress-rule

不变

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: dev-ingress-prod
  namespace: devops
spec:
  ingressClassName: nginx
  tls:
    - hosts:
      - mydevweb.local
      secretName: mydevweb-secret
  rules:
  - host: mydevweb.local
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: dev-demo-prod
            port:
              number: 8080

3.2.2 canary的ingress-rule

注解内容有变

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: dev-ingress-canary
  namespace: devops
  ###canary的cookie注解
  annotations:
    nginx.ingress.kubernetes.io/canary: "true"
    nginx.ingress.kubernetes.io/canary-by-cookie: "Canary"
  ###以上是cookie注解
spec:
  ingressClassName: nginx
  tls:
    - hosts:
      - mydevweb.local
      secretName: mydevweb-secret
  rules:
  - host: mydevweb.local
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: dev-demo-canary
            port:
              number: 8080

注释

注解 含义
nginx.ingress.kubernetes.io/canary 标记为灰度规则
nginx.ingress.kubernetes.io/canary-by-cookie 指定 Cookie 名(这里是 Canary)

3.2.3 验证服务

普通用户场景访问

#-k忽略证书校验
curl -k https://mydevweb.local
#或
curl -k -H "Host: mydevweb.local" https://mydevweb.local

image-gcQn.png

灰度用户场景访问

curl -k -H "Host: mydevweb.local" --cookie "Canary=always" https://mydevweb.local

image-xPIQ.png

3.3 基于权重百分比灰度发布

3.3.1 prod的ingress-rule

不变

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: dev-ingress-prod
  namespace: devops
spec:
  ingressClassName: nginx
  tls:
    - hosts:
      - mydevweb.local
      secretName: mydevweb-secret
  rules:
  - host: mydevweb.local
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: dev-demo-prod
            port:
              number: 8080

3.3.2 canary的ingress-rule

注解内容有变

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: dev-ingress-canary
  namespace: devops
  ###canary的weight注解
  annotations:
    nginx.ingress.kubernetes.io/canary: "true"
    nginx.ingress.kubernetes.io/canary-weight: "20"
  ###以上是weight注解
spec:
  ingressClassName: nginx
  tls:
    - hosts:
      - mydevweb.local
      secretName: mydevweb-secret
  rules:
  - host: mydevweb.local
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: dev-demo-canary
            port:
              number: 8080

注释

注解 含义
nginx.ingress.kubernetes.io/canary 标记为灰度规则
nginx.ingress.kubernetes.io/canary-weight 权重百分比

3.3.3 验证服务

10次curl请求有2次灰度响应,符合预期

#-k忽略证书校验
for i in {1..10}; do curl -k -H "Host: mydevweb.local" https://mydevweb.local ;sleep 1;echo -e;done

image-cvKQ.png

3.3.4 快速调整权重

#填入实际的命名空间和ingress名称
kubectl -n devops annotate ingress dev-ingress-canary nginx.ingress.kubernetes.io/canary-weight="80" --overwrite

调整80后,8次灰度响应,符合预期

image-HXpE.png

3.3.5 全流量切换

全流量切换,通常符合最终版本上线了,优雅几乎无感知

kubectl -n devops annotate ingress dev-ingress-canary nginx.ingress.kubernetes.io/canary-weight="100" --overwrite

image-rbHa.png

1
  1. 支付宝打赏

    qrcode alipay
  2. 微信打赏

    qrcode weixin

评论区