全部產品
Search
文件中心

Container Compute Service:在ACK叢集中通過ALB Ingress實現灰階發布

更新時間:Dec 11, 2024

灰階發布是一種常用的軟體發布策略,通過漸進式地向使用者推送新版本的服務,來保證生產環境中服務迭代升級時系統的穩定性。ALB Ingress支援使用canary註解實現基於Header、Cookie、Weight的灰階發布。本文介紹如何通過ALB Ingress的canary註解實現服務的灰階發布。

前提條件

注意事項

  • 通過canary註解實現的三種灰階策略的優先順序為Header>Cookie>Weight,同時配置三種策略時,優先順序高的策略將優先進行灰階發布。關於canary註解的詳細資料,請參見ALB Ingress灰階發布註解

  • canary灰階發布不支援在同一條Ingress上同時配置基於Header/Cookie的灰階策略與基於權重Weight的灰階策略,這種情境下需要通過拆分為兩條Ingress或通過自訂轉寄動作實現。自訂轉寄動作可以實現基於更豐富的轉寄條件的灰階發布策略。關於自訂轉寄規則,請參見自訂ALB Ingress的轉寄規則

  • 通過canary註解實現灰階發布時,ALB Ingress轉寄規則生效順序依賴Ingress namespace/name字典序。為保證灰階規則生效順序,可以使用alb.ingress.kubernetes.io/order標識Ingress之間的生效順序。alb.ingress.kubernetes.io/order的取值範圍為1~1000,預設標識為數字10,值越小表示優先順序越高。例如,如果您想提高Ingress的優先順序,可以將目標Ingress的alb.ingress.kubernetes.io/order數值調小。

步驟一:部署服務

  1. 部署服務tea。

    1. 使用以下內容,建立tea-deploy.yaml

      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: tea
      spec:
        replicas: 1
        selector:
          matchLabels:
            app: tea
        template:
          metadata:
            labels:
              app: tea
          spec:
            containers:
            - name: tea
              image: registry.cn-hangzhou.aliyuncs.com/acs-sample/old-nginx:latest
              ports:
              - containerPort: 80
    2. 執行以下命令,部署服務tea。

      kubectl apply -f tea-deploy.yaml
  2. 部署名為tea-svc的Service。

    1. 使用以下內容,建立tea-svc.yaml

      apiVersion: v1
      kind: Service
      metadata:
        name: tea-svc
      spec:
        ports:
        - port: 80
          targetPort: 80
          protocol: TCP
        selector:
          app: tea
        type: ClusterIP
    2. 執行以下命令,部署Service。

      kubectl apply -f tea-svc.yaml
  3. 部署名為tea-ingress的Ingress。

    1. 使用以下內容,建立tea-ingress.yaml

      apiVersion: networking.k8s.io/v1
      kind: Ingress
      metadata:
        name: tea-ingress
      spec:
        ingressClassName: alb
        rules:
         - host: demo.domain.ingress.top # 請替換成您自己的網域名稱,並確保它已正確解析到Ingress控制器所在的負載平衡器的IP地址。
           http:
            paths:
            - path: /
              pathType: Prefix
              backend:
                service:
                  name: tea-svc
                  port:
                    number: 80
    2. 執行以下命令,部署Ingress。

      kubectl apply -f tea-ingress.yaml
  4. 驗證部署成功。

    1. 執行以下命令,請求訪問服務。

      curl -H Host:demo.domain.ingress.top http://alb-ny3ute4r8yevni****.cn-chengdu.alb.aliyuncs.com

      預期輸出:

      old

步驟二:灰階發布新版本服務

