全部產品
Search
文件中心

Alibaba Cloud Service Mesh:使用ASM跨叢集網格代理實現多叢集跨網路互連

更新時間:Nov 09, 2024

阿里雲ASM支援將多個ACK叢集整合在一個ASM執行個體中,為分布廣泛的服務提供統一的管理和營運平台。ASM跨叢集網格代理提供了更為靈活的多叢集網路互聯方案,本文將介紹如何在多叢集情境下利用跨叢集網格代理打通叢集通訊。

背景資訊

ASM支援多叢集模式,即使用者可以在同一個ASM執行個體中加入多個ACK叢集。 您可以在ASM中加入多個不同網路下的ACK叢集,若多叢集的網路不具備打通三層網路的條件(設施限制、CIDR衝突、費用等原因),則可以利用ASM網關打通叢集網路,使用ASM跨叢集網格代理可以靈活使用公、私人網路將叢集網路聯通,無感解決地址衝突問題,實現多叢集統一的流量治理、安全防護以及全鏈路可觀測。本文將以Sleep應用跨叢集訪問httpbin為例介紹如何在ASM環境下利用跨叢集網格代理配置跨網路多叢集互連。

能力優勢

ASM 1.22及以上版本提供的跨叢集網格代理完整實現了七層用戶端負載平衡,跨叢集調用情境下,所有路由能力與非跨叢集負載平衡完全對齊。

前提條件

  • 已建立ASM執行個體,版本不低於1.22。具體操作,請參見建立ASM執行個體

  • 已添加多個叢集到ASM執行個體。具體操作,請參見添加叢集到ASM執行個體。(本文樣本為兩個)。

  • 已開啟ASM自動注入。具體操作,請參見啟用自動注入

  • 服務之間跨叢集訪問需要滿足以下兩個條件之一:

    • 開啟了ASM的在ASM中使用DNS代理(推薦)。

    • 手動在用戶端所在的叢集建立一個和服務端叢集相同的目標Service。

步驟一:為ASM控制面綁定公網IP

為了使與ASM執行個體不在同一網路的叢集中的資料平面組件可以正確地串連到ASM控制平面,需要為ASM控制平面Pilot使用的SLB執行個體綁定EIP,以將Pilot暴露於公網。

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

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

  3. 基本資料頁面右側,找到Istio Pilot 地址並單擊綁定EIP

說明

綁定EIP到Pilot負載平衡後,若刪除ASM執行個體時未解除綁定,EIP將隨ASM執行個體釋放。

步驟二:為叢集指定網路設定,並啟用跨叢集網格代理

您可以為每個叢集指定一個邏輯網路。同一個邏輯網路之間的服務可以直接互相訪問,不同邏輯網路之間的服務需要通過跨叢集網格代理才可以訪問。

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

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

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

    • 為ACK-1指定所屬邏輯網路為network1。

    • 為ACK-2指定所屬邏輯網路為network2,並且在ACK-2中啟用跨叢集網格代理訪問

    image

應用上述配置後,ASM會為您在ACK-2中建立一個預設跨叢集網格代理,該網關具有公網IP。ACK-1中的服務將會自動通過這個跨叢集網格代理訪問到ACK-2中的服務,並且這條鏈路預設會啟用mTLS加密。

您可以通過ASM叢集的kubeconfig查看跨叢集網格代理的定義,跨叢集網格代理有一個特殊的名稱:asm-cross-network-${ACK ID}。您可以根據自己的需求,自行調節網關的資源和副本數等配置。

說明

目前跨叢集網格代理是一個TCP Proxy,無法進行L7負載平衡。可能在某些情況下存在負載不均衡的情況。

步驟三:驗證跨叢集訪問

