全部產品
Search
文件中心

Alibaba Cloud Service Mesh:基於多叢集實現跨地區容災和流量負載平衡

更新時間:Jun 30, 2024

Service MeshASM為應用服務提供了跨地區流量分布和跨地區容錯移轉能力。跨地區流量分布功能可以將流量按照設定的權重路由至多個叢集,實現多地區負載平衡。跨地區容錯移轉功能可以在某地區服務發生故障時,將該地區流量轉移至其他地區,實現跨地區容災。以Bookinfo應用為例,本文介紹如何使用跨地區容錯移轉和流量分布能力實現跨地區容災和流量負載平衡。

網路規劃

在進行操作前,您需要對vSwitch、VPC和叢集的網段、名稱等資訊進行規劃,本文規劃如下:

說明

關於資料平面多叢集地址規劃的詳細介紹,請參見多叢集網路規劃

  • vSwich和VPC的網路規劃

    • vSwitch網路規劃

      重要

      為了避免使用CEN打通VPC網路後產生路由衝突,兩個vSwitch不能使用相同的網段。

      對象

      vSwitch名稱

      VPC

      IPv4網段

      叢集

      vpc-hangzhou-switch-1

      vpc-hangzhou

      20.0.0.0/16

      vpc-shanghai-switch-1

      vpc-shanghai

      21.0.0.0/16

      Service Mesh

      vpc-hangzhou-switch-2

      vpc-hangzhou2

      192.168.0.0/24

    • VPC網路規劃

      對象

      VPC名稱

      Region

      IPv4網段

      叢集

      vpc-hangzhou

      cn-hangzhou

      20.0.0.0/8

      vpc-shanghai

      cn-shanghai

      21.0.0.0/8

      Service Mesh

      vpc-hangzhou2

      cn-hangzhou

      192.168.0.0/16

  • 叢集的Pod和Service網路規劃

    叢集名稱

    Region

    VPC

    Pod CIDR

    Service CIDR

    ack-hangzhou

    cn-hangzhou

    vpc-hangzhou

    10.0.0.0/16

    172.16.0.0/16

    ack-shanghai

    cn-shanghai

    vpc-shanghai

    10.1.0.0/16

    172.17.0.0/16

步驟一:建立不同地區的叢集

  1. 按照以上規劃建立2個杭州和上海地區的vSwitch,然後使用vSwitch建立VPC。具體操作,請參見建立交換器建立專用網路和交換器

  2. 使用上文建立的VPC和網路規劃建立杭州和上海地區的叢集。具體操作,請參見建立Kubernetes託管版叢集

  3. 根據以上規劃建立1個杭州地區的ASM執行個體。具體操作,請參見建立ASM執行個體

步驟二:使用CEN實現跨地區VPC網路互連

