全部產品
Search
文件中心

Alibaba Cloud Service Mesh:通過ASM多主控制面架構實現多叢集容災

更新時間:Oct 31, 2024

Service Mesh (ASM)支援多主控制面架構,即由多個服務網格執行個體共同管理多個Kubernetes叢集的架構模式。多主控制面架構相比單個ASM執行個體添加多個Kubernetes叢集,在配置隔離、配置下發延遲等方面有明顯優勢,更適用於搭建業務對等部署的多叢集容災方案。本文將介紹如何基於兩個ACK叢集搭建包含兩個ASM執行個體的多主控制面架構。

背景資訊

多主控制面架構是一種使用服務網格管理多個Kubernetes叢集的架構模式。在這種架構中,多個服務網格執行個體分別管理各自的Kubernetes叢集的資料面組件,並為叢集中的網格代理分發配置。同時,這些執行個體依靠共用的根信任認證,實現跨叢集的服務發現和通訊。

相比直接在一個ASM執行個體中添加多個叢集,多主控制面架構有著以下優勢:

  • 擁有更好的配置推送延遲表現:多個叢集通常跨地區、可用性區域或VPC部署。在這種情況下,使用多個ASM執行個體分別串連到就近的Kubernetes叢集中的網格代理擁有更好的配置推送效能表現。

  • 配置和環境隔離性更好:多個叢集分別由多個ASM執行個體管理。每個ASM執行個體可以部署不同的控制面資源,從而實現對配置和版本的灰階或隔離。同時,在升級ASM執行個體時可以多個控制面分批進行升級,從而更好地確保線上環境的可用性。

  • 穩定性表現更佳:遇到可用性區域、地區不可用或網路問題等極端情況時,一個控制面串連所有叢集的方式,可能會出現叢集因為無法串連到控制面而無法同步配置或啟動的問題;而在多主控制面架構下,正常地區或可用性區域中的網格代理仍可正常串連到控制面,不影響服務網格配置的下發與網格代理的正常啟動。

構建多主控制面架構,需要建立複用相同網格根憑證的多個ASM執行個體。網格根憑證是控制面為網格代理簽發身分識別驗證所用認證時使用的根憑證。通過複用相同的根憑證,串連到每個ASM執行個體的網格代理之間可以實現相互信任以及使用mTLS協議相互訪問。

前提條件

已建立兩個Kubernetes叢集,分別命名為cluster-1和cluster-2,都設定為開啟使用EIP暴露API Server。具體操作,請參見建立ACK託管叢集

步驟一:建立兩個複用根憑證的ASM執行個體,並各添加一個叢集

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

  2. 網格管理頁單擊建立新網格,具體建立時使用的關鍵配置項見下表。

    配置項

    樣本值

    網格名稱

    mesh-1。

    地區

    選擇和cluster-1叢集相同的地區。

    Istio版本

    選擇v1.22.6.71-g7d67a80b-aliyun或以上版本。

    Kubernetes叢集

    選擇cluster-1,選擇後,專用網路、交換器配置項將會自動填滿。

    具體操作以及其他配置項的說明,請參見建立ASM執行個體。建立後,稍等2-3分鐘直至mesh-1執行個體的狀態轉變為運行中

  3. 再次在網格管理頁單擊建立新網格,具體建立時使用的關鍵配置項見下表。

    配置項

    樣本值

    網格名稱

    mesh-2。

    地區

    選擇和cluster-2叢集相同的地區。

    Istio版本

    選擇v1.22.6.71-g7d67a80b-aliyun或以上版本。

    Kubernetes叢集

    選擇cluster-2,選擇後,專用網路、交換器配置項將會自動填滿。

    網格根憑證

    單擊展開進階選項,選中複用已有ASM執行個體根憑證,在下方下拉框中選擇mesh-1。

    具體操作以及其他配置項的說明與mesh-1相同。建立後,稍等2-3分鐘直至mesh-2執行個體的狀態轉變為運行中

步驟二:以僅服務發現模式將叢集添加到ASM執行個體