部署新版本服務和Ingress,使得當請求Header為location: hz時將路由到新版本服務canary,其他請求Header以及不攜帶請求Header將有50%的流量路由到新版本服務canary。

  1. 部署新版本服務canary。

    1. 使用以下內容,建立canary-deploy.yaml

      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: canary
      spec:
        replicas: 1
        selector:
          matchLabels:
            app: canary
        template:
          metadata:
            labels:
              app: canary
          spec:
            containers:
            - name: canary
              image: registry.cn-hangzhou.aliyuncs.com/acs-sample/new-nginx:latest
              ports:
              - containerPort: 80
    2. 執行以下命令,部署canary。

      kubectl apply -f canary-deploy.yaml
  2. 部署名為canary-svc的Service。

    1. 使用以下內容,建立canary-svc.yaml

      apiVersion: v1
      kind: Service
      metadata:
        name: canary-svc
      spec:
        ports:
        - port: 80
          targetPort: 80
          protocol: TCP
        selector:
          app: canary
        type: ClusterIP
    2. 執行以下命令,部署Service。

      kubectl apply -f canary-svc.yaml
  3. 部署基於Header分配流量的Ingress。

    1. 使用以下內容,建立canary-header-ingress.yaml

      apiVersion: networking.k8s.io/v1
      kind: Ingress
      metadata:
        annotations:
          alb.ingress.kubernetes.io/canary: "true"
          alb.ingress.kubernetes.io/canary-by-header: "location"
          alb.ingress.kubernetes.io/canary-by-header-value: "hz"
        name: canary-header-ingress
        namespace: default
      spec:
        ingressClassName: alb
        rules:
          - host: demo.domain.ingress.top # 請替換成您自己的網域名稱,並確保它已正確解析到Ingress控制器所在的負載平衡器的IP地址。
            http:
              paths:
                - backend:
                    service:
                      name: canary-svc
                      port:
                        number: 80
                  path: /
                  pathType: Prefix
      • alb.ingress.kubernetes.io/canary:設定為true,表示啟用canary註解功能。

      • alb.ingress.kubernetes.io/canary-by-headeralb.ingress.kubernetes.io/canary-by-header-value:佈建要求Header的索引值對。本文設定為location: hz,表示請求Header為location: hz,請求流量會被分配到新版本服務;對於其他Header,將會被忽略,並通過灰階優先順序將請求流量分配到其他規則設定的服務。

    2. 執行以下命令,部署基於Header分配流量的Ingress。

      kubectl apply -f canary-header-ingress.yaml
  4. 部署基於權重分配流量的Ingress。

    1. 使用以下內容,建立canary-weight-ingress.yaml

      apiVersion: networking.k8s.io/v1
      kind: Ingress
      metadata:
        annotations:
          alb.ingress.kubernetes.io/canary: "true"
          alb.ingress.kubernetes.io/canary-weight: "50"
        name: canary-weight-ingress
        namespace: default
      spec:
        ingressClassName: alb
        rules:
          - host: demo.domain.ingress.top # 請替換成您自己的網域名稱,並確保它已正確解析到Ingress控制器所在的負載平衡器的IP地址。
            http:
              paths:
                - backend:
                    service:
                      name: canary-svc
                      port:
                        number: 80
                  path: /
                  pathType: Prefix

      alb.ingress.kubernetes.io/canary-weight:設定路由到新版本服務的流量百分比。本文設定為50,表示50%的流量將路由到新版本服務。

    2. 執行以下命令,部署基於權重分配流量的Ingress。

      kubectl apply -f canary-weight-ingress.yaml
  5. 驗證灰階發布新版本服務是否成功。

    1. 執行以下命令,擷取ALB執行個體的訪問地址。

      kubectl get ingress

      預期輸出:

      NAME                    CLASS   HOSTS                     ADDRESS                                              PORTS   AGE
      canary-header-ingress   alb     demo.domain.ingress.top   alb-ny3ute4r8yevni****.cn-chengdu.alb.aliyuncs.com   80      8m23s
      canary-weight-ingress   alb     demo.domain.ingress.top   alb-ny3ute4r8yevni****.cn-chengdu.alb.aliyuncs.com   80      8m16s
      tea-ingress             alb     demo.domain.ingress.top   alb-ny3ute4r8yevni****.cn-chengdu.alb.aliyuncs.com   80      7m5s
    2. 執行以下命令,多次使用攜帶location: hz要求標頭的請求訪問服務。

      curl -H Host:demo.domain.ingress.top -H "location:hz" http://alb-ny3ute4r8yevni****.cn-chengdu.alb.aliyuncs.com

      預期輸出:

      new

      多次使用攜帶location: hz要求標頭的請求訪問服務,都返回new的結果,說明使用攜帶location: hz要求標頭的請求訪問服務時,請求都路由到新版本服務。

    3. 多次執行以下命令,發送不攜帶要求標頭的請求訪問服務。

      curl -H Host:demo.domain.ingress.top http://alb-ny3ute4r8yevni****.cn-chengdu.alb.aliyuncs.com

      多次不攜帶要求標頭的請求訪問服務,約50%機率返回new的結果,約50%機率返回old的結果,說明不攜帶要求標頭的請求訪問服務時,請求按照50%權重路由到新版本服務。

    4. 多次執行以下命令,使攜帶location: bj要求標頭的請求訪問服務。

      curl -H Host:demo.domain.ingress.top -H "location:bj" http://alb-ny3ute4r8yevni****.cn-chengdu.alb.aliyuncs.com

      多次攜帶location: bj要求標頭的請求訪問服務,約50%的機率返回new的結果,約50%的機率返回old的結果,說明攜帶location: bj要求標頭的請求訪問服務時,請求按照50%的權重路由到新版本服務。

    根據以上結果,可以看到當請求Header為location: hz時將路由到新版本服務canary,不攜帶請求Header以及其他請求Header有50%的流量路由到新版本服務canary,說明灰階發布canary服務成功。

