腾讯云手把手教你使用Nginx Ingress实现金丝雀发布

时间:2021-07-15 | 标签: | 作者:Q8 | 来源:roc 陈鹏网络

小提示:您能找到这篇{腾讯云手把手教你使用Nginx Ingress实现金丝雀发布}绝对不是偶然,我们能帮您找到潜在客户,解决您的困扰。如果您对本页介绍的腾讯云手把手教你使用Nginx Ingress实现金丝雀发布内容感兴趣,有相关需求意向欢迎拨打我们的服务热线,或留言咨询,我们将第一时间联系您!

< color: rgb(31, 73, 125);">概述

< ">本文将介绍如何使用Nginx Ingress实现金丝雀发布,从使用场景分析,到用法详解,再到上手实践。

前提条件

< ">集群中需要部署Nginx Ingress作为Ingress Controller,并且对外暴露了统一的流量入口,参考Nginx Ingress on TKE部署最佳实践。

Nginx Ingress可以用在哪些发布场景?

< ">使用Nginx Ingress来实现金丝雀发布,可以用在哪些场景呢?这个主要看使用什么策略进行流量切分,目前Nginx Ingress支持基于Header、Cookie和服务权重这3种流量切分的策略,基于它们可以实现以下两种发布场景。

场景一:将新版本灰度给部分用户

< ">假设线上运行了一套对外提供7层服务的Service A服务,后来开发了个新版本Service A'想要上线,但又不想直接替换掉原来的Service A,希望先灰度一小部分用户,等运行一段时间足够稳定了再逐渐全量上线新版本,最后平滑下线旧版本。这个时候就可以利用Nginx Ingress基于Header或Cookie进行流量切分的策略来发布,业务使用Header或Cookie来标识不同类型的用户,我们通过配置Ingress来实现让带有指定Header或Cookie的请求被转发到新版本,其它的仍然转发到旧版本,从而实现将新版本灰度给部分用户:

场景二:切一定比例的流量给新版本

< ">假设线上运行了一套对外提供7层服务的Service B服务,后来修复了一些问题,需要灰度上线一个新版本Service B',但又不想直接替换掉原来的Service B,而是让先切10%的流量到新版本,等观察一段时间稳定后再逐渐加大新版本的流量比例直至完全替换旧版本,最后再滑下线旧版本,从而实现切一定比例的流量给新版本:

注解说明

< ">我们通过给Ingress资源指定Nginx Ingress所支持的一些annotation可以实现金丝雀发布,需要给服务创建两个Ingress,一个正常的Ingress,另一个是带nginx.ingress.kubernetes.io/canary:"true"这个固定的annotation的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:这个可以作为canary-by-header的补充,允许指定请求头的值可以自定义成其它值,不再只能是always或never;当请求头的值命中这里的自定义值时,请求将会转发给该Ingress定义的对应后端服务,如果是其它值则将会忽略该annotation。

< ">nginx.ingress.kubernetes.io/canary-by-header-pattern:这个与上面的canary-by-header-value类似,唯一的区别是它是用正则表达式对来匹配请求头的值,而不是只固定某一个值;需要注意的是,如果它与canary-by-header-value同时存在,这个annotation将会被忽略。

< ">nginx.ingress.kubernetes.io/canary-by-cookie:这个与canary-by-header类似,只是这个用于cookie,同样也是只支持always和never的值。

< ">nginx.ingress.kubernetes.io/canary-weight:表示Canary Ingress所分配流量的比例的百分比,取值范围[0-100],比如设置为10,意思是分配10%的流量给Canary Ingress对应的后端服务。

< ">上面的规则会按优先顺序进行评估,优先顺序如下:canary-by-header->canary-by-cookie->canary-weight

< ">注意:当Ingress被标记为Canary Ingress时,除了nginx.ingress.kubernetes.io/load-balance和nginx.ingress.kubernetes.io/upstream-hash-by之外,所有其他非Canary注释都将被忽略。

上手实践

< ">下面我们给出一些例子,让你快速上手Nginx Ingress的金丝雀发布,环境为TKE集群。

使用YAML创建资源

< ">本文的示例将使用yaml的方式部署工作负载和创建Service,有两种操作方式。

< ">方式一:在TKE或EKS控制台右上角点击YAML创建资源,然后将本文示例的yaml粘贴进去:

< ">方式二:将示例的yaml保存成文件,然后使用kubectl指定yaml文件来创建,如:kubectl apply-f xx.yaml。

部署两个版本的服务

