zoukankan      html  css  js  c++  java
  • ASP.NET Core on K8S学习之旅(14)Ingress灰度发布

    本篇已加入《.NET Core on K8S学习实践系列文章索引》,可以点击查看更多容器化技术相关系列文章。

    之前一篇介绍了Ingress的基本概念和Nginx Ingress的基本配置和使用,本篇继续Ingress的使用,来看看如何使用Ingress实现灰度发布(金丝雀发布)。此外,我也有录制一个10min+的小视频介绍蓝绿发布和金丝雀发布的基本概念,视频入口点击这里

    一、准备工作

    1.1 WebAPI项目准备

      首先,我们还是准备两个版本的ASP.NET Core WebAPI项目,具体项目代码参见这里

      他们之间的差别在于一个接口的返回JSON数据,比如V1.0版本中返回的是Version: 1.0,而V1.1版本中返回的是Version:1.1。

        [Route("api/[controller]")]
        [ApiController]
        public class HomeController : ControllerBase
        {
            // GET api/home
            [HttpGet]
            public ActionResult<IEnumerable<string>> Get()
            {
                return new string[] {
                    "Hello, welcome to EDC's demo. Version: 1.0"
                };
            }
        }

      运行结果为:

      (2)将此项目各个版本根据Dockerfile打成镜像,分别是xilife/canary-api-demo:1.0,1.1。

      (3)将本地镜像push到远程镜像仓库,这里我传送到了docker hub的一个公共仓库里边:

    docker push xilife/canary-api-demo:1.0
    docker push xilife/canary-api-demo:1.1

    1.2 WebAPI项目部署

      其次,我们将这两个WebAPI项目部署到K8s集群中,还是通过熟悉的yaml文件来将其部署为Service:

      (1)V1.0版本(假设为线上版本)

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: canary-api-demo
      namespace: xdp-poc
      labels:
        name: canary-api-demo
    spec:
      replicas: 2
      selector:
        matchLabels:
          name: canary-api-demo
      template:
        metadata:
          labels:
            name: canary-api-demo
        spec:
          containers:
          - name: canary-api-demo
            image: xilife/canary-api-demo:1.0
            ports:
            - containerPort: 80
            imagePullPolicy: IfNotPresent
    
    ---
    
    kind: Service
    apiVersion: v1
    metadata:
      name: canary-api-svc
      namespace: xdp-poc
    spec:
      type: NodePort
      ports:
        - port: 80
          targetPort: 80
      selector:
        name: canary-api-demo

      (2)V1.1版本(假设为灰度版本)

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: canary-api-demo-gray
      namespace: xdp-poc
      labels:
        name: canary-api-demo-gray
    spec:
      replicas: 2
      selector:
        matchLabels:
          name: canary-api-demo-gray
      template:
        metadata:
          labels:
            name: canary-api-demo-gray
        spec:
          containers:
          - name: canary-api-demo-gray
            image: xilife/canary-api-demo:1.1
            ports:
            - containerPort: 80
            imagePullPolicy: IfNotPresent
    
    ---
    
    kind: Service
    apiVersion: v1
    metadata:
      name: canary-api-svc-gray
      namespace: xdp-poc
    spec:
      type: NodePort
      ports:
        - port: 80
          targetPort: 80
      selector:
        name: canary-api-demo-gray

      将这两个应用部署至K8s集群:

    kubectl apply -f deploy-canary-api-svc.yml
    kubectl apply -f deploy-canary-api-gray-svc.yml

    二、Ingress灰度发布应用

      Ingress-Nginx 支持配置 Ingress Annotations 来实现不同场景下的灰度发布和测试,可以满足金丝雀发布、蓝绿部署与 A/B 测试等业务场景。

      因此我们准备两个版本的Ingress的yml文件,它提供了两种方式:

      一是基于用户请求的流量切分,具体又包括了基于Request Header的流量切分与基于Cookie的流量切分两种方式;如下图所示:

      二是基于服务权重的流量切分;如下图所示:

    2.1 基于Request Header的流量切分方式

      根据Request Header的流量切分方式的约定,适用于灰度发布及A/B测试。当 Request Header 设置为 always时,请求将会被一直发送到 Canary 版本;当 Request Header 设置为 never时,请求不会被发送到 Canary 入口;对于任何其他 Header 值,将忽略 Header,并通过优先级将请求与其他金丝雀规则进行优先级的比较。

      为1.0版本准备一个Ingress,让它先工作着:

    apiVersion: networking.k8s.io/v1beta1
    kind: Ingress
    metadata:
      name: nginx-ingress
      namespace: xdp-poc
      annotations:
        kubernetes.io/ingress.class: "nginx"
        nginx.ingress.kubernetes.io/rewrite-target: /api/$2
    spec:
      rules:
      - host: portal.k8s.xi-life.cn
        http:
          paths:
          - path: /api(/|$)(.*)
            backend:
              serviceName: canary-api-svc
              servicePort: 80

      应用至K8s集群:

    kubectl apply -f ingress-nginx.yaml

      再为1.1版本准备一个Ingress,让它作为灰度版本的入口逐步替换原v1版本的流量接入:

    apiVersion: networking.k8s.io/v1beta1
    kind: Ingress
    metadata:
      name: nginx-ingress-gray
      namespace: xdp-poc
      annotations:
        kubernetes.io/ingress.class: "nginx"
        nginx.ingress.kubernetes.io/rewrite-target: /api/$2
        nginx.ingress.kubernetes.io/canary: "true"
        nginx.ingress.kubernetes.io/canary-by-header: "canary"
        nginx.ingress.kubernetes.io/canary-by-header-value: "true"
    spec:
      rules:
      - host: portal.k8s.xi-life.cn
        http:
          paths:
          - path: /api(/|$)(.*)
            backend:
              serviceName: canary-api-svc-gray
              servicePort: 80

      应用至K8s集群:

    kubectl apply -f ingress-nginx-gray.yaml

       快速验证:

    2.2 基于Cookie的流量切分方式

      根据基于 Cookie 的流量切分方式的约定,当 Cookie 值设置为 always时,它将被路由到 Canary 入口;当 Cookie 值设置为 never时,请求不会被发送到 Canary 入口;对于任何其他值,将忽略 Cookie 并将请求与其他金丝雀规则进行优先级的比较。

      为灰度版本准备Ingress:

    apiVersion: networking.k8s.io/v1beta1
    kind: Ingress
    metadata:
      name: nginx-ingress-gray
      namespace: xdp-poc
      annotations:
        kubernetes.io/ingress.class: "nginx"
        nginx.ingress.kubernetes.io/proxy-body-size: "100m"
        nginx.ingress.kubernetes.io/limit-rps: '10'
        nginx.ingress.kubernetes.io/rewrite-target: /api/$2
        nginx.ingress.kubernetes.io/canary: "true"
        nginx.ingress.kubernetes.io/canary-by-cookie: "xdp-v2-cookie"
    spec:
      rules:
      - host: portal.k8s.xi-life.cn
        http:
          paths:
          - path: /api(/|$)(.*)
            backend:
              serviceName: canary-api-svc-gray
              servicePort: 80

      应用至K8s集群:

    kubectl apply -f ingress-nginx-gray.yaml

      快速验证:

      (1)未添加Cookie

      (2)为要访问的域名添加一个Cookie

      (3)再次请求验证

    2.3 基于服务权重的流量切分方式 

      根据基于服务权重的流量切分方式的约定,适用于蓝绿部署,权重范围 0 - 100 按百分比将请求路由到 Canary Ingress 中指定的服务。权重为 0 意味着该金丝雀规则不会向 Canary 入口的服务发送任何请求。权重为 100 意味着所有请求都将被发送到 Canary 入口。

      为灰度版本准备Ingress:

    apiVersion: networking.k8s.io/v1beta1
    kind: Ingress
    metadata:
      name: nginx-ingress-gray
      namespace: xdp-poc
      annotations:
        kubernetes.io/ingress.class: "nginx"
        nginx.ingress.kubernetes.io/proxy-body-size: "100m"
        nginx.ingress.kubernetes.io/limit-rps: '10'
        nginx.ingress.kubernetes.io/rewrite-target: /api/$2
        nginx.ingress.kubernetes.io/canary: "true"
        nginx.ingress.kubernetes.io/canary-weight: "50"
    spec:
      rules:
      - host: portal.k8s.xi-life.cn
        http:
          paths:
          - path: /api(/|$)(.*)
            backend:
              serviceName: canary-api-svc-gray
              servicePort: 80

      应用至K8s集群:

    kubectl apply -f ingress-nginx-gray.yaml

      快速验证:这里我直接通过浏览器来测试,需要注意的是这里的50%是一个近似分布值,可能实际中不会太精确。

    三、三种方式的对比

      Nginx Ingress提供的三种灰度发布的方式的优先级顺序为:
    canary-by-header -> canary-by-cookie -> canary-weight
      已知限制:
      (1)Ingress-Nginx是在0.21.0版本中才引入的Canary功能,因此建议确保版本在0.22.0及之后(据说0.21.0版本的基于Cookie方式有点问题);
      (2)目前每个Ingress规则中最多只能应用一个canary入口

    四、小结

      本文介绍了Nginx Ingress提供的三种灰度发布(canary)的方式,然后介绍了如何使用Nginx Ingress并进行配置实现ASP.NET Core WebAPI应用服务的灰度发布实践,最后对比三种方式的优先级及限制,希望对你有所帮助。

    参考资料

    (1)JadePeng,《K8s基于Nginx Ingress实现灰度发布

    (2)我的小碗汤,《Nginx Ingress实现灰度和金丝雀发布

    (3)梁宽,《再也不踩坑的K8s实战指南

    (4)WangT,《K8s基于Nginx Ingress进行蓝绿部署/金丝雀发布

    (5)linus.lin,《一文明白蓝绿部署、滚动部署、灰度发布、金丝雀发布

  • 相关阅读:
    如何在HTML5 图片预览
    js本地图片预览代码兼容所有浏览器
    c#无损高质量压缩图片
    c#如何在win7下设置IE代理的完美解决方案
    关于Android 访问权限设置
    在asp.net mvc中将checkbox传到后台时总是true的解决方法
    IO流
    Map集合重要练习
    Map笔记总结
    泛型笔记
  • 原文地址:https://www.cnblogs.com/edisonchou/p/aspnet_core_on_k8s_deepstudy_part14.html
Copyright © 2011-2022 走看看