步驟三:下線老版本服務

系統運行一段時間後,當新版本服務已經穩定並且符合預期時,需要下線舊版本的服務,僅保留新版本服務線上上運行。為了達到該目標,需要將原服務的Ingress中的Service修改為新版本服務的Service,使得流量都路由到新版本服務,然後刪除灰階Ingress。

  1. 執行以下命令,修改tea-ingress.yaml檔案。

    vim tea-ingress.yaml

    將tea-ingress.yaml檔案中的Service由tea-svc修改為canary-svc。

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: tea-ingress
    spec:
      ingressClassName: alb
      rules:
       - host: demo.domain.ingress.top # 請替換成您自己的網域名稱,並確保它已正確解析到Ingress控制器所在的負載平衡器的IP地址。
         http:
          paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: canary-svc # 將tea-svc替換為canary-svc。
                port:
                  number: 80
  2. 執行以下命令,使修改後的Ingress生效。

    kubectl apply -f tea-ingress.yaml
  3. 驗證下線老版本服務是否成功。

    1. 執行以下命令,多次使用攜帶location: hz要求標頭的請求訪問服務。

      curl -H Host:demo.domain.ingress.top -H "location:hz" http://alb-ny3ute4r8yevni****.cn-chengdu.alb.aliyuncs.com

      預期輸出:

      new

      多次使用攜帶location: hz要求標頭的請求訪問服務,都返回new的結果,說明使用攜帶location: hz要求標頭的請求訪問服務時,請求都路由到新版本服務。

    2. 執行以下命令,多次使用不攜帶要求標頭的請求訪問服務。

      curl -H Host:demo.domain.ingress.top http://alb-ny3ute4r8yevni****.cn-chengdu.alb.aliyuncs.com

      預期輸出:

      new

      多次使用不攜帶要求標頭的請求訪問服務,都返回new的結果,說明使用不攜帶要求標頭的請求訪問服務時,請求都路由到新版本服務。

    3. 執行以下命令,使多次攜帶location: bj要求標頭的請求訪問服務。

      curl -H Host:demo.domain.ingress.top -H "location:bj" http://alb-ny3ute4r8yevni****.cn-chengdu.alb.aliyuncs.com

      預期輸出:

      new

      多次使用攜帶location: bj要求標頭的請求訪問服務,都返回new的結果,說明使用攜帶location: bj要求標頭的請求訪問服務時,請求都路由到新版本服務。

    根據以上結果,可以看到攜帶location: hz要求標頭,攜帶其他要求標頭,或者不攜帶要求標頭的請求都路由到新版本服務,說明下線老版本服務成功。

  4. 執行以下命令,刪除名為canary-weight-ingress和canary-header-ingress的灰階Ingress,完成灰階發布流程。

    kubectl delete ingress canary-weight-ingress canary-header-ingress