全部產品
Search
文件中心

Container Service for Kubernetes:管理南北

更新時間:Nov 09, 2024

ACK One多叢集網關基於MSE Ingress提供了強大的多叢集南北向流量的管理,可以快速幫您實現同城應用多活容災、流量多叢集負載平衡、基於Header路由流量到指定叢集等能力。本文介紹如何通過多叢集網關管理多叢集應用的南北流量。

背景資訊

多叢集網關優勢

在Container Service領域,管理叢集內服務的南北向流量的常用方式是使用Ingress資源進行管理。但Ingress為單叢集維度,無法獨立為多個叢集中的應用流量進行管理,因此,ACK One基於MSE Ingress實現地區級的Global Ingress來統一處理多叢集應用的南北向流量,並提供強大的流量管理能力,協助您快速、低成本地實現同城應用多活容災、流量多叢集負載平衡、基於Header路由流量到指定叢集等能力。此外,多叢集網關使用易上手的Ingress API進行管理,極大地降低了使用門檻。

重要

使用多叢集網關會產生一定的費用,關於多叢集網關的計費資訊,請參見普通執行個體計費概述

MSE相關文檔

  • MseIngressConfig是由MSE Ingress Controller提供的CRD資源,用於管理MSE雲原生網關執行個體的生命週期,配置Ingress監聽選項以及全域配置。MseIngressConfig的常見用法,請參見配置MseIngressConfig

  • MSE Ingress已支援Nginx-Ingress核心和常用的Annotation,並推出額外的Annotation來彌補Nginx-Ingress的不足。更多資訊,請參見MSE Ingress支援的Annotation

前提條件

步驟一:在ACK One Fleet執行個體中建立多叢集網關

在ACK One Fleet執行個體中建立一個多叢集網關(網關預設可用性區域高可用),並將關聯集群添加至多叢集網關

通過控制台建立

  1. 登入ACK One控制台,在左側導覽列選擇艦隊 > 多叢集網關

  2. 多叢集網關頁面右上方單擊建立網關

  3. 在彈出的面板中,根據實際情況修改建立多叢集網關的YAML檔案,然後單擊建立。

通過命令列建立

  1. 擷取ACK One Fleet執行個體的虛擬交換器ID並記錄。

    1. 執行以下命令,擷取交換器執行個體ID。

    aliyun adcp DescribeHubClusterDetails --ClusterId <YOUR_FLEET_CLUSTERID>
    1. 從預期輸出的VSwitches中複製一個交換器執行個體ID。

  2. 使用以下內容,建立mseingressconfig.yaml檔案。

    替換以下${vsw-id1}為您上一步擷取的交換器ID。您也可以在建立網關時,通過添加Annotation同步指定待添加到多叢集網關的關聯集群。

    apiVersion: mse.alibabacloud.com/v1alpha1
    kind: MseIngressConfig
    metadata:
      name: ackone-gateway
      # 添加關聯集群到MSE網關。
      #annotations:
      #  mse.alibabacloud.com/remote-clusters: ${cluster1},${cluster2}
    spec:
      common:
        instance:
          replicas: 3
          spec: 2c4g
        network:
          # 公網SLB和內網SLB,可都配置,如果2個欄位都不配置則預設使用公網SLB。
          #publicSLBSpec: slb.s2.small
          #privateSLBSpec: slb.s2.small
          vSwitches:
          - ${vsw-id1}
      ingress:
        local:
          ingressClass: mse
      name: mse-ingress
  3. 執行以下命令,在ACK One Fleet執行個體中建立一個名為mse-ingress的網關。

    kubectl apply -f mseingressconfig.yaml
  4. 執行以下命令,驗證網關是否建立成功。

    kubectl get mseingressconfig ackone-gateway

    預期輸出:

    NAME             STATUS      AGE
    ackone-gateway   Listening   3m15s

    預期輸出中網關狀態為Listening,表明雲原生網關建立成功處於運行狀態,並自動監聽叢集中IngressClass為mse的Ingress資源。

    通過MseIngressConfig建立的多叢集網關會按照Pending、Running、Listening的狀態依次變化。各狀態說明如下:

    • Pending:表明雲原生網關正在建立中,需等待3分鐘左右。

    • Running:表明雲原生網關建立成功,並處於運行狀態。

    • Listening:表明雲原生網關處於運行狀態,並監聽叢集中Ingress資源。

    • Failed:表明雲原生網關處於非法狀態,可以查看Status欄位中的Message來進一步明確原因。