步驟一執行後,mesh-1執行個體將會添加並管理cluster-1叢集,mesh-2執行個體將會添加並管理cluster-2叢集。此外,兩個ASM執行個體還需要以僅服務發現模式添加對方所管理的叢集,以發現對方叢集中的服務以及服務端點。

  1. 在mesh-1執行個體中以僅服務發現模式添加cluster-2叢集。

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

    2. 網格管理頁面,單擊目標執行個體名稱mesh-1,然後在左側導覽列,選擇叢集與工作負載管理 > Kubernetes叢集,然後單擊添加

    3. 在添加Kubernetes叢集頁面,找到cluster-2叢集,然後單擊叢集操作列中的添加(僅服務發現)。在彈出的對話方塊中單擊確定。添加叢集後,在網格執行個體 > 基本資料頁面,可以看到ASM執行個體的狀態變為更新中。數秒之後(時間長度與添加的叢集數量有關),單擊頁面右上方的image,ASM執行個體的狀態會變為運行中。在Kubernetes叢集頁面,可以看到已添加叢集的資訊。

      image

  2. 在mesh-2執行個體中以僅服務發現模式添加cluster-1叢集。

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

    2. 網格管理頁面,單擊目標執行個體名稱mesh-2,然後在左側導覽列,選擇叢集與工作負載管理 > Kubernetes叢集,然後單擊添加

    3. 在添加Kubernetes叢集頁面,找到cluster-2叢集,然後單擊叢集操作列中的添加(僅服務發現)。在彈出的對話方塊中單擊確定。添加叢集後,在網格執行個體 > 基本資料頁面,可以看到ASM執行個體的狀態變為更新中。數秒之後(時間長度與添加的叢集數量有關),單擊頁面右上方的image,ASM執行個體的狀態會變為運行中。在Kubernetes叢集頁面,可以看到已添加叢集的資訊。

      image

重要

當以僅服務發現模式添加Kubernetes叢集時,ASM執行個體僅會對該叢集內的服務以及服務端點進行服務發現,但不會向該叢集下發任何資料面組件。同時,針對ASM執行個體所做的任何配置修改無法作用於以僅服務發現模式添加的Kubernetes叢集。

僅服務發現模式僅適用於構建多主控制面架構的情境。如果您希望ASM執行個體直接管理您的Kubernetes叢集,請直接將叢集添加到ASM執行個體。具體操作,請參見添加叢集到ASM執行個體

步驟三(可選):在兩個ASM執行個體中進行多叢集網路設定

如果cluster-1、cluster-2兩個Kubernetes叢集分別位於不同的網路(即兩個叢集存在跨VPC、跨地區等情況),且叢集間網路沒有通過CEN打通,則需要在兩個ASM執行個體中進行多叢集網路設定,並為cluster-1、cluster-2分別部署跨叢集網格代理,以保證叢集間的相互訪問可達。關於跨叢集網格代理的更多資訊,請參見使用ASM跨叢集網格代理實現多叢集跨網路互連

  1. 在mesh-1執行個體中配置cluster-1和cluster-2叢集的網路設定。

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

    2. 網格管理頁面,單擊目標執行個體mesh-1名稱,然後在左側導覽列,選擇叢集與工作負載管理 > Kubernetes叢集

    3. 單擊多叢集網路設定按鈕,按照以下方式配置多叢集網路。

      1. 為cluster-1叢集指定所屬邏輯網路為network1,並為cluster-1叢集啟用跨叢集網格代理訪問。

      2. 為cluster-2叢集指定所屬邏輯網路為network2。

    image

  1. 在mesh-1執行個體中配置cluster-1和cluster-2叢集的網路設定。

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

    2. 網格管理頁面,單擊目標執行個體mesh-1名稱,然後在左側導覽列,選擇叢集與工作負載管理 > Kubernetes叢集

    3. 單擊多叢集網路設定按鈕,按照以下方式配置多叢集網路。

      1. 為cluster-1叢集指定所屬邏輯網路為network1。

      2. 為cluster-2叢集指定所屬邏輯網路為network2,並為cluster-1叢集啟用跨叢集網格代理訪問。

    image

步驟四:在兩個ASM執行個體中部署樣本應用