使用CEN打通叢集之間的VPC網路,以及叢集和Service Mesh之間的VPC網路。

  1. 登入雲企業網控制台,建立CEN執行個體。具體操作,請參見建立雲企業網執行個體

  2. 建立轉寄路由器。

    1. 雲企業網執行個體頁面,單擊步驟1建立的雲企業網執行個體名稱,然後在基本資料頁簽下方,單擊建立轉寄路由器

    2. 建立轉寄路由器對話方塊,選擇地區,輸入名稱,然後單擊確認

    本樣本配置了兩個轉寄路由器:

    • 地區華東2(上海)名稱shanghai-router

    • 地區華東1(杭州)名稱hangzhou-router

  3. 將VPC添加到轉寄路由器,為上海和杭州兩個轉寄路由器重複下列步驟,將VPC串連到轉寄路由器。

    1. 雲企業網執行個體頁面,單擊步驟1建立的雲企業網執行個體名稱,然後在基本資料頁簽下方,單擊剛建立的轉寄路由器ID,進入轉寄路由器頁面。

    2. 單擊地區內串連管理頁簽,然後單擊建立網路執行個體串連執行個體類型選擇Virtual Private Cloud網路執行個體選擇Region對應的VPC執行個體。

    3. 其他選項保持預設,單擊確定建立

  4. 設定跨地區頻寬。

    1. 單擊步驟2建立的轉寄路由器名稱,在頁面右側,單擊建立網路執行個體串連

    2. 串連網路執行個體對話方塊,配置相關資訊,然後單擊確認建立

      下圖為杭州到上海的樣本。地區表示當前地區對端地區表示目標地區。關於配置項的說明,請參見跨地區串連2023-09-27_15-11-25.png

      建立完成後,您可以在跨地區串連管理頁簽,看到新建立的執行個體。

  5. 添加安全性群組規則。

    本文以Flannel網路外掛程式為例,在兩個叢集的安全性群組內添加對方叢集的Pod網路CIDR,允許對方叢集的Pod網段地址的入向通訊。

    說明

    Terway網路外掛程式請使用叢集vSwitch的CIDR。您可以登入專用網路管理主控台,在交換器頁面的IPv4網段列,擷取vSwitch的CIDR。

    1. 登入Container Service管理主控台,在左側導覽列選擇叢集

    2. 叢集列表頁面,單擊ack-shanghai叢集名稱,然後在叢集資訊頁面的基本資料頁簽,查看ack-shanghai叢集的Pod網路CIDR。

    3. 叢集列表頁面單擊ack-hangzhou叢集右側操作列下的詳情

    4. 叢集資訊頁面單擊叢集資源頁簽,然後單擊安全性群組右側的安全性群組ID。

    5. 安全性群組詳情頁簽入方向下單擊手動添加

    6. 設定協議類型全部為ack-shanghai叢集的Pod網路CIDR,其他為預設值,然後單擊操作列下的儲存

    7. 重複執行以上步驟,查看ack-hangzhou叢集的Pod網路CIDR,然後在ack-shanghai叢集的安全性群組中,添加ack-hangzhou叢集的Pod網路CIDR。

    8. 登入任意hangzhou叢集的ECS, 使用ping命令測試與shanghai叢集中的ECS是否連通。

步驟三:添加叢集到ASM執行個體並建立託管式的入口網關

  1. 將杭州地區和上海地區的兩個叢集添加到ASM執行個體。具體操作,請參見添加叢集到ASM執行個體

  2. 使用以下YAML,建立一個託管式的入口網關。具體操作,請參見建立入口網關

    展開查看託管式的入口網關YAML

    apiVersion: istio.alibabacloud.com/v1beta1
    kind: IstioGateway
    metadata:
      annotations:
        asm.alibabacloud.com/managed-by-asm: 'true'
      name: ingressgateway
      namespace: istio-system
    spec:
      gatewayType: ingress
      dnsPolicy: ClusterFirst
      externalTrafficPolicy: Local
      hostNetwork: false
      ports:
      - name: http
        port: 80
        protocol: TCP
        targetPort: 80
      - name: https
        port: 443
        protocol: TCP
        targetPort: 443
      replicaCount: 1
      resources:
        limits:
          cpu: '2'
          memory: 2G
        requests:
          cpu: 200m
          memory: 256Mi
      rollingMaxSurge: 100%
      rollingMaxUnavailable: 25%
      runAsRoot: true
      serviceType: LoadBalancer