上述步驟中的網路設定需要在業務Pod啟動時生效。如果修改網路設定之前已經啟動了業務Pod,則需要重啟業務Pod。

  1. 在ACK-1中建立Sleep應用,樣本YAML配置如下:

    sleep.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
    ---
  2. 在ACK-2中建立httpbin應用,樣本YAML配置如下:

    httpbin.yaml

    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: httpbin
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: httpbin
      labels:
        app: httpbin
        service: httpbin
    spec:
      ports:
      - name: http
        port: 8000
        targetPort: 80
      selector:
        app: httpbin
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: httpbin
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: httpbin
          version: v1
      template:
        metadata:
          labels:
            app: httpbin
            version: v1
        spec:
          serviceAccountName: httpbin
          containers:
          - image: registry-cn-hangzhou.ack.aliyuncs.com/ack-demo/httpbin:0.1.0
            imagePullPolicy: IfNotPresent
            name: httpbin
            ports:
            - containerPort: 80
  3. 從Sleep對應的Pod中訪問httpbin應用(使用ACK-1的kubeconfig)。

    1. 擷取Sleep Pod名稱。

      kubectl get pod | grep sleep
    2. 在Sleep中使用curl訪問httpbin。

      kubectl exec ${sleep pod名稱} -- curl httpbin:8000/status/418

      此時可以看到訪問成功,輸出如下所示:

        % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                       Dload  Upload   Total   Spent    Left  Speed
      100   135  100   135    0     0  16075      0 --:--:-- --:--:-- --:--:-- 16875
      
          -=[ teapot ]=-
      
             _...._
           .'  _ _ `.
          | ."` ^ `". _,
          \_;`"---"`|//
            |       ;/
            \_     _/
              `"""`
  4. 驗證Sleep通過跨叢集網格代理訪問了httpbin。

    1. 查看Sleep Pod的日誌(使用ACK-1的kubeconfig)。

      kubectl logs ${sleep pod名稱} -c istio-proxy | tail -1

      輸出如下所示:

      {"authority_for":"httpbin:8000","bytes_received":"0","bytes_sent":"135","downstream_local_address":"xxx.xxx.xxx.xx:8000","downstream_remote_address":"xx.x.xxx.xxx:xxxxx","duration":"7","istio_policy_status":"-","method":"GET","path":"/status/418","protocol":"HTTP/1.1","request_id":"08dc43e9-60c8-4f2f-910a-b727172ce311","requested_server_name":"-","response_code":"418","response_flags":"-","route_name":"default","start_time":"2024-05-23T10:06:27.289Z","trace_id":"-","upstream_cluster":"outbound|8000||httpbin.default.svc.cluster.local","upstream_host":"xxx.xx.xxx.xxx:15443","upstream_local_address":"xx.x.xxx.xxx:60248","upstream_response_time":"7","upstream_service_time":"7","upstream_transport_failure_reason":"-","user_agent":"curl/8.1.2","x_forwarded_for":"-"}

      其中的upstream_host欄位標識Sleep Pod直接存取的目標,可以看到訪問的連接埠是1544315443是跨叢集網格代理專用的連接埠。

    2. 查看跨叢集網格代理的日誌(使用ACK-2的kubeconfig)。

      首先擷取跨叢集網格代理Pod。

      kubectl -n istio-system get pod | grep asm-cross-network
      
      istio-asm-cross-network-c0859be51XXX   1/1     Running   0          20h
      istio-asm-cross-network-c0859be51XXX   1/1     Running   0          20h

      可以看到預設有兩個跨叢集網格代理的Pod。您可以分別查看這兩個Pod的日誌,可以看到類似的訪問日誌。

       kubectl logs istio-asm-cross-network-c0859be51XXX -n istio-system  | tail -1
      
      {"authority_for":"-","bytes_received":"xxxx","bytes_sent":"xxxx","downstream_local_address":"xx.xx.x.xx:15443","downstream_remote_address":"xx.xx.xx.xx:xxxxx","duration":"1568569","istio_policy_status":"-","method":"-","path":"-","protocol":"-","request_id":"-","requested_server_name":"outbound_.8000_._.httpbin.default.svc.cluster.local","response_code":"0","response_flags":"-","route_name":"-","start_time":"2024-05-23T08:41:16.618Z","trace_id":"-","upstream_cluster":"outbound_.8000_._.httpbin.default.svc.cluster.local","upstream_host":"xx.xx.xx.xxx:80","upstream_local_address":"xx.x.xx.xx:xxxxx","upstream_response_time":"-","upstream_service_time":"-","upstream_transport_failure_reason":"-","user_agent":"-","x_forwarded_for":"-"}