如下圖所示,本節將在cluster-1部署sleep服務和helloworld服務的v1版本,cluster-2部署helloworld服務的v2版本。兩個叢集中的服務可以通過ASM跨叢集網路代理程式實現相互訪問。

  1. 在mesh-1執行個體和mesh-2執行個體中為default命名空間開啟自動注入,具體操作,參考管理全域命名空間

  2. 使用以下內容,建立sleep應用和helloworld應用的v1版本。

    展開查看YAML內容

    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: sleep
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: sleep
      labels:
        app: sleep
        service: sleep
    spec:
      ports:
      - port: 80
        name: http
      selector:
        app: sleep
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: sleep
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: sleep
      template:
        metadata:
          labels:
            app: sleep
        spec:
          terminationGracePeriodSeconds: 0
          serviceAccountName: sleep
          containers:
          - name: sleep
            image: registry.cn-hangzhou.aliyuncs.com/acs/curl:8.1.2
            command: ["/bin/sleep", "infinity"]
            imagePullPolicy: IfNotPresent
            volumeMounts:
            - mountPath: /etc/sleep/tls
              name: secret-volume
          volumes:
          - name: secret-volume
            secret:
              secretName: sleep-secret
              optional: true
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: helloworld
      labels:
        app: helloworld
    spec:
      ports:
      - port: 5000
        name: http
      selector:
        app: helloworld
    ---
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: helloworld
      labels:
        account: helloworld
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: helloworld-v1
      labels: 
        apps: helloworld
        version: v1
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: helloworld
          version: v1
      template:
        metadata:
          labels:
            app: helloworld
            version: v1
        spec:
          serviceAccount: helloworld
          serviceAccountName: helloworld
          containers:
          - name: helloworld
            image: registry-cn-hangzhou.ack.aliyuncs.com/ack-demo/examples-helloworld-v1:1.0
            imagePullPolicy: IfNotPresent 
            ports:
            - containerPort: 5000
  3. 在cluster-1中部署此YAML。具體操作,請參見通過編排模板建立Linux應用

  4. 使用以下內容,建立helloworld應用的v2版本。

    展開查看YAML內容

    apiVersion: v1
    kind: Service
    metadata:
      name: helloworld
      labels:
        app: helloworld
    spec:
      ports:
      - port: 5000
        name: http
      selector:
        app: helloworld
    ---
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: helloworld
      labels:
        account: helloworld
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: helloworld-v2
      labels: 
        apps: helloworld
        version: v2
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: helloworld
          version: v2
      template:
        metadata:
          labels:
            app: helloworld
            version: v2
        spec:
          serviceAccount: helloworld
          serviceAccountName: helloworld
          containers:
          - name: helloworld
            image: registry-cn-hangzhou.ack.aliyuncs.com/ack-demo/examples-helloworld-v2:1.0
            imagePullPolicy: IfNotPresent 
            ports:
            - containerPort: 5000
  5. 在cluster-2中部署此YAML。具體操作,請參見通過編排模板建立Linux應用

步驟五:驗證多主控制面架構下部署的應用互相訪問

  1. 使用cluster-1叢集的kubeconfig,執行以下命令。

     kubectl exec -it deploy/sleep -- sh -c 'for i in $(seq 1 10); do curl helloworld:5000/hello; done;'

    預期輸出:

    Hello version: v1, instance: helloworld-v1-7b888xxxxx-xxxxx
    Hello version: v1, instance: helloworld-v1-7b888xxxxx-xxxxx
    Hello version: v2, instance: helloworld-v2-7b949xxxxx-xxxxx
    Hello version: v2, instance: helloworld-v2-7b949xxxxx-xxxxx
    Hello version: v1, instance: helloworld-v1-7b888xxxxx-xxxxx
    Hello version: v2, instance: helloworld-v2-7b949xxxxx-xxxxx
    Hello version: v2, instance: helloworld-v2-7b949xxxxx-xxxxx
    Hello version: v2, instance: helloworld-v2-7b949xxxxx-xxxxx
    Hello version: v2, instance: helloworld-v2-7b949xxxxx-xxxxx
    Hello version: v1, instance: helloworld-v1-7b888xxxxx-xxxxx

    可以看到helloworld的版本在v1和v2之間來回切換。

  2. 執行以下命令,將cluster-1叢集中的sleep應用的Pod副本數量改為0。

    kubectl scale deploy sleep --replicas=0
  3. 使用以下內容建立單獨的sleep應用。

    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: sleep
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: sleep
      labels:
        app: sleep
        service: sleep
    spec:
      ports:
      - port: 80
        name: http
      selector:
        app: sleep
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: sleep
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: sleep
      template:
        metadata:
          labels:
            app: sleep
        spec:
          terminationGracePeriodSeconds: 0
          serviceAccountName: sleep
          containers:
          - name: sleep
            image: registry.cn-hangzhou.aliyuncs.com/acs/curl:8.1.2
            command: ["/bin/sleep", "infinity"]
            imagePullPolicy: IfNotPresent
  4. 在cluster-2叢集中部署以上內容。具體操作,請參見通過編排模板建立Linux應用

  5. 使用cluster-2叢集的kubeconfig再次執行以下命令。

     kubectl exec -it deploy/sleep -- sh -c 'for i in $(seq 1 10); do curl helloworld:5000/hello; done;'

    預期輸出:

    Hello version: v1, instance: helloworld-v1-7b888xxxxx-xxxxx
    Hello version: v2, instance: helloworld-v2-7b949xxxxx-xxxxx
    Hello version: v2, instance: helloworld-v2-7b949xxxxx-xxxxx
    Hello version: v2, instance: helloworld-v2-7b949xxxxx-xxxxx
    Hello version: v2, instance: helloworld-v2-7b949xxxxx-xxxxx
    Hello version: v1, instance: helloworld-v1-7b888xxxxx-xxxxx
    Hello version: v2, instance: helloworld-v2-7b949xxxxx-xxxxx
    Hello version: v1, instance: helloworld-v1-7b888xxxxx-xxxxx
    Hello version: v2, instance: helloworld-v2-7b949xxxxx-xxxxx
    Hello version: v2, instance: helloworld-v2-7b949xxxxx-xxxxx

    可以看到helloworld的版本仍然在v1和v2之間來回切換。