步驟四:部署示範應用Bookinfo

  1. 在ack-hangzhou叢集部署Bookinfo應用。

    1. 使用kubectl串連到ack-hangzhou叢集。具體操作,請參見擷取叢集KubeConfig並通過kubectl工具串連叢集

    2. 使用以下內容,建立ack-hangzhou-k8s.yaml

      展開查看ack-hangzhou-k8s.yaml

      # Details service
      apiVersion: v1
      kind: Service
      metadata:
        name: details
        labels:
          app: details
          service: details
      spec:
        ports:
        - port: 9080
          name: http
        selector:
          app: details
      ---
      apiVersion: v1
      kind: ServiceAccount
      metadata:
        name: bookinfo-details
        labels:
          account: details
      ---
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: details-v1
        labels:
          app: details
          version: v1
      spec:
        replicas: 1
        selector:
          matchLabels:
            app: details
            version: v1
        template:
          metadata:
            labels:
              app: details
              version: v1
          spec:
            serviceAccountName: bookinfo-details
            containers:
            - name: details
              image: docker.io/istio/examples-bookinfo-details-v1:1.16.2
              imagePullPolicy: IfNotPresent
              ports:
              - containerPort: 9080
              securityContext:
                runAsUser: 1000
      ---
      # Ratings service
      apiVersion: v1
      kind: Service
      metadata:
        name: ratings
        labels:
          app: ratings
          service: ratings
      spec:
        ports:
        - port: 9080
          name: http
        selector:
          app: ratings
      ---
      apiVersion: v1
      kind: ServiceAccount
      metadata:
        name: bookinfo-ratings
        labels:
          account: ratings
      ---
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: ratings-v1
        labels:
          app: ratings
          version: v1
      spec:
        replicas: 1
        selector:
          matchLabels:
            app: ratings
            version: v1
        template:
          metadata:
            labels:
              app: ratings
              version: v1
          spec:
            serviceAccountName: bookinfo-ratings
            containers:
            - name: ratings
              image: docker.io/istio/examples-bookinfo-ratings-v1:1.16.2
              imagePullPolicy: IfNotPresent
              ports:
              - containerPort: 9080
              securityContext:
                runAsUser: 1000
      ---
      # Reviews service
      apiVersion: v1
      kind: Service
      metadata:
        name: reviews
        labels:
          app: reviews
          service: reviews
      spec:
        ports:
        - port: 9080
          name: http
        selector:
          app: reviews
      ---
      apiVersion: v1
      kind: ServiceAccount
      metadata:
        name: bookinfo-reviews
        labels:
          account: reviews
      ---
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: reviews-v1
        labels:
          app: reviews
          version: v1
      spec:
        replicas: 1
        selector:
          matchLabels:
            app: reviews
            version: v1
        template:
          metadata:
            labels:
              app: reviews
              version: v1
          spec:
            serviceAccountName: bookinfo-reviews
            containers:
            - name: reviews
              image: docker.io/istio/examples-bookinfo-reviews-v1:1.16.2
              imagePullPolicy: IfNotPresent
              env:
              - name: LOG_DIR
                value: "/tmp/logs"
              ports:
              - containerPort: 9080
              volumeMounts:
              - name: tmp
                mountPath: /tmp
              - name: wlp-output
                mountPath: /opt/ibm/wlp/output
              securityContext:
                runAsUser: 1000
            volumes:
            - name: wlp-output
              emptyDir: {}
            - name: tmp
              emptyDir: {}
      ---
      # Productpage services
      apiVersion: v1
      kind: Service
      metadata:
        name: productpage
        labels:
          app: productpage
          service: productpage
      spec:
        ports:
        - port: 9080
          name: http
        selector:
          app: productpage
      ---
      apiVersion: v1
      kind: ServiceAccount
      metadata:
        name: bookinfo-productpage
        labels:
          account: productpage
      ---
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: productpage-v1
        labels:
          app: productpage
          version: v1
      spec:
        replicas: 1
        selector:
          matchLabels:
            app: productpage
            version: v1
        template:
          metadata:
            labels:
              app: productpage
              version: v1
          spec:
            serviceAccountName: bookinfo-productpage
            containers:
            - name: productpage
              image: docker.io/istio/examples-bookinfo-productpage-v1:1.16.2
              imagePullPolicy: IfNotPresent
              ports:
              - containerPort: 9080
              volumeMounts:
              - name: tmp
                mountPath: /tmp
              securityContext:
                runAsUser: 1000
            volumes:
            - name: tmp
              emptyDir: {}
      ---
      
    3. 執行以下命令,在ack-hangzhou叢集部署Bookinfo應用。

      kubectl apply -f ack-hangzhou-k8s.yaml
  2. 在ack-shanghai叢集部署Bookinfo應用。

    1. 使用kubectl串連到ack-shanghai叢集。具體操作,請參見擷取叢集KubeConfig並通過kubectl工具串連叢集

      說明

      使用kubectl串連到ack-shanghai叢集時,您需要將ack-hangzhou叢集的kubeconfig切換成ack-shanghai叢集的kubeconfig。

    2. 使用以下內容,建立ack-shanghai.yaml

      展開查看ack-shanghai.yaml

      # Details service
      apiVersion: v1
      kind: Service
      metadata:
        name: details
        labels:
          app: details
          service: details
      spec:
        ports:
        - port: 9080
          name: http
        selector:
          app: details
      ---
      apiVersion: v1
      kind: ServiceAccount
      metadata:
        name: bookinfo-details
        labels:
          account: details
      ---
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: details-v1
        labels:
          app: details
          version: v1
      spec:
        replicas: 1
        selector:
          matchLabels:
            app: details
            version: v1
        template:
          metadata:
            labels:
              app: details
              version: v1
          spec:
            serviceAccountName: bookinfo-details
            containers:
            - name: details
              image: docker.io/istio/examples-bookinfo-details-v1:1.16.2
              imagePullPolicy: IfNotPresent
              ports:
              - containerPort: 9080
              securityContext:
                runAsUser: 1000
      ---
      # Ratings service
      apiVersion: v1
      kind: Service
      metadata:
        name: ratings
        labels:
          app: ratings
          service: ratings
      spec:
        ports:
        - port: 9080
          name: http
        selector:
          app: ratings
      ---
      apiVersion: v1
      kind: ServiceAccount
      metadata:
        name: bookinfo-ratings
        labels:
          account: ratings
      ---
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: ratings-v1
        labels:
          app: ratings
          version: v1
      spec:
        replicas: 1
        selector:
          matchLabels:
            app: ratings
            version: v1
        template:
          metadata:
            labels:
              app: ratings
              version: v1
          spec:
            serviceAccountName: bookinfo-ratings
            containers:
            - name: ratings
              image: docker.io/istio/examples-bookinfo-ratings-v1:1.16.2
              imagePullPolicy: IfNotPresent
              ports:
              - containerPort: 9080
              securityContext:
                runAsUser: 1000
      ---
      # Reviews service
      apiVersion: v1
      kind: Service
      metadata:
        name: reviews
        labels:
          app: reviews
          service: reviews
      spec:
        ports:
        - port: 9080
          name: http
        selector:
          app: reviews
      ---
      apiVersion: v1
      kind: ServiceAccount
      metadata:
        name: bookinfo-reviews
        labels:
          account: reviews
      ---
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: reviews-v2
        labels:
          app: reviews
          version: v2
      spec:
        replicas: 1
        selector:
          matchLabels:
            app: reviews
            version: v2
        template:
          metadata:
            labels:
              app: reviews
              version: v2
          spec:
            serviceAccountName: bookinfo-reviews
            containers:
            - name: reviews
              image: docker.io/istio/examples-bookinfo-reviews-v2:1.16.2
              imagePullPolicy: IfNotPresent
              env:
              - name: LOG_DIR
                value: "/tmp/logs"
              ports:
              - containerPort: 9080
              volumeMounts:
              - name: tmp
                mountPath: /tmp
              - name: wlp-output
                mountPath: /opt/ibm/wlp/output
              securityContext:
                runAsUser: 1000
            volumes:
            - name: wlp-output
              emptyDir: {}
            - name: tmp
              emptyDir: {}
      ---
      # Productpage services
      apiVersion: v1
      kind: Service
      metadata:
        name: productpage
        labels:
          app: productpage
          service: productpage
      spec:
        ports:
        - port: 9080
          name: http
        selector:
          app: productpage
      ---
      apiVersion: v1
      kind: ServiceAccount
      metadata:
        name: bookinfo-productpage
        labels:
          account: productpage
      ---
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: productpage-v1
        labels:
          app: productpage
          version: v1
      spec:
        replicas: 1
        selector:
          matchLabels:
            app: productpage
            version: v1
        template:
          metadata:
            labels:
              app: productpage
              version: v1
          spec:
            serviceAccountName: bookinfo-productpage
            containers:
            - name: productpage
              image: docker.io/istio/examples-bookinfo-productpage-v1:1.16.2
              imagePullPolicy: IfNotPresent
              ports:
              - containerPort: 9080
              volumeMounts:
              - name: tmp
                mountPath: /tmp
              securityContext:
                runAsUser: 1000
            volumes:
            - name: tmp
              emptyDir: {}
      ---
      	  
    3. 執行以下命令,在ack-shanghai叢集部署Bookinfo應用。

      kubectl apply -f ack-shanghai.yaml
    4. 使用kubectl串連到ASM。具體操作,請參見通過控制面kubectl訪問Istio資源

      說明

      使用kubectl串連到ASM時,您需要將ack-shanghai叢集的kubeconfig切換成ASM的kubeconfig。

  3. 在ASM中建立路由規則。

    1. 使用以下內容,建立asm.yaml

      展開查看asm.yaml

      apiVersion: networking.istio.io/v1alpha3
      kind: Gateway
      metadata:
        name: bookinfo-gateway
      spec:
        selector:
          istio: ingressgateway # use istio default controller
        servers:
        - port:
            number: 80
            name: http
            protocol: HTTP
          hosts:
          - "*"
      ---
      apiVersion: networking.istio.io/v1alpha3
      kind: VirtualService
      metadata:
        name: bookinfo
      spec:
        hosts:
        - "*"
        gateways:
        - bookinfo-gateway
        http:
        - match:
          - uri:
              exact: /productpage
          - uri:
              prefix: /static
          - uri:
              exact: /login
          - uri:
              exact: /logout
          - uri:
              prefix: /api/v1/products
          route:
          - destination:
              host: productpage
              port:
                number: 9080
      ---
      apiVersion: networking.istio.io/v1alpha3
      kind: DestinationRule
      metadata:
        name: productpage
      spec:
        host: productpage
        subsets:
        - name: v1
          labels:
            version: v1
      ---
      apiVersion: networking.istio.io/v1alpha3
      kind: DestinationRule
      metadata:
        name: reviews
      spec:
        host: reviews
        subsets:
        - name: v1
          labels:
            version: v1
        - name: v2
          labels:
            version: v2
        - name: v3
          labels:
            version: v3
      ---
      apiVersion: networking.istio.io/v1alpha3
      kind: DestinationRule
      metadata:
        name: ratings
      spec:
        host: ratings
        subsets:
        - name: v1
          labels:
            version: v1
        - name: v2
          labels:
            version: v2
        - name: v2-mysql
          labels:
            version: v2-mysql
        - name: v2-mysql-vm
          labels:
            version: v2-mysql-vm
      ---
      apiVersion: networking.istio.io/v1alpha3
      kind: DestinationRule
      metadata:
        name: details
      spec:
        host: details
        subsets:
        - name: v1
          labels:
            version: v1
        - name: v2
          labels:
            version: v2
      ---
      	  
    2. 執行以下命令,建立路由規則。

      kubectl apply -f asm.yaml
  4. 驗證Bookinfo應用是否部署成功。

    1. 登入Container Service管理主控台

    2. 在控制台左側導覽列,單擊叢集

    3. 叢集列表頁面單擊ack-hangzhou叢集右側操作列下的詳情

    4. 在叢集管理頁左側導覽列,選擇網路 > 服務

    5. 服務頁面頂部設定命名空間為Istio-system,查看istio-ingressgateway右側External IP下連接埠為80的IP地址。

    6. 在瀏覽器地址欄中輸入入口網關IP地址/productpage

      多次重新整理頁面,可以看到以下圖片輪流出現。review1review1