步驟二:在多叢集網關中添加關聯集群

通過控制台添加

  1. 登入ACK One控制台,在左側導覽列選擇艦隊 > 多叢集網關

  2. 多叢集網關頁面上方的下拉框中選擇要修改的目標多叢集網關,然後在頁面右上方單擊編輯

  3. 在彈出的面板中修改MseIngresConfig.yaml檔案,修改annotations參數中的叢集ID,然後單擊更新

    樣本如下:

    annotations:
      mse.alibabacloud.com/remote-clusters: ${cluster1-id},${cluster2-id}
    • ${cluster1-id}${cluster2-id}為添加的關聯集群的ID,多個關聯集群以英文半形逗號(,)間隔,您可以通過修改叢集ID來添加或刪除關聯的叢集。

    • 若建立多叢集網關時未添加關聯集群,則MseIngresConfig.yaml檔案中沒有annotations參數,添加關聯集群時,您需要將以上樣本添加到MseIngresConfig.yaml檔案的metadata對象中,再修改叢集ID。

通過命令列方式添加

  1. 在ACK One Fleet執行個體中,通過mseingressconfig對象的Annotation控制多叢集網關中添加或刪除關聯集群。替換以下${cluster1-id}${cluster2-id}為您待添加的關聯集群的ID,添加多個關聯集群時,中間以英文半形逗號(,)間隔。

    annotations:
      mse.alibabacloud.com/remote-clusters: ${cluster1-id},${cluster2-id}
  2. 執行以下命令,查看關聯集群是否已成功添加至多叢集網關。

    kubectl get mseingressconfig ackone-gateway -ojsonpath="{.status.remoteClusters}"

    預期輸出:

    [{"clusterId":"c7fb82****"},{"clusterId":"cd3007****"}]

    預期輸出中已包含指定的ClusterID,並且無Failed資訊,表明關聯集群已成功添加至多叢集網關。

步驟三:使用GitOps部署Demo應用

  1. 使用GitOps將Demo應用部署到兩個關聯的ACK叢集中。具體操作,請參見GitOps快速入門

    1. 建立2個GitOps Application,分別對應2個關聯集群。樣本:web-demo-cluster1、web-demo-cluster2。

    2. Source配置如下:

      • Repository URL設定為https://github.com/AliyunContainerService/gitops-demo.git

      • Revision設定為HEAD

      • Path設定為manifests/helm/web-demo

    3. DESTINATION分別選擇2個關聯集群,namespace設定為web-demo

    4. Helm Values Files中的參數名稱為envNamevalue分別為cluster1cluster2

    部署後的Deployment和Service的YAML檔案如下。

    展開查看Deployment和Service的YAML檔案

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      labels:
        app: web-demo
        app.kubernetes.io/instance: web-demo-cluster1
      name: web-demo
      namespace: web-demo
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: web-demo
      template:
        metadata:
          labels:
            app: web-demo
        spec:
          containers:
          - name: web-demo
            image: acr-multiple-clusters-registry.cn-hangzhou.cr.aliyuncs.com/ack-multiple-clusters/web-demo:0.4.0
            env:
            - name: ENV_NAME
              value: cluster1
    ---
    apiVersion: v1       
    kind: Service
    metadata:
      name: service1
      namespace: web-demo
    spec:
      ports:
      - port: 80
        protocol: TCP
        targetPort: 8080
      selector:
        app: web-demo
      sessionAffinity: None
      type: ClusterIP

步驟四:使用MSE Ingress管理多叢集流量

通過在Ingress中指定IngressClass來使用MSE Ingress,並且使用不同的Annotation實現不同的流量管理能力。MSE Ingress不僅支援Nginx-Ingress核心和常用的Annotation,還針對Nginx-Ingress Annotation未支援的流量治理配置,推出額外的Annotation以彌補Nginx-Ingress的不足。MSE Ingress支援的Annotations請參見MSE Ingress支援的Annotation。下文以典型的多叢集流量管理情境為例說明。

重要

Ingress對象和Demo應用中Service對象的Namespace需要保持一致。