< ">这里以简单的nginx为例,先部署一个v1版本:

apiVersion: apps/v1



kind: Deployment

metadata:

  name: nginx-v1

spec:

  replicas: 1

  selector:

    matchLabels:

      app: nginx

      version: v1

  template:

    metadata:

      labels:

        app: nginx

        version: v1

    spec:

      containers:

      - name: nginx

        image: "openresty/openresty:centos"

        ports:

        - name: http

          protocol: TCP

          containerPort: 80

        volumeMounts:

        - mountPath: /usr/local/openresty/nginx/conf/nginx.conf

          name: config

          subPath: nginx.conf

      volumes:

      - name: config

        configMap:

          name: nginx-v1

---

apiVersion: v1

kind: ConfigMap

metadata:

  labels:

    app: nginx

    version: v1

  name: nginx-v1

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 '

          &n危机公关文案范文bsp;         local header_str = ngx.say("nginx-v1")

                ';

            }

        }

    }

---

apiVersion: v1

kind: Service

metadata:

  name: ngin原生信息流推广x-v1

spec:

  type: ClusterIP

  ports:

  - port: 80

    protocol: TCP

    name: http

  selector:

    app: nginx

    version: v1

< ">再部署一个v2版本:

apiVersion: apps/v1

kind: Deployment

metadata:

  name: nginx-v2

spec:

  replicas: 1

  selector:

    matchLabels:

      app: nginx

      version: v2

  template:

    metadata:

      labels:

        app: nginx

        version: v2

    spec:

      containers:

      - name: nginx

        image: "openresty/openresty:centos"

        ports:

        - name: http

          protocol: TCP

          containerPort: 80

        volumeMounts:

        - mountPath: /usr/local/openresty/nginx/conf/nginx.conf

          name: config

          subPath: nginx.conf

      volumes:

      - name: config

        configMap:

          name: nginx-v2

---

apiVersion: v1

kind: ConfigMap

metadata:

  labels:

    app: nginx

    version: v2

  name: nginx-v2

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("nginx-v2")

                ';

            }

        }

    }

---

apiVersion: v1

kind: Service

metadata:

  name: nginx-v2

spec:

  type: ClusterIP

  ports:

  - port: 80

    protocol: TCP

    name: http

  selector:

    app: nginx

    version: v2

< ">可以在控制台看到部署的情况:

< ">再创建一个Ingress,对外暴露服务,指向v1版本的服务:

apiVersion: extensions/v1beta1

kind: Ingress

metadata:

  name: nginx

  annotations:

    kubernetes.io/ingress.class: nginx

spec:

  rules:

  - host: canary.example.com

    http:

      paths:

      - backend:

          serviceName: nginx-v1

          servicePort: 80

        path: /

< ">访问验证一下:

$curl-H"Host:canary.example.com"http://EXTERNAL-IP#EXTERNAL-IP替换为Nginx Ingress自身对外暴露的IP

nginx-v1

基于Header的流量切分

< ">创建Canary Ingress,指定v2版本的后端服务,且加上一些annotation,实现仅将带有名为Region且值为cd或sz的请求头的请求转发给当前Canary Ingress,模拟灰度新版本给成都和深圳地域的用户:

apiVersion: extensions/v1beta1

kind: Ingress

metadata:

  annotations:

    kubernetes.io/ingress.class: nginx

    nginx.ingress.kubernetes.io/canary: "true"

    nginx.ingress.kubernetes.io/canary-by-header: "Region"

    nginx.ingress.kubernetes.io/canary-by-header-pattern: "cd|sz"

  name: nginx-canary

spec:

  rules:

  - host: canary.example.com

    http:

      paths:

      - backend:

          serviceName: nginx-v2

          servicePort: 80

        path: /

< ">测试访问:

$curl-H"Host:canary.example.com"-H"Region:cd"http://EXTERNAL-IP#EXTERNAL-IP替换为Nginx Ingress自身对外暴露的IP

nginx-v2

$curl-H"Host:canary.example.com"-H"Region:bj"http://EXTERNAL-IP

nginx-v1

$curl-H"Host:canary.example.com"-H"Region:sz"http://EXTERNAL-IP

nginx-v2

$curl-H"Host:canary.example.com"http://EXTERNAL-IP

nginx-v1

< ">可以看到,只有header Region为cd或sz的请求才由v2版本服务响应。

基于Cookie的流量切分

