K8S Nginx Ingress实现金丝雀发布

通过给 Ingress 资源指定 Nginx Ingress 所支持的 annotation 可实现金丝雀发布。

需给服务创建2个 Ingress,其中1个常规 Ingress,另1个为带 nginx.ingress.kubernetes.io/canary: "true" 固定的 annotation 的 Ingress,称为 Canary Ingress。

Canary Ingress 一般代表新版本的服务,结合另外针对流量切分策略的 annotation 一起配置即可实现多种场景的金丝雀发布。

以下为相关 annotation 的详细介绍:

  • nginx.ingress.kubernetes.io/canary-by-header
    表示如果请求头中包含指定的 header 名称,并且值为 always,就将该请求转发给该 Ingress 定义的对应后端服务。如果值为 never 则不转发,可以用于回滚到旧版。如果为其他值则忽略该 annotation。

  • nginx.ingress.kubernetes.io/canary-by-header-value

    该 annotation 可以作为 canary-by-header 的补充,可指定请求头为自定义值,包含但不限于 alwaysnever。当请求头的值命中指定的自定义值时,请求将会转发给该 Ingress 定义的对应后端服务,如果是其它值则忽略该 annotation。

  • nginx.ingress.kubernetes.io/canary-by-header-pattern

    canary-by-header-value 类似,区别为该 annotation 用正则表达式匹配请求头的值,而不是只固定某一个值。如果该 annotation 与 canary-by-header-value 同时存在,该 annotation 将被忽略。

  • nginx.ingress.kubernetes.io/canary-by-cookie

    canary-by-header 类似,该 annotation 用于 cookie,仅支持 alwaysnever

  • nginx.ingress.kubernetes.io/canary-weight

    表示 Canary Ingress 所分配流量的比例的百分比,取值范围 0-100。例如,设置为10,则表示分配10%的流量给 Canary Ingress 对应的后端服务。

一、部署蓝环境版本服务

1、ConfigMap

bash 复制代码
kind: ConfigMap
apiVersion: v1
metadata:
  name: nginx-blue-config
data:
  nginx.conf: |-
    worker_processes  1;

    events {
        accept_mutex on;
        multi_accept on;
        use epoll;
        worker_connections  1024;
    }

    http {
        ignore_invalid_headers off;
        server {
            listen 80;
            location / {
                access_by_lua '
                    local header_str = ngx.say("blue")
                ';
            }
        }
    }

2、Deployment

bash 复制代码
kind: Deployment
apiVersion: apps/v1
metadata:
  name: nginx-blue
  labels:
    dce.daocloud.io/app: nginx-blue
  annotations:
    dce.daocloud.io/last-replicas: '1'
    deployment.kubernetes.io/revision: '3'
    kubernetes.io/change-cause: update YAML
spec:
  replicas: 1
  selector:
    matchLabels:
      dce.daocloud.io/component: nginx-blue
  template:
    metadata:
      name: nginx-blue
      labels:
        dce.daocloud.io/app: nginx-blue
        dce.daocloud.io/component: nginx-blue
      annotations:
        dce.daocloud.io/parcel.egress.burst: '0'
        dce.daocloud.io/parcel.egress.rate: '0'
        dce.daocloud.io/parcel.ingress.burst: '0'
        dce.daocloud.io/parcel.ingress.rate: '0'
        dce.daocloud.io/parcel.net.type: calico
    spec:
      volumes:
        - name: nginx-blue-config
          configMap:
            name: nginx-blue-config
            defaultMode: 420
      containers:
        - name: nginx-blue
          image: 'x.x.x.x/library/openresty:1.19.9.1-sw-r4'
          resources:
            limits:
              cpu: 500m
              memory: '314572800'
            requests:
              cpu: 200m
              memory: '314572800'
          volumeMounts:
            - name: nginx-blue-config
              mountPath: /etc/nginx/nginx.conf
              subPath: nginx.conf

3、Service

bash 复制代码
kind: Service
apiVersion: v1
metadata:
  name: nginx-blue-default
  labels:
    dce.daocloud.io/app: nginx-blue
  annotations:
    io.daocloud.dce.serviceSelectorType: service
spec:
  ports:
    - name: nginx-nginx-default-80680-80
      protocol: TCP
      port: 80
      targetPort: 80
      nodePort: 31046
  selector:
    dce.daocloud.io/component: nginx-blue
  clusterIP: 172.31.69.137
  type: NodePort
  sessionAffinity: None
  externalTrafficPolicy: Cluster

4、修改pod内容

bash 复制代码
cd /usr/local/openresty/nginx/html/

ls
50x.html  index.html

echo "Hello Blue" > index.html

cat index.html 
Hello Blue

二、部署绿环境版本服务

1、ConfigMap

bash 复制代码
kind: ConfigMap
apiVersion: v1
metadata:
  name: nginx-green-config