樣本1:預設負載平衡到所有服務後端

在ACK One Fleet執行個體中建立以下Ingress對象,可以預設將流量負載平衡到所有叢集的同名服務後端,所有副本均衡。路由到不同叢集的流量比例等同於叢集中的副本數量的比例,例如,Cluster 1和Cluster 2中副本數比例為9:1,則流量在Cluster 1和Cluster 2中的流量比也為9:1。本例使用1:1的副本數示範。拓撲如下所示:image.png

  1. 使用以下內容,建立ingress-demo.yaml檔案。

    以下Ingress對象的YAML檔案中,通過網域名稱example.com下的/svc1路由規則暴露後端服務service1

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: web-demo
      namespace: web-demo
    spec:
      ingressClassName: mse
      rules:
      - host: example.com
        http:
          paths:
          - path: /svc1
            pathType: Exact
            backend:
              service:
                name: service1
                port: 
                  number: 80
  2. 執行以下命令,在ACK One Fleet執行個體中部署Ingress。

    kubectl apply -f ingress-demo.yaml
  3. 執行以下命令,擷取多叢集網關對外IP。

    kubectl get ingress web-demo -nargocd -ojsonpath="{.status.loadBalancer}"
  4. 執行以下命令,查看流量的路由情況。

    替換以下XX.XX.XX.XX為上一步擷取的多叢集網關對外IP。

    for i in {1..50}; do curl -H "host: example.com" XX.XX.XX.XX/svc1; sleep 1;  done

    預期輸出:

    This is env cluster1 !
    Config file is 
    This is env cluster1 !
    Config file is 
    This is env cluster1 !
    Config file is 
    This is env cluster1 !
    Config file is 
    This is env cluster2 !
    Config file is 
    This is env cluster1 !
    Config file is 
    This is env cluster1 !
    Config file is 
    This is env cluster1 !
    Config file is 
    This is env cluster1 !
    Config file is 
    This is env cluster1 !
    Config file is 
    This is env cluster1 !
    Config file is 

    預期輸出表明,流量被路由到所有叢集上。

樣本2:流量僅路由到指定叢集

在ACK One Fleet執行個體中建立以下Ingress對象,可以將流量僅路由到Cluster 1的服務後端。拓撲如下所示:image.png

  1. 使用以下內容,建立ingress-demo-cluster-one.yaml檔案。

    以下Ingress對象的YAML檔案中,通過添加兩個Annotations mse.ingress.kubernetes.io/service-subsetmse.ingress.kubernetes.io/subset-labels以實現網域名稱example.com下的/service1路由規則暴露後端服務service1。關於MSE Ingress支援的Annotations詳情,請參見MSE Ingress支援的Annotation

    • mse.ingress.kubernetes.io/service-subset:服務的子版本名稱。建議定義為與目的地組群相關且可讀性強的值。

    • mse.ingress.kubernetes.io/subset-labels:指定目的地組群的ID。

      apiVersion: networking.k8s.io/v1
      kind: Ingress
      metadata:
        annotations:
          mse.ingress.kubernetes.io/service-subset: cluster-demo-1
          mse.ingress.kubernetes.io/subset-labels: |
            topology.istio.io/cluster ${cluster1-id}
        name: web-demo-cluster-one
        namespace: web-demo
      spec:
        ingressClassName: mse
        rules:
        - host: example.com
          http:
            paths:
            - path: /service1
              pathType: Exact
              backend:
                service:
                  name: service1
                  port: 
                    number: 80
  2. 執行以下命令,在ACK One Fleet執行個體中部署Ingress。

    kubectl apply -f ingress-demo-cluster-one.yaml
  3. 執行以下命令,擷取多叢集網關對外IP。

    kubectl get ingress web-demo -nargocd -ojsonpath="{.status.loadBalancer}"
  4. 執行以下命令,查看流量的路由情況。

    替換以下XX.XX.XX.XX為上一步擷取的多叢集網關對外IP。

    for i in {1..50}; do curl -H "host: example.com" XX.XX.XX.XX/service1; sleep 1;  done

    預期輸出:

    This is env cluster1 !
    Config file is 
    This is env cluster1 !
    Config file is 
    This is env cluster1 !
    Config file is 
    This is env cluster1 !
    Config file is 
    This is env cluster1 !
    ...

    預期輸出表明,固定的流量被路由到Cluster 1上。