< ">与前面Header类似,不过使用Cookie就无法自定义value了,这里以模拟灰度成都地域用户为例,仅将带有名为user_from_cd的cookie的请求转发给当前Canary Ingress。先删除前面基于Header的流量切分的Canary Ingress,然后创建下面新的Canary Ingress:

apiVersion: extensions/v1beta1

kind: Ingress

metadata:

  annotations:

    kubernetes.io/ingress.class: nginx

    nginx.ingress.kubernetes.io/canary: "true"

    nginx.ingress.kubernetes.io/canary-by-cookie: "user_from_cd"

  name: nginx-canary

spec:

  rules:

  - host: canary.example.com

    http:

      paths:

      - backend:

          serviceName: nginx-v2

          servicePort: 80

        path: /

< ">测试访问:

$curl-s-H"Host:canary.example.com"--cookie"user_from_cd=always"http://EXTERNAL-IP#EXTERNAL-IP替换为Nginx Ingress自身对外暴露的IP

nginx-v2

$curl-s-H"Host:canary.example.com"--cookie"user_from_bj=always"http://EXTERNAL-IP

nginx-v1

$curl-s-H"Host:canary.example.com"http://EXTERNAL-IP

nginx-v1

< ">可以看到,只有cookie user_from_cd为always的请求才由v2版本的服务响应。

基于服务权重的流量切分

< ">基于服务权重的Canary Ingress就简单了,直接定义需要导入的流量比例,这里以导入10%流量到v2版本为例(如果有,先删除之前的Canary Ingress):

apiVersion: extensions/v1beta1

kind: Ingress

metadata:

  annotations:

    kubernetes.io/ingress.class: nginx

    nginx.ingress.kubernetes.io/canary: "true"

    nginx.ingress.kubernetes.io/canary-weight: "10"

  name: nginx-canary

spec:

  rules:

  - host: canary.example.com

    http:

      paths:

      - backend:

          serviceName: nginx-v2

          servicePort: 80

        path: /

< ">测试访问:

$for i in{1..10};do curl-H"Host:canary.example.com"http://EXTERNAL-IP;done;

nginx-v1

nginx-v1

nginx-v1

nginx-v1

nginx-v1

nginx-v1



nginx-v2

nginx-v1

nginx-v1

nginx-v1

< ">可以看到,大概只有十分之一的几率由v2版本的服务响应,符合10%服务权重的设置。

存在的缺陷

< ">虽然我们使用Nginx Ingress实现了几种不同姿势的金丝雀发布,但还存在一些缺陷:

< ">相同服务的Canary Ingress只能定义一个,所以后端服务最多支持两个版本。

< ">Ingress里必须配置域名,否则不会有效果。

< ">即便流量完全切到了Canary Ingress上,旧版服务也还是必须存在,不然会报错。

< ">< font-size: 18px; color: rgb(31, 73, 125);">总结

< ">本文全方位总结了Nginx Ingress的金丝雀发布用法,虽然Nginx Ingress在金丝雀发布这方面的能力有限,并且还存在一些缺陷,但基本也能覆盖一些常见的场景,如果集群中使用了Nginx Ingress,并且发布的需求也不复杂,可以考虑使用这种方案。

参考资料

Nginx Ingress金丝雀注解官方文档:https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#canary

Nginx Ingress on TKE部署最佳实践:https://mp.weixin.qq.com/s/NAwz4dlsPuJnqfWYBHkfGg

腾讯云手把手教你使用Nginx Ingress实现金丝雀发布

上一篇:《七龙珠:武斗传奇》与 GCP 后端
下一篇:shopify怎么绑定手机


版权声明:以上主题为“腾讯云手把手教你使用Nginx Ingress实现金丝雀发布"的内容可能是本站网友自行发布,或者来至于网络。如有侵权欢迎联系我们客服QQ处理,谢谢。
相关内容
推荐内容
扫码咨询
    腾讯云手把手教你使用Nginx Ingress实现金丝雀发布
    打开微信扫码或长按识别二维码

小提示:您应该对本页介绍的“腾讯云手把手教你使用Nginx Ingress实现金丝雀发布”相关内容感兴趣,若您有相关需求欢迎拨打我们的服务热线或留言咨询,我们尽快与您联系沟通腾讯云手把手教你使用Nginx Ingress实现金丝雀发布的相关事宜。

关键词:腾讯云手把手教你使用N

关于 | 业务 | 案例 | 免责 | 隐私
客服邮箱:sales@1330.com.cn
电话:400-021-1330 | 客服QQ:865612759
沪ICP备12034177号 | 沪公网安备31010702002418号