1. 程式人生 > >ASP.NET Core on K8S學習之旅(14)Ingress灰度釋出

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,《一文明白藍綠部署、滾動部署、灰度釋出、金絲雀釋出》

 

 

作者:周旭龍

出處:https://edisonchou.cnblogs.com

本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段宣告,且在文章頁面明顯位置給出原文連結。