樣本3:根據Header將流量路由到指定叢集

如需根據自訂Header將流量路由到指定叢集的服務後端,您可以在ACK One Fleet執行個體中建立Example 1或者Example 2Ingress對象,然後再建立以下Ingress對象(此Ingress對象無法單獨生效)。拓撲如下所示:

重要

基於Header方式進行流量調度時,您需要在Ingress的註解上配置Canary註解和Header匹配策略,同時需確保已存在另一個Ingress中不包含Canary註解且存在相同的Host + Path訪問另一個叢集中的服務。即Header方式的Ingress不能單獨生效,需搭配使用另一個不指定Header的Ingress指向另一個叢集中的服務。

image.png

  1. 使用以下內容,建立ingress-demo-header.yaml檔案。

    以下Ingress對象的YAML檔案中,通過網域名稱example.com下的/service1路由規則暴露後端服務service1

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      annotations:
        mse.ingress.kubernetes.io/service-subset: cluster-demo-2
        mse.ingress.kubernetes.io/subset-labels: |
          topology.istio.io/cluster c15d48ca9d1fd43f9bbb89c56a474843c
        nginx.ingress.kubernetes.io/canary: "true"
        nginx.ingress.kubernetes.io/canary-by-header: "stage"
        nginx.ingress.kubernetes.io/canary-by-header-value: "gray"
      name: web-demo-cluster-second
      namespace: web-demo
    spec:
      ingressClassName: mse
      rules:
      - host: example.com
        http:
          paths:
          - path: /service1
            pathType: Exact
            backend:
              service:
                name: service1
                port: 
                  number: 80
  2. 執行以下命令,在ACK One Fleet執行個體中部署Ingress。

    kubectl apply -f ingress-demo-header.yaml
  3. 執行以下命令,擷取多叢集網關對外IP。

    kubectl get ingress web-demo -nargocd -ojsonpath="{.status.loadBalancer}"
  4. 執行以下命令,查看流量的路由情況。

    替換以下XX.XX.XX.XX為上一步擷取的多叢集網關對外IP。

    for i in {1..50}; do curl -H "host: example.com" -H "stage: gray" xx.xx.xx.xx/service1; sleep 1;  done

    預期輸出:

    This is env cluster2 !
    Config file is 
    This is env cluster2 !
    Config file is 
    This is env cluster2 !
    Config file is 
    This is env cluster2 !
    Config file is 
    This is env cluster2 !
    Config file is 
    ...

    預期輸出表明,流量根據Header stage: gray被路由到Cluster 2上。

樣本4:多叢集應用跨叢集容災

多叢集網關具備多叢集應用跨叢集容災的能力,無需額外配置。例如,上述配置的多叢集網關管理了兩個關聯的ACK叢集的流量,如果其中一個叢集的服務異常或被刪除,流量會自動轉到另一個可用叢集。上述樣本1樣本2樣本3均一樣,即使已經指定路由到某個叢集,但當此叢集上的應用異常後,也會被容災到其他叢集上。

以下以樣本3為例說明,在正常情況下,添加Header stage: gray,您可以訪問到Cluster 2的後端,當Cluster 2的Deployment副本數被縮為0時,請求會切換至Cluster 1的後端。拓撲如下所示:image.png

  1. 執行以下命令,擷取多叢集網關對外IP。

    kubectl get ingress web-demo -nargocd -ojsonpath="{.status.loadBalancer}"
  2. 執行以下命令,查看流量的路由情況。

    替換以下XX.XX.XX.XX為上一步擷取的多叢集網關對外IP。

    for i in {1..50}; do curl -H "host: example.com" -H "stage: gray" XX.XX.XX.XX/service1; sleep 1;  done

    預期輸出:

    This is env cluster1 !
    Config file is 
    This is env cluster1 !
    Config file is 
    This is env cluster1 !
    Config file is 
    This is env cluster1 !
    Config file is 
    This is env cluster1 !
    Config file is 
    ...

    預期輸出表明,流量被自動容災到Cluster 1上。

樣本5:根據權重進行流量路由