data:
  nginx.conf: |-
    worker_processes  1;

    events {
        accept_mutex on;
        multi_accept on;
        use epoll;
        worker_connections  1024;
    }

    http {
        ignore_invalid_headers off;
        server {
            listen 80;
            location / {
                access_by_lua '
                    local header_str = ngx.say("green")
                ';
            }
        }
    }

2、Deployment

bash 复制代码
kind: Deployment
apiVersion: apps/v1
metadata:
  name: nginx-green
  labels:
    dce.daocloud.io/app: nginx-green
  annotations:
    deployment.kubernetes.io/revision: '5'
    kubernetes.io/change-cause: update YAML
spec:
  replicas: 1
  selector:
    matchLabels:
      dce.daocloud.io/component: nginx-green
  template:
    metadata:
      name: nginx-green
      labels:
        dce.daocloud.io/app: nginx-green
        dce.daocloud.io/component: nginx-green
        env: green
      annotations:
        dce.daocloud.io/parcel.egress.burst: '0'
        dce.daocloud.io/parcel.egress.rate: '0'
        dce.daocloud.io/parcel.ingress.burst: '0'
        dce.daocloud.io/parcel.ingress.rate: '0'
        dce.daocloud.io/parcel.net.type: calico
        dce.daocloud.io/parcel.net.value: default-ipv4-ippool
    spec:
      volumes:
        - name: nginx-green-config
          configMap:
            name: nginx-green-config
            defaultMode: 420
      containers:
        - name: nginx-green
          image: 'x.x.x.x/library/openresty:1.19.9.1-sw-r4'
          resources:
            limits:
              cpu: 500m
              memory: '314572800'
            requests:
              cpu: 200m
              memory: '314572800'
          volumeMounts:
            - name: nginx-green-config
              mountPath: /etc/nginx/nginx.conf
              subPath: nginx.conf

3、Service

bash 复制代码
kind: Service
apiVersion: v1
metadata:
  name: nginx-green-default
  labels:
    dce.daocloud.io/app: nginx-green
  annotations:
    io.daocloud.dce.serviceSelectorType: service
spec:
  ports:
    - name: nginx-nginx-default-15833-80
      protocol: TCP
      port: 80
      targetPort: 80
      nodePort: 35218
  selector:
    dce.daocloud.io/component: nginx-green
  clusterIP: 172.31.207.22
  type: NodePort
  sessionAffinity: None
  externalTrafficPolicy: Cluster

4、修改pod内容

bash 复制代码
cd /usr/local/openresty/nginx/html/

ls
50x.html  index.html

echo "Hello Green" > index.html

cat index.html 
Hello Green

三、设置Ingress

1、blue环境Ingress

bash 复制代码
kind: Ingress
apiVersion: networking.k8s.io/v1beta1
metadata:
  name: nginx-blue-ingress
  labels:
    dce.daocloud.io/app: nginx-blue
  annotations:
    nginx.ingress.kubernetes.io/use-port-in-redirects: 'true'
spec:
  rules:
    - host: nginx.ms-sit.xxxxxx.net
      http:
        paths:
          - path: /
            pathType: ImplementationSpecific
            backend:
              serviceName: nginx-blue-default
              servicePort: 80

2、green环境Ingress

bash 复制代码
kind: Ingress
apiVersion: networking.k8s.io/v1beta1
metadata:
  name: nginx-green-ingress
  labels:
    dce.daocloud.io/app: nginx-green
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/canary: 'true'
    nginx.ingress.kubernetes.io/canary-by-header: env
    nginx.ingress.kubernetes.io/canary-by-header-pattern: green
spec:
  rules:
    - host: nginx.ms-sit.xxxxxx.net
      http:
        paths:
          - path: /
            pathType: ImplementationSpecific
            backend:
              serviceName: nginx-green-default
              servicePort: 80

四、测试

相关推荐
天蓝不会忘记023 小时前
k8s集群部署的方法原理
云原生·容器·kubernetes
红球yyds5 小时前
用anisble搭建k8s集群及原理
云原生·容器·kubernetes
Thneonl8 小时前
让恢复动作敢按下去:dry-run、审批门、自动回滚与 mutable twin
rust·kubernetes
东风破_19 小时前
Docker 基础:为什么需要容器?
前端·后端·nginx
东风破_19 小时前
Docker 实战:使用 Nginx 作为容器入口代理 Node 服务
前端·后端·nginx
ltl21 小时前
mTLS 工程实践:服务间双向认证怎么落地
kubernetes
外滩运维专家1 天前
通配符证书到期,阿里云上几个服务的证书怎么一次换完
运维·开发语言·nginx·https·php·消息推送
栩栩云生1 天前
别再硬记 AWS 和 k8s 命令了!一行命令把十几个云平台的 CLI 全接进 AI
kubernetes·agent·mcp
对象存储与RustFS1 天前
给 Kubernetes 找一个对象存储后端:RustFS Helm 部署 + 应用接入实录
后端·云原生·kubernetes
qq10916069811 天前
nginx+TongWeb 配置非443端口的https
网络·nginx·https