服務網格 ASM(Service Mesh)支持多主控制面架構,即由多個服務網格實例共同管理多個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實例,并各添加一個集群
登錄ASM控制臺,在左側導航欄,選擇 。
在網格管理頁單擊創建新網格,具體創建時使用的關鍵配置項見下表。
配置項
示例值
網格名稱
mesh-1。
地域
選擇和cluster-1集群相同的地域。
Istio版本
選擇v1.22.6.71-g7d67a80b-aliyun或以上版本。
Kubernetes集群
選擇cluster-1,選擇后,專有網絡、交換機配置項將會自動填充。
具體操作以及其他配置項的說明,請參見創建ASM實例。創建后,稍等2-3分鐘直至mesh-1實例的狀態轉變為運行中。
再次在網格管理頁單擊創建新網格,具體創建時使用的關鍵配置項見下表。
配置項
示例值
網格名稱
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實例還需要以僅服務發現模式添加對方所管理的集群,以發現對方集群中的服務以及服務端點。
在mesh-1實例中以僅服務發現模式添加cluster-2集群。
登錄ASM控制臺,在左側導航欄,選擇 。
在網格管理頁面,單擊目標實例名稱mesh-1,然后在左側導航欄,選擇集群與工作負載管理 > Kubernetes集群,然后單擊添加。
在添加Kubernetes集群頁面,找到cluster-2集群,然后單擊集群操作列中的添加(僅服務發現)。在彈出的對話框中單擊確定。添加集群后,在網格實例 > 基本信息頁面,可以看到ASM實例的狀態變為更新中。數秒之后(時長與添加的集群數量有關),單擊頁面右上方的,ASM實例的狀態會變為運行中。在Kubernetes集群頁面,可以看到已添加集群的信息。
在mesh-2實例中以僅服務發現模式添加cluster-1集群。
登錄ASM控制臺,在左側導航欄,選擇 。
在網格管理頁面,單擊目標實例名稱mesh-2,然后在左側導航欄,選擇集群與工作負載管理 > Kubernetes集群,然后單擊添加。
在添加Kubernetes集群頁面,找到cluster-1集群,然后單擊集群操作列中的添加(僅服務發現)。在彈出的對話框中單擊確定。添加集群后,在網格實例 > 基本信息頁面,可以看到ASM實例的狀態變為更新中。數秒之后(時長與添加的集群數量有關),單擊頁面右上方的,ASM實例的狀態會變為運行中。在Kubernetes集群頁面,可以看到已添加集群的信息。
當以僅服務發現模式添加Kubernetes集群時,ASM實例僅會對該集群內的服務以及服務端點進行服務發現,但不會向該集群下發任何數據面組件。同時,針對ASM實例所做的任何配置修改無法作用于以僅服務發現模式添加的Kubernetes集群。
僅服務發現模式僅適用于構建多主控制面架構的場景。如果您希望ASM實例直接管理您的Kubernetes集群,請直接將集群添加到ASM實例。具體操作,請參見添加集群到ASM實例。
步驟三(可選):在兩個ASM實例中進行多集群網絡配置
如果cluster-1、cluster-2兩個Kubernetes集群分別位于不同的網絡(即兩個集群存在跨VPC、跨地域等情況),且集群間網絡沒有通過CEN打通,則需要在兩個ASM實例中進行多集群網絡配置,并為cluster-1、cluster-2分別部署跨集群網格代理,以保證集群間的相互訪問可達。關于跨集群網格代理的更多信息,請參見使用ASM跨集群網格代理實現多集群跨網絡互通。
在mesh-1實例中配置cluster-1和cluster-2集群的網絡配置。
登錄ASM控制臺,在左側導航欄,選擇 。
在網格管理頁面,單擊目標實例mesh-1名稱,然后在左側導航欄,選擇集群與工作負載管理 > Kubernetes集群。
單擊多集群網絡配置按鈕,按照以下方式配置多集群網絡。
為cluster-1集群指定所屬邏輯網絡為network1,并為cluster-1集群啟用跨集群網格代理訪問。
為cluster-2集群指定所屬邏輯網絡為network2。
在mesh-2實例中配置cluster-1和cluster-2集群的網絡配置。
登錄ASM控制臺,在左側導航欄,選擇 。
在網格管理頁面,單擊目標實例mesh-2名稱,然后在左側導航欄,選擇集群與工作負載管理 > Kubernetes集群。
單擊多集群網絡配置按鈕,按照以下方式配置多集群網絡。
為cluster-1集群指定所屬邏輯網絡為network1。
為cluster-2集群指定所屬邏輯網絡為network2,并為cluster-2集群啟用跨集群網格代理訪問。
步驟四:在兩個ASM實例中部署示例應用
如下圖所示,本節將在cluster-1部署sleep服務和helloworld服務的v1版本,cluster-2部署helloworld服務的v2版本。兩個集群中的服務可以通過ASM跨集群網絡代理實現相互訪問。
在mesh-1實例和mesh-2實例中為default命名空間開啟自動注入。具體操作,參考管理全局命名空間。
使用以下內容,創建sleep應用和helloworld應用的v1版本。
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
在cluster-1中部署此YAML。具體操作,請參見通過編排模板創建Linux應用。
使用以下內容,創建helloworld應用的v2版本。
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
在cluster-2中部署此YAML。具體操作,請參見通過編排模板創建Linux應用。
步驟五:驗證多主控制面架構下部署的應用互相訪問
使用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之間來回切換。
執行以下命令,將cluster-1集群中的sleep應用的Pod副本數量改為0。
kubectl scale deploy sleep --replicas=0
使用以下內容創建單獨的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
在cluster-2集群中部署以上內容。具體操作,請參見通過編排模板創建Linux應用。
使用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之間來回切換。