樣本1中,您可以通過調節叢集中副本數的比例,實現按比例路由流量到不同的叢集。本樣本介紹如何在Annotations中配置權重來按比例路由流量到不同的叢集,也可以使用該方式進行灰階發布。您可以在ACK One Fleet執行個體中建立以下2個Ingress對象實現該能力,拓撲如下所示:

重要

基於權重方式進行流量調度時,您需要在Ingress的註解上配置Canary註解和Header匹配策略,同時需保證已存在另一個Ingress不含有Canary註解且存在相同的Host + Path訪問另一個叢集中的服務。即權重方式的Ingress不能單獨生效,需搭配使用另一個不指定權重的Ingress指向另一個叢集中的服務。

image.png

  1. 使用以下內容,建立ingress-weight.yaml檔案。

    以下Ingress對象的YAML檔案中,替換YAML中的${cluster1-id}為目的地組群ID。通過添加Annotations以實現網域名稱example.com下的/svc1-w路由規則暴露後端服務service1

    • mse.ingress.kubernetes.io/service-subset:服務的子版本名稱。建議定義為與目的地組群相關且可讀性強的值。

    • mse.ingress.kubernetes.io/subset-labels:目標ACK叢集的ID。

    • nginx.ingress.kubernetes.io/canary:設定為"true",表示開啟灰階發布能力。

    • nginx.ingress.kubernetes.io/canary-weight:請求到該叢集的流量百分比(值為0~100的整數)。

      apiVersion: networking.k8s.io/v1
      kind: Ingress
      metadata:
        annotations:
          mse.ingress.kubernetes.io/service-subset: cluster-demo-1
          mse.ingress.kubernetes.io/subset-labels: |
            topology.istio.io/cluster ${cluster1-id}
        name: web-demo-weight
        namespace: web-demo
      spec:
        ingressClassName: mse
        rules:
        - host: example.com
          http:
            paths:
            - path: /svc1-w
              pathType: Exact
              backend:
                service:
                  name: service1
                  port: 
                    number: 80
      ---
      apiVersion: networking.k8s.io/v1
      kind: Ingress
      metadata:
        annotations:
          mse.ingress.kubernetes.io/service-subset: cluster-demo-2
          mse.ingress.kubernetes.io/subset-labels: |
            topology.istio.io/cluster ${cluster2-id}
          nginx.ingress.kubernetes.io/canary: "true"
          nginx.ingress.kubernetes.io/canary-weight: "10"
        name: web-demo-weight-canary
        namespace: web-demo
      spec:
        ingressClassName: mse
        rules:
        - host: example.com
          http:
            paths:
            - path: /svc1-w
              pathType: Exact
              backend:
                service:
                  name: service1
                  port: 
                    number: 80
  2. 執行以下命令,在ACK One Fleet執行個體中部署Ingress。

    kubectl apply -f ingress-weight.yaml -nargocd
  3. 執行以下命令,擷取多叢集網關對外IP。

    kubectl get ingress web-demo -nargocd -ojsonpath="{.status.loadBalancer}"
  4. 執行以下命令,查看流量的路由情況。

    替換以下XX.XX.XX.XX為上一步擷取的多叢集網關對外IP。

    for i in {1..50}; do curl -H "host: example.com" XX.XX.XX.XX/svc1-w; sleep 1;  done

    預期輸出:

    This is env cluster1 !
    Config file is 
    This is env cluster1 !
    Config file is 
    This is env cluster1 !
    Config file is 
    This is env cluster1 !
    Config file is 
    This is env cluster1 !
    Config file is 
    This is env cluster1 !
    Config file is 
    This is env cluster1 !
    Config file is 
    This is env cluster1 !
    Config file is 
    This is env cluster1 !
    Config file is 
    This is env cluster1 !
    Config file is 
    This is env cluster1 !
    Config file is 
    This is env cluster2 !
    Config file is 
    This is env cluster1 !
    Config file is 
    This is env cluster1 !
    Config file is 
    This is env cluster1 !
    Config file is 
    This is env cluster1 !
    Config file is 
    This is env cluster1 !
    Config file is 
    This is env cluster1 !
    Config file is 
    This is env cluster2 !
    Config file is 
    This is env cluster1 !
    Config file is 
    ...

    預期輸出表明,根據權重進行流量路由,90%的流量被路由到Cluster 1上,10%的流量被路由到Cluster 2上。