步驟五:使用跨地區流量分布和跨地區容錯移轉

設定跨地區流量分布

  1. 登入ASM控制台,在左側導覽列,選擇服務網格 > 網格管理

  2. 網格管理頁面,單擊目標執行個體名稱,然後在左側導覽列,選擇網格執行個體 > 基本資料

  3. 基本資料頁面,單擊跨地區負載平衡右側的啟用跨地區流量分布

    說明

    如果您已經啟用跨地區容錯移轉,您需要禁用跨地區容錯移轉後,才能啟用跨地區流量分布。

  4. 跨地區流量分布對話方塊設定策略為cn-hangzhou,然後單擊建立策略

  5. 單擊展開表徵圖,然後單擊添加表徵圖,設定目標為cn-hangzhou,權重為90%。

  6. 單擊添加表徵圖,設定目標為cn-shanghai,權重為10%,單擊確認

  7. 執行以下命令,迴圈請求10次Bookinfo應用,驗證跨地區流量分布是否成功。

    for ((i=1;i<=10;i++));do curl http://<ack-hangzhou叢集中80連接埠的入口網關地址>/productpage 2>&1|grep full.stars;done

    預期輸出:

    <!-- full stars: -->
    <!-- full stars: -->

    可以看到訪問10次,輸出2行full stars,說明10次請求中9次路由到了ack-hangzhou叢集的v1版本reviews服務,1次路由到了ack-shanghai叢集的v2版本reviews服務,流量按照權重路由到多個叢集成功。

