多叢集網關(Multi-cluster Gateways)是ACK One為多雲、多叢集環境提供的雲原生網關,通過託管MSE Ingress並使用Ingress API以管理七層南北向流量。多叢集網關支援同城自動容災和基於Header的灰階發布,可以幫您簡化多叢集應用的營運和節省成本,結合ACK One GitOps的能力,您可以快速構建同城多活或主備容災系統(不包含資料容災)。
容災概述
目前雲上容災主要分為以下三類:
同城跨AZ容災
同城容災包含多活容災和主備容災,同城中心之間物理距離較近,網路延遲低,可防範AZ層級性質的災難損害,例如火災、斷網或斷電等。
跨地區多活容災
跨地區多活容災對於網路延遲相對較高,但可以防範地區性質的災難損害,例如地震、水災等。
兩地三中心
兩地三中心將同城雙中心和跨地區災備結合起來,兼具兩者的優點,適用於對應用與資料連續性和可用性要求高的情境。
而從實際情況考慮,同城容災相比於跨地區容災,在資料容災方面更容易實現,所以同城容災仍然具有非常重要的意義。
功能優勢
基於多叢集網關的容災方案與基於DNS流量分發的容災方案對比優勢如下:
基於DNS流量分發的容災方案需要多個LB IP(每個叢集1個),而基於多叢集網關的容災方案在地區層級僅需要1個LB IP,且預設提供同地區多可用性區域的高可用性。
基於多叢集網關的容災支援七層路由轉寄能力,而基於DNS流量分發的容災不支援七層路由轉寄。
基於DNS流量分發的容災方案在IP切換時,通常會有用戶端緩衝而造成服務短暫不可用,而基於多叢集網關的容災方案則可以平滑地將流量Fallback到另一個叢集的服務後端。
多叢集網關是地區層級的,所以所有操作都僅需在Fleet執行個體中操作(建立網關、Ingress資源等),無需在每個ACK叢集中都安裝Ingress Controller和建立Ingress資源,提供地區級全域流量管理能力的同時,還能減少多叢集管理成本。
方案架構
ACK One多叢集網關通過託管MSE Ingress來實現,結合ACK One GitOps的應用多叢集分發能力,可以協助您快速實現應用的同城容災系統。本文將通過GitOps部署樣本應用到中國(香港)地區的兩個不同可用性區域的ACK叢集(Cluster 1、Cluster 2)為例,介紹如何?同城多活容災和同城主備容災。
本文樣本應用為Web應用,包含Deployment、Service資源,通過多叢集網關實現同城容災的方案架構如下圖所示。
在ACK One Fleet中通過MseIngressConfig資源來建立MSE網關。
在同一個地區的兩個不同可用性區域AZ 1和AZ 2中,分別建立一個ACK叢集Cluster 1和Cluster 2。
通過ACK One GitOps將應用分發到已建立的Cluster 1和Cluster 2叢集中。
建立多叢集網關後,通過設定流量規則可以實現按權重路由流量、根據Header將流量路由到指定叢集的能力,當其中一個叢集異常時,流量將自動路由到另一個叢集中。
前提條件
已開啟艦隊管理功能。具體操作,請參見開啟艦隊管理功能。
ACK One Fleet已關聯2個與Fleet執行個體相同VPC的ACK叢集。具體操作,請參見添加關聯集群。
已從ACK One控制台擷取Fleet執行個體的KubeConfig,並通過kubectl串連至Fleet執行個體。
- 說明
關於多叢集網關計費的更多資訊,請參見計費規則。
已在ACK One Fleet執行個體中建立Namespace,該Namespace與關聯集群中部署應用的Namespace一致(本文樣本的Namespace為
gateway-demo)
步驟一:使用GitOps部署應用到多個叢集
通過ArgoCD UI部署
登入ACK One控制台,在左側導覽列選擇。
在GitOps頁面,單擊GitOps控制台跳轉至GitOps頁面。
說明若ACK One艦隊的Fleet執行個體未開啟GitOps,請先單擊開啟GitOps,才能登入GitOps控制台。
如需通過公網訪問GitOps,請開通公網訪問GitOps。
添加應用倉庫。
在ArgoCD UI左側導覽列選擇Settings,然後選擇 。
在彈出的面板中配置以下資訊,然後單擊CONNECT添加串連。
地區
參數
參數值
Choose your connection method
VIA HTTPS
CONNECT REPO USING HTTPS
Type
git
Project
default
Repository URL
https://github.com/AliyunContainerService/gitops-demo.git
Skip server verification
勾選

