使用 NGINX Ingress 进行 Canary 发布

在现代微服务架构中,Canary 发布(金丝雀发布)是一种流行的部署策略。它通过将新版本逐步推广到一小部分用户,观察其表现并降低风险,最终实现平稳过渡。本文将详细讲解如何利用 NGINX Ingress Controller 在 Kubernetes 中配置 Canary 发布。

什么是 Canary 发布?

Canary 发布是一种渐进式部署方式,其核心思想是将新版本的服务首先部署到生产环境中的一小部分用户(称为“金丝雀”),通过监控其性能和用户反馈来验证稳定性。如果一切正常,再逐步将流量切换到新版本;如果发现问题,则可以快速回滚。这种策略在减少部署风险的同时,保证了用户体验。

NGINX Ingress Controller 如何支持 Canary 发布?

NGINX Ingress Controller 通过一系列注解(annotations)提供了灵活的 Canary 发布支持。这些注解允许开发者控制流量在不同服务版本之间的分配方式。常见的注解包括:

  • nginx.ingress.kubernetes.io/canary:设为 "true" 以启用 Canary 功能。
  • nginx.ingress.kubernetes.io/canary-weight:基于权重的流量分配,值为 0-100,表示 Canary 版本接收的流量百分比。
  • nginx.ingress.kubernetes.io/canary-by-header:基于请求头的流量分配,指定检查的请求头名称。
  • nginx.ingress.kubernetes.io/canary-by-header-value:与 canary-by-header 配合使用,指定触发 Canary 的请求头值。
  • nginx.ingress.kubernetes.io/canary-by-cookie:基于 Cookie 的流量分配,指定检查的 Cookie 名称。

在本文中,我们将以基于 Cookie 的 Canary 发布为例,展示具体的配置过程。

示例:基于 Cookie 的 Canary 发布

假设我们有一个主服务 nginx 和一个 Canary 服务 nginx-hello-world,目标是根据用户请求中的 Cookie 值,将部分流量路由到 Canary 版本。以下是完整的配置步骤和代码。

1. 创建 ConfigMap

首先,创建一个 ConfigMap,用于存储 Canary 版本的自定义页面 index.html

apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-index
data:
  index.html: |
    
    
    
        Hello World
    
    
        

Hello, World!

这个 ConfigMap 将提供一个简单的“Hello, World!”页面,作为 Canary 版本的响应内容。

2. 部署 Canary 版本

接下来,部署 Canary 版本的 NGINX 服务,并挂载上述 ConfigMap 中的 index.html

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-hello-world
  labels:
    app: nginx-hello-world
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx-hello-world
  template:
    metadata:
      labels:
        app: nginx-hello-world
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80
        volumeMounts:
        - name: nginx-config
          mountPath: /usr/share/nginx/html/index.html
          subPath: index.html
      volumes:
      - name: nginx-config
        configMap:
          name: nginx-index
3. 创建 Canary 服务的 Service

为 Canary 版本创建一个 Service:

apiVersion: v1
kind: Service
metadata:
  name: nginx-hello-world
spec:
  selector:
    app: nginx-hello-world
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
  type: ClusterIP
4. 部署主版本

部署主版本的 NGINX 服务,这里我们使用一个自定义镜像 nextvirus/nginx:cookie(假设它包含主版本的逻辑):

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nextvirus/nginx:cookie
        ports:
        - containerPort: 80
5. 创建主服务的 Service

为主版本创建一个 Service:

apiVersion: v1
kind: Service
metadata:
  name: nginx
spec:
  selector:
    app: nginx
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
  type: ClusterIP
6. 配置 Ingress 资源

最后,配置两个 Ingress 资源,分别定义主版本和 Canary 版本的路由规则:

主版本 Ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx-ingress
spec:
  ingressClassName: nginx
  rules:
  - host: n.com   # 替换为你的域名
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: nginx
            port:
              number: 80

在配置完成后需要先访问下页面设置下 cookie。

Canary 版本 Ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx-ingress-hello-world
  annotations:
    nginx.ingress.kubernetes.io/canary: "true"
    nginx.ingress.kubernetes.io/canary-by-cookie: "testCookie"
spec:
  ingressClassName: nginx
  rules:
  - host: n.com   # 替换为你的域名
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: nginx-hello-world
            port:
              number: 80

配置解析

在上述配置中:

  • 主 Ingress (nginx-ingress):默认将流量路由到主服务 nginx
  • Canary Ingress (nginx-ingress-hello-world):通过注解启用 Canary 功能,并使用 canary-by-cookie: "testCookie" 指定基于 Cookie 的路由规则。
  • 工作原理:NGINX Ingress Controller 会检查请求中的 Cookie。如果存在名为 testCookie 的 Cookie 且其值满足条件(例如值为 true),流量将被路由到 Canary 服务 nginx-hello-world;否则,流量将路由到主服务 nginx

测试 Canary 发布

部署完成后,可以通过以下方式测试:

  1. 不带 Cookie 的请求

    curl http://n.com
    

    结果将返回主服务的响应。

  2. 带特定 Cookie 的请求

    curl -b "testCookie=true" http://n.com
    

    结果将返回 Canary 服务的响应,cookie设置页面。

扩展:其他 Canary 策略

除了基于 Cookie 的方式,NGINX Ingress Controller 还支持以下策略:

1. 基于权重的 Canary 发布

通过注解 nginx.ingress.kubernetes.io/canary-weight 设置流量百分比。例如:

annotations:
  nginx.ingress.kubernetes.io/canary: "true"
  nginx.ingress.kubernetes.io/canary-weight: "20"

这表示 20% 的流量将被路由到 Canary 服务。

2. 基于请求头的 Canary 发布

通过注解 nginx.ingress.kubernetes.io/canary-by-headernginx.ingress.kubernetes.io/canary-by-header-value 指定。例如:

annotations:
  nginx.ingress.kubernetes.io/canary: "true"
  nginx.ingress.kubernetes.io/canary-by-header: "X-Canary"
  nginx.ingress.kubernetes.io/canary-by-header-value: "true"

当请求头 X-Canary 的值为 true 时,流量将被路由到 Canary 服务。

总结

通过 NGINX Ingress Controller,我们可以轻松实现 Canary 发布,支持基于 Cookie、权重和请求头等多种流量分配策略。上述示例展示了基于 Cookie 的配置方法,帮助团队在生产环境中逐步验证新版本,确保部署过程安全可靠。如果您需要更复杂的流量控制,可以结合其他注解灵活调整策略。

你可能感兴趣的:(k8s,nginx,运维,kubernetes,云原生)