設定跨地區容錯移轉

  1. 停用ack-hangzhou叢集的review。

    1. 登入Container Service管理主控台

    2. 在控制台左側導覽列,單擊叢集

    3. 在叢集管理頁左側導覽列,選擇工作負載 > 無狀態

    4. 無狀態版面設定命名空間為default,單擊reviews-v1右側操作列下的伸縮

    5. 伸縮版面設定所需容器組數量為0,然後單擊確定

  2. 配置DestinationRule。

    配置DestinationRule,當1s內無法請求到reviews服務,該reviews服務將被移除1min。

    1. 登入ASM控制台

    2. 在左側導覽列,選擇服務網格 > 網格管理

    3. 網格管理頁面,找到待配置的執行個體,單擊執行個體的名稱或在操作列中單擊管理

    4. 在網格詳情頁面左側導覽列,選擇流量管理中心 > 目標規則

    5. 目標規則頁面單擊reviews右側操作列下的YAML

    6. 編輯面板增加以下內容,然後單擊確定

      spec:
        ......
        trafficPolicy:
          connectionPool:
            http:
              maxRequestsPerConnection: 1
          outlierDetection:
            baseEjectionTime: 1m
            consecutive5xxErrors: 1
            interval: 1s
      • maxRequestsPerConnection:最大串連數量。

      • baseEjectionTime:最小的移除時間長度。

      • consecutive5xxErrors:連續錯誤數量。

      • interval:移除檢測的時間間隔。

  3. 啟用跨地區容錯移轉。

    1. 在網格詳情頁面左側導覽列,選擇網格執行個體 > 基本資料

    2. 基本資料頁面單擊跨地區負載平衡右側的啟用跨地區容錯移轉

      說明

      如果您已經啟用跨地區流量分布,您需要禁用跨地區流量分布後,才能啟用跨地區容錯移轉。

    3. 跨地區容錯移轉對話方塊中設定當策略源是cn-shanghai,源容錯移轉至cn-hangzhou,當策略源是cn-hangzhou,源容錯移轉至cn-shanghai,然後單擊確認

  4. 執行以下命令,迴圈請求10次Bookinfo應用,並對路由到v2版本reviews服務的結果數量進行統計。

    for ((i=1;i<=10;i++));do curl http://<ack-hangzhou叢集中80連接埠的入口網關地址>/productpage 2>&1|grep full.stars;done|wc -l

    預期輸出:

    20

    可以看到訪問10次,返回20(每次路由到v2版本reviews服務會返回兩行包含full stars的結果),說明10次請求全部路由到了ack-shanghai叢集的v2版本reviews服務,跨地區容錯移轉成功。

FAQ

為什麼通過雲企業網CEN打通了叢集VPC網路,在ASM中加入K8s叢集仍然提示失敗?

當您的叢集處於不同地區,在打通叢集VPC網路時,您若未購買跨地區流量包,或者正確設定跨地區流量,ASM控制平面將無法串連到資料平面叢集,導致ASM添加叢集失敗。

針對以上這個問題,您需要重新在雲企業網CEN中設定跨地區流量打通叢集VPC網路,具體操作,請參見步驟二:使用CEN實現跨地區VPC網路互連