串連添加成功後會顯示Git的CONNECTION STATUS為Successful。

建立應用。
在ArgoCD的Applications頁面中,單擊+ NEW APP,進行如下參數配置。
地區
參數
說明
GENERAL
Application Name
自訂應用程式名稱。
Project Name
default
SYNC POLICY
可根據實際情況選擇同步策略。取值:
Manual:當Git端有變更時,需手動執行同步動作將其部署至目的地組群。
Automatic:ArgoCD Server每隔3分鐘自動檢測Git端的變更並將其自動部署至目的地組群。
SYNC OPTIONS
勾選
AUTO-CREATE NAMESPACE。SOURCE
Repository URL
在下拉式清單選擇已有Git Repo,此處選擇上一步已添加的
https://github.com/AliyunContainerService/gitops-demo.git。Revision
選擇Branches:
gateway-demo。Path
manifests/helm/web-demo
DESTINATION
Cluster URL
選擇叢集1或叢集2的URL。
也可以單擊右側的
URL,切換為根據CLUSTER NAME欄位選擇。Namespace
本樣本使用
gateway-demo。表示應用資源(Service、Deployment)將被建立在此Namespace下。Helm
Parameters
envCluster值設定為cluster-demo-1或cluster-demo-2,用於區分請求由哪個叢集的後端處理。
通過ArgoCD CLI部署
在ACK One Fleet執行個體中開啟GitOps。具體操作,請參見在ACK One Fleet執行個體中開啟GitOps。
訪問ArgoCD。具體操作,請參見通過ArgoCD CLI方式訪問ArgoCD。
建立並發布應用。
執行以下命令,添加Git Repo。
argocd repo add https://github.com/AliyunContainerService/gitops-demo.git --name ackone-gitops-demos預期輸出:
Repository 'https://github.com/AliyunContainerService/gitops-demo.git' added執行以下命令,查看已添加的Git Repo列表。
argocd repo list預期輸出:
TYPE NAME REPO INSECURE OCI LFS CREDS STATUS MESSAGE PROJECT git https://github.com/AliyunContainerService/gitops-demo.git false false false false Successful default執行以下命令,查看Clusters列表。
argocd cluster list預期輸出:
SERVER NAME VERSION STATUS MESSAGE PROJECT https://1.1.XX.XX:6443 c83f3cbc90a****-temp01 1.22+ Successful https://2.2.XX.XX:6443 c83f3cbc90a****-temp02 1.22+ Successful https://kubernetes.default.svc in-cluster Unknown Cluster has no applications and is not being monitored.使用Application方式建立並發布Demo應用到目的地組群。
使用以下內容,建立apps-web-demo.yaml檔案。
其中
repoURL需替換為您實際的倉庫地址。執行以下命令,部署應用。
kubectl apply -f apps-web-demo.yaml執行以下命令,查看應用列表。
argocd app list預期輸出:
# app list NAME CLUSTER NAMESPACE PROJECT STATUS HEALTH SYNCPOLICY CONDITIONS REPO PATH TARGET argocd/web-demo-cluster1 https://10.1.XX.XX:6443 default Synced Healthy Auto <none> https://github.com/AliyunContainerService/gitops-demo.git manifests/helm/web-demo main argocd/web-demo-cluster2 https://10.1.XX.XX:6443 default Synced Healthy Auto <none> https://github.com/AliyunContainerService/gitops-demo.git manifests/helm/web-demo main
步驟二:在Fleet執行個體中通過kubectl建立多叢集網關
通過在ACK One Fleet中建立MseIngressConfig對象來建立一個多叢集網關,並將關聯集群添加至多叢集網關。
擷取ACK One Fleet執行個體的虛擬交換器ID並記錄。具體操作,請參見擷取交換器ID。
使用以下內容,建立gateway.yaml檔案。
說明請將
${vsw-id1}和${vsw-id2}替換為您上一步擷取的交換器ID,${cluster1}、${cluster2}替換為您待添加的關聯集群ID。子叢集
${cluster1}、${cluster2}的安全性群組的入方向需要允許該交換器網段的IP和所有連接埠通過。
apiVersion: mse.alibabacloud.com/v1alpha1 kind: MseIngressConfig metadata: annotations: mse.alibabacloud.com/remote-clusters: ${cluster1},${cluster2} name: ackone-gateway-hongkong spec: common: instance: replicas: 3 spec: 2c4g network: vSwitches: - ${vsw-id} ingress: local: ingressClass: mse name: mse-ingress參數
說明
mse.alibabacloud.com/remote-clusters
表示待添加到多叢集網關的叢集。此處所填的是已經關聯到Fleet執行個體的叢集ID。
spec.name
網關執行個體名稱。
spec.common.instance.spec
可選,網關執行個體規格。預設為
4c8g。spec.common.instance.replicas
可選,網關執行個體副本數。預設為3個。
spec.ingress.local.ingressClass
可選,待監聽的ingressClass名稱,表示監聽Fleet執行個體中所有
ingressClass欄位設定為mse的Ingress。執行以下命令,部署多叢集網關。
kubectl apply -f gateway.yaml執行以下命令,驗證多叢集網關是否建立成功並處於監聽狀態。
kubectl get mseingressconfig ackone-gateway-hongkong預期輸出:
NAME STATUS AGE ackone-gateway-hongkong Listening 3m15s預期輸出中網關狀態為
Listening,表明雲原生網關建立成功處於運行狀態,並自動監聽叢集中IngressClass為mse的Ingress資源。通過MseIngressConfig建立的多叢集網關會按照Pending、Running、Listening的狀態依次變化。各狀態說明如下:
Pending:表明雲原生網關正在建立中,需等待3分鐘左右。
Running:表明雲原生網關建立成功,並處於運行狀態。
Listening:表明雲原生網關處於運行狀態,並監聽叢集中Ingress資源。
Failed:表明雲原生網關處於非法狀態,可以查看Status欄位中的Message來進一步明確原因。
執行以下命令,確認關聯集群是否添加成功。
kubectl get mseingressconfig ackone-gateway-hongkong -ojsonpath="{.status.remoteClusters}"預期輸出:
[{"clusterId":"c7fb82****"},{"clusterId":"cd3007****"}]預期輸出中已包含指定的Cluster ID,並且無Failed資訊,表明關聯集群已成功添加至多叢集網關。
步驟三:使用Ingress實現同城容災
多叢集網關通過Ingress對多叢集流量進行管理,您可以在ACK One Fleet執行個體中建立Ingress對象來實現同城多活容災和同城主備容災。
確認您已經在Fleet執行個體中建立Namespacegateway-demo,此處建立的Ingress需要和上一步部署的Demo應用中Service的Namespace保持一致為gateway-demo。
同城多活容災
建立Ingress實現同城多活容災
在ACK One Fleet執行個體中建立以下Ingress對象,可以實現同城多活容災。
預設將流量負載平衡到已添加到多叢集網關的兩個叢集的同名服務後端的每個副本中,如果其中的Cluster 1後端異常,網關自動將流量全都路由到Cluster 2。Cluster 1和Cluster 2的副本數比為9:1,所以預設90%流量被路由到Cluster 1, 10%流量被路由到Cluster 2,在Cluster 1後端全部異常後,100%流量自動被路由到Cluster 2。拓撲如下所示:
使用以下內容,建立ingress-demo.yaml檔案。
以下代碼中,通過網域名稱
example.com下的/svc1路由規則暴露後端服務service1。apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: web-demo spec: ingressClassName: mse rules: - host: example.com http: paths: - path: /svc1 pathType: Exact backend: service: name: service1 port: number: 80執行以下命令,在ACK One Fleet執行個體中部署Ingress。
kubectl apply -f ingress-demo.yaml -n gateway-demo
實現灰階發布驗證
在多活容災情境下,不影響業務的前提下,您可以通過以下方式對應用進行灰階發布驗證。
在已有叢集中建立應用,僅將Service和Deployment的name和selector與原應用進行區分,之後基於Header在建立的應用上進行驗證。
使用以下內容,在Cluster 1中建立new-app.yaml檔案。僅Service和Deployment與原應用有差異,其他均一致。
apiVersion: v1 kind: Service metadata: name: service1-canary-1 namespace: gateway-demo spec: ports: - port: 80 protocol: TCP targetPort: 8080 selector: app: web-demo-canary-1 sessionAffinity: None type: ClusterIP --- apiVersion: apps/v1 kind: Deployment metadata: name: web-demo-canary-1 namespace: gateway-demo spec: replicas: 1 selector: matchLabels: app: web-demo-canary-1 template: metadata: labels: app: web-demo-canary-1 spec: containers: - env: - name: ENV_NAME value: cluster-demo-1-canary image: 'registry-cn-hangzhou.ack.aliyuncs.com/acs/web-demo:0.6.0' imagePullPolicy: Always name: web-demo執行以下命令,在Cluster 1中部署新的應用。
kubectl apply -f new-app.yaml使用以下內容,建立new-ingress.yaml檔案。
在Fleet執行個體中建立基於Header的Ingress。通過添加Annotations開啟Canary,並指定Header,在請求中使用Header:
canary-dest: cluster1來將流量路由到灰階版本進行驗證。nginx.ingress.kubernetes.io/canary:設定為"true",表示開啟灰階發布能力。nginx.ingress.kubernetes.io/canary-by-header:請求到該叢集的header key。nginx.ingress.kubernetes.io/canary-by-header-value:請求到該叢集的header value。apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: web-demo-canary-1 namespace: gateway-demo annotations: nginx.ingress.kubernetes.io/canary: "true" nginx.ingress.kubernetes.io/canary-by-header: "canary-dest" nginx.ingress.kubernetes.io/canary-by-header-value: "cluster1" spec: ingressClassName: mse rules: - host: example.com http: paths: - path: /svc1 pathType: Exact backend: service: name: service1-canary-1 port: number: 80
執行以下命令,在Fleet執行個體中部署基於Header的Ingress。
kubectl apply -f new-ingress.yaml
驗證同城多活容災實現效果
修改部署到Cluster 1的副本數為9,Cluster 2的副本數為1,即期望預設流量按照9:1路由到Cluster 1和Cluster 2,並且在Cluster1異常後,自動將所有流量路由到Cluster 2。
執行以下命令,擷取多叢集網關的對外IP。
kubectl get ingress web-demo -n gateway-demo -ojsonpath="{.status.loadBalancer}"預設流量按比例路由到兩個叢集
執行以下命令,查看流量的路由情況。
替換以下
XX.XX.XX.XX為上一步擷取的多叢集網關的對外IP。for i in {1..100}; do curl -H "host: example.com" XX.XX.XX.XX done預期輸出:
預期輸出表明,流量被負載平衡到了Cluster 1和Cluster 2,到Cluster 1和Cluster 2的流量比為9:1。Cluster 1異常後流量全部容災到Cluster 2
如果將Cluster 1的Deployment的
replica縮為0時,得到的輸出結果如下,表明流量已被自動容災到Cluster 2。
通過Header將請求路由到灰階版本
執行以下命令,查看流量的路由情況。
替換以下
XX.XX.XX.XX為實現灰階發布驗證中的應用和Ingress部署完成後查詢到的IP。for i in {1..100}; do curl -H "host: example.com" -H "canary-dest: cluster1" xx.xx.xx.xx/svc1; sleep 1; done預期輸出:
預期輸出表明,添加了header:canary-dest: cluster1的請求都被路由到了Cluster 1中的灰階版本。
同城主備容災
在ACK One Fleet執行個體中建立以下Ingress對象,可以實現同城主備容災。
當兩個叢集後端都正常時,流量僅路由到Cluster 1的服務後端;如果其中一個Cluster 1後端異常,網關會自動將流量路由到Cluster 2。拓撲如下所示:
建立Ingress實現同城主備容災
使用以下內容,建立ingress-demo-cluster-one.yaml檔案。
以下Ingress對象的YAML檔案中,通過添加兩個Annotations
mse.ingress.kubernetes.io/service-subset、mse.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 spec: ingressClassName: mse rules: - host: example.com http: paths: - path: /service1 pathType: Exact backend: service: name: service1 port: number: 80
執行以下命令,在ACK One Fleet執行個體中部署Ingress。
kubectl apply -f ingress-demo-cluster-one.yaml -ngateway-demo
實現叢集層級灰階發布
多叢集網關支援建立基於Header的Ingress以實現將請求路由到指定叢集,基於該能力與建立Ingress實現同城主備容災中Ingress對象實現的全副本負載平衡的能力,可以實現基於Header的灰階發布。
已建立Ingress實現同城主備容災中的Ingress。
在ACK One Fleet執行個體中建立包含Header相關Annotation的Ingress,實現叢集層級的灰階發布。請求的Header與Ingress中的配置相匹配時,請求將被路由到灰階版本的後端。
使用以下內容,建立ingress-demo-cluster-gray.yaml檔案。
以下Ingress對象的YAML檔案中,替換YAML中的
${cluster1-id}為目的地組群ID。除了mse.ingress.kubernetes.io/service-subset和mse.ingress.kubernetes.io/subset-labels兩個Annotation之外,您還需要添加以下Annotation以實現網域名稱example.com下的/service1路由規則暴露後端服務service1nginx.ingress.kubernetes.io/canary:設定為"true",表示開啟灰階發布能力。nginx.ingress.kubernetes.io/canary-by-header:表示請求到該叢集的header key。nginx.ingress.kubernetes.io/canary-by-header-value:表示請求到該叢集的header value。
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-by-header: "app-web-demo-version" nginx.ingress.kubernetes.io/canary-by-header-value: "gray" name: web-demo-cluster-gray name: web-demo spec: ingressClassName: mse rules: - host: example.com http: paths: - path: /service1 pathType: Exact backend: service: name: service1 port: number: 80執行以下命令,在ACK One Fleet執行個體中部署Ingress。
kubectl apply -f ingress-demo-cluster-gray.yaml -n gateway-demo
驗證同城主備容災實現效果
為便於驗證,修改部署到Cluster 1和Cluster 2的副本數都為1,期望預設流量只被路由到Cluster 1,加灰階Header的流量被路由到Cluster 2,當Cluster 1應用異常後,預設流量也被路由到Cluster 2。
執行以下命令,擷取多叢集網關的對外IP。
kubectl get ingress web-demo -n gateway-demo -ojsonpath="{.status.loadBalancer}"預設流量路由到Cluster 1
執行以下命令,查看預設流量是否被路由到Cluster 1。
替換以下
XX.XX.XX.XX為上一步擷取的多叢集網關的對外IP。for i in {1..100}; do curl -H "host: example.com" xx.xx.xx.xx/service1; sleep 1; done預期輸出:
預期輸出表明,預設流量全都被路由到Cluster 1了。通過header將請求路由到灰階版本
執行以下命令,查看Header的請求是否被路由到灰階版本。
替換以下
XX.XX.XX.XX為上一步擷取的多叢集網關的對外IP。for i in {1..50}; do curl -H "host: example.com" -H "app-web-demo-version: gray" xx.xx.xx.xx/service1; sleep 1; done預期輸出:
預期輸出表明,添加了Header:app-web-demo-version: gray的請求都被路由到了Cluster 2(灰階版本)。Cluster 1異常後流量被容災到Cluster 2
如果將Cluster 1的Deployment的
replica縮為0時,得到的輸出結果如下,表明流量已被自動容災到Cluster 2。
相關文檔
如需瞭解ACK One多叢集網關的南北流量管理能力,請參見管理南北流量。
關於ACK One GitOps應用分發的相關操作,請參見GitOps快速入門。