ACK One多叢集網關基於MSE Ingress提供了強大的多叢集南北向流量的管理,可以快速幫您實現同城應用多活容災、流量多叢集負載平衡、基於Header路由流量到指定叢集等能力。本文介紹如何通過多叢集網關管理多叢集應用的南北流量。
背景資訊
多叢集網關優勢
在Container Service領域,管理叢集內服務的南北向流量的常用方式是使用Ingress資源進行管理。但Ingress為單叢集維度,無法獨立為多個叢集中的應用流量進行管理,因此,ACK One基於MSE Ingress實現地區級的Global Ingress來統一處理多叢集應用的南北向流量,並提供強大的流量管理能力,協助您快速、低成本地實現同城應用多活容災、流量多叢集負載平衡、基於Header路由流量到指定叢集等能力。此外,多叢集網關使用易上手的Ingress API進行管理,極大地降低了使用門檻。
使用多叢集網關會產生一定的費用,關於多叢集網關的計費資訊,請參見普通執行個體計費概述。
MSE相關文檔
MseIngressConfig是由MSE Ingress Controller提供的CRD資源,用於管理MSE雲原生網關執行個體的生命週期,配置Ingress監聽選項以及全域配置。MseIngressConfig的常見用法,請參見配置MseIngressConfig。
MSE Ingress已支援Nginx-Ingress核心和常用的Annotation,並推出額外的Annotation來彌補Nginx-Ingress的不足。更多資訊,請參見MSE Ingress支援的Annotation。
前提條件
已在ACK One Fleet執行個體中建立Namespace,該Namespace與關聯集群中部署應用的Namespace一致。
步驟一:在ACK One Fleet執行個體中建立多叢集網關
在ACK One Fleet執行個體中建立一個多叢集網關(網關預設可用性區域高可用),並將關聯集群添加至多叢集網關
通過控制台建立
登入ACK One控制台,在左側導覽列選擇。
在多叢集網關頁面右上方單擊建立網關。
在彈出的面板中,根據實際情況修改建立多叢集網關的YAML檔案,然後單擊建立。
通過命令列建立
擷取ACK One Fleet執行個體的虛擬交換器ID並記錄。
執行以下命令,擷取交換器執行個體ID。
aliyun adcp DescribeHubClusterDetails --ClusterId <YOUR_FLEET_CLUSTERID>從預期輸出的
VSwitches中複製一個交換器執行個體ID。
使用以下內容,建立mseingressconfig.yaml檔案。
替換以下
${vsw-id1}為您上一步擷取的交換器ID。您也可以在建立網關時,通過添加Annotation同步指定待添加到多叢集網關的關聯集群。apiVersion: mse.alibabacloud.com/v1alpha1 kind: MseIngressConfig metadata: name: ackone-gateway # 添加關聯集群到MSE網關。 #annotations: # mse.alibabacloud.com/remote-clusters: ${cluster1},${cluster2} spec: common: instance: replicas: 3 spec: 2c4g network: # 公網SLB和內網SLB,可都配置,如果2個欄位都不配置則預設使用公網SLB。 #publicSLBSpec: slb.s2.small #privateSLBSpec: slb.s2.small vSwitches: - ${vsw-id1} ingress: local: ingressClass: mse name: mse-ingress執行以下命令,在ACK One Fleet執行個體中建立一個名為mse-ingress的網關。
kubectl apply -f mseingressconfig.yaml執行以下命令,驗證網關是否建立成功。
kubectl get mseingressconfig ackone-gateway預期輸出:
NAME STATUS AGE ackone-gateway Listening 3m15s預期輸出中網關狀態為Listening,表明雲原生網關建立成功處於運行狀態,並自動監聽叢集中IngressClass為
mse的Ingress資源。通過MseIngressConfig建立的多叢集網關會按照Pending、Running、Listening的狀態依次變化。各狀態說明如下:
Pending:表明雲原生網關正在建立中,需等待3分鐘左右。
Running:表明雲原生網關建立成功,並處於運行狀態。
Listening:表明雲原生網關處於運行狀態,並監聽叢集中Ingress資源。
Failed:表明雲原生網關處於非法狀態,可以查看Status欄位中的Message來進一步明確原因。
步驟二:在多叢集網關中添加關聯集群
通過控制台添加
登入ACK One控制台,在左側導覽列選擇。
在多叢集網關頁面上方的下拉框中選擇要修改的目標多叢集網關,然後在頁面右上方單擊編輯。
在彈出的面板中修改MseIngresConfig.yaml檔案,修改
annotations參數中的叢集ID,然後單擊更新。樣本如下:
annotations: mse.alibabacloud.com/remote-clusters: ${cluster1-id},${cluster2-id}${cluster1-id},${cluster2-id}為添加的關聯集群的ID,多個關聯集群以英文半形逗號(,)間隔,您可以通過修改叢集ID來添加或刪除關聯的叢集。若建立多叢集網關時未添加關聯集群,則MseIngresConfig.yaml檔案中沒有
annotations參數,添加關聯集群時,您需要將以上樣本添加到MseIngresConfig.yaml檔案的metadata對象中,再修改叢集ID。
通過命令列方式添加
在ACK One Fleet執行個體中,通過mseingressconfig對象的Annotation控制多叢集網關中添加或刪除關聯集群。替換以下
${cluster1-id}、${cluster2-id}為您待添加的關聯集群的ID,添加多個關聯集群時,中間以英文半形逗號(,)間隔。annotations: mse.alibabacloud.com/remote-clusters: ${cluster1-id},${cluster2-id}執行以下命令,查看關聯集群是否已成功添加至多叢集網關。
kubectl get mseingressconfig ackone-gateway -ojsonpath="{.status.remoteClusters}"預期輸出:
[{"clusterId":"c7fb82****"},{"clusterId":"cd3007****"}]預期輸出中已包含指定的ClusterID,並且無Failed資訊,表明關聯集群已成功添加至多叢集網關。
步驟三:使用GitOps部署Demo應用
使用GitOps將Demo應用部署到兩個關聯的ACK叢集中。具體操作,請參見GitOps快速入門。
建立2個GitOps Application,分別對應2個關聯集群。樣本:web-demo-cluster1、web-demo-cluster2。
Source配置如下:Repository URL設定為https://github.com/AliyunContainerService/gitops-demo.gitRevision設定為HEADPath設定為manifests/helm/web-demo
DESTINATION分別選擇2個關聯集群,namespace設定為web-demo。Helm Values Files中的參數名稱為envName,value分別為cluster1、cluster2。
部署後的Deployment和Service的YAML檔案如下。
步驟四:使用MSE Ingress管理多叢集流量
通過在Ingress中指定IngressClass來使用MSE Ingress,並且使用不同的Annotation實現不同的流量管理能力。MSE Ingress不僅支援Nginx-Ingress核心和常用的Annotation,還針對Nginx-Ingress Annotation未支援的流量治理配置,推出額外的Annotation以彌補Nginx-Ingress的不足。MSE Ingress支援的Annotations請參見MSE Ingress支援的Annotation。下文以典型的多叢集流量管理情境為例說明。
Ingress對象和Demo應用中Service對象的Namespace需要保持一致。
樣本1:預設負載平衡到所有服務後端
在ACK One Fleet執行個體中建立以下Ingress對象,可以預設將流量負載平衡到所有叢集的同名服務後端,所有副本均衡。路由到不同叢集的流量比例等同於叢集中的副本數量的比例,例如,Cluster 1和Cluster 2中副本數比例為9:1,則流量在Cluster 1和Cluster 2中的流量比也為9:1。本例使用1:1的副本數示範。拓撲如下所示:
使用以下內容,建立ingress-demo.yaml檔案。
以下Ingress對象的YAML檔案中,通過網域名稱
example.com下的/svc1路由規則暴露後端服務service1。apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: web-demo namespace: 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執行以下命令,擷取多叢集網關對外IP。
kubectl get ingress web-demo -nargocd -ojsonpath="{.status.loadBalancer}"執行以下命令,查看流量的路由情況。
替換以下
XX.XX.XX.XX為上一步擷取的多叢集網關對外IP。for i in {1..50}; do curl -H "host: example.com" XX.XX.XX.XX/svc1; sleep 1; done預期輸出:
This is env cluster1 ! Config file is This is env cluster1 ! Config file is This is env cluster1 ! Config file is This is env cluster1 ! Config file is This is env cluster2 ! Config file is This is env cluster1 ! Config file is This is env cluster1 ! Config file is This is env cluster1 ! Config file is This is env cluster1 ! Config file is This is env cluster1 ! Config file is This is env cluster1 ! Config file is預期輸出表明,流量被路由到所有叢集上。
樣本2:流量僅路由到指定叢集
在ACK One Fleet執行個體中建立以下Ingress對象,可以將流量僅路由到Cluster 1的服務後端。拓撲如下所示:
使用以下內容,建立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 namespace: 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-one.yaml執行以下命令,擷取多叢集網關對外IP。
kubectl get ingress web-demo -nargocd -ojsonpath="{.status.loadBalancer}"執行以下命令,查看流量的路由情況。
替換以下
XX.XX.XX.XX為上一步擷取的多叢集網關對外IP。for i in {1..50}; do curl -H "host: example.com" XX.XX.XX.XX/service1; sleep 1; done預期輸出:
This is env cluster1 ! Config file is This is env cluster1 ! Config file is This is env cluster1 ! Config file is This is env cluster1 ! Config file is This is env cluster1 ! ...預期輸出表明,固定的流量被路由到Cluster 1上。
樣本3:根據Header將流量路由到指定叢集
如需根據自訂Header將流量路由到指定叢集的服務後端,您可以在ACK One Fleet執行個體中建立Example 1或者Example 2Ingress對象,然後再建立以下Ingress對象(此Ingress對象無法單獨生效)。拓撲如下所示:
基於Header方式進行流量調度時,您需要在Ingress的註解上配置Canary註解和Header匹配策略,同時需確保已存在另一個Ingress中不包含Canary註解且存在相同的Host + Path訪問另一個叢集中的服務。即Header方式的Ingress不能單獨生效,需搭配使用另一個不指定Header的Ingress指向另一個叢集中的服務。

使用以下內容,建立ingress-demo-header.yaml檔案。
以下Ingress對象的YAML檔案中,通過網域名稱
example.com下的/service1路由規則暴露後端服務service1。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 c15d48ca9d1fd43f9bbb89c56a474843c nginx.ingress.kubernetes.io/canary: "true" nginx.ingress.kubernetes.io/canary-by-header: "stage" nginx.ingress.kubernetes.io/canary-by-header-value: "gray" name: web-demo-cluster-second namespace: 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-header.yaml執行以下命令,擷取多叢集網關對外IP。
kubectl get ingress web-demo -nargocd -ojsonpath="{.status.loadBalancer}"執行以下命令,查看流量的路由情況。
替換以下
XX.XX.XX.XX為上一步擷取的多叢集網關對外IP。for i in {1..50}; do curl -H "host: example.com" -H "stage: gray" xx.xx.xx.xx/service1; sleep 1; done預期輸出:
This is env cluster2 ! Config file is This is env cluster2 ! Config file is This is env cluster2 ! Config file is This is env cluster2 ! Config file is This is env cluster2 ! Config file is ...預期輸出表明,流量根據Header
stage: gray被路由到Cluster 2上。
樣本4:多叢集應用跨叢集容災
多叢集網關具備多叢集應用跨叢集容災的能力,無需額外配置。例如,上述配置的多叢集網關管理了兩個關聯的ACK叢集的流量,如果其中一個叢集的服務異常或被刪除,流量會自動轉到另一個可用叢集。上述樣本1、樣本2、樣本3均一樣,即使已經指定路由到某個叢集,但當此叢集上的應用異常後,也會被容災到其他叢集上。
以下以樣本3為例說明,在正常情況下,添加Header stage: gray,您可以訪問到Cluster 2的後端,當Cluster 2的Deployment副本數被縮為0時,請求會切換至Cluster 1的後端。拓撲如下所示:
執行以下命令,擷取多叢集網關對外IP。
kubectl get ingress web-demo -nargocd -ojsonpath="{.status.loadBalancer}"執行以下命令,查看流量的路由情況。
替換以下
XX.XX.XX.XX為上一步擷取的多叢集網關對外IP。for i in {1..50}; do curl -H "host: example.com" -H "stage: gray" XX.XX.XX.XX/service1; sleep 1; done預期輸出:
This is env cluster1 ! Config file is This is env cluster1 ! Config file is This is env cluster1 ! Config file is This is env cluster1 ! Config file is This is env cluster1 ! Config file is ...預期輸出表明,流量被自動容災到Cluster 1上。
樣本5:根據權重進行流量路由
在樣本1中,您可以通過調節叢集中副本數的比例,實現按比例路由流量到不同的叢集。本樣本介紹如何在Annotations中配置權重來按比例路由流量到不同的叢集,也可以使用該方式進行灰階發布。您可以在ACK One Fleet執行個體中建立以下2個Ingress對象實現該能力,拓撲如下所示:
基於權重方式進行流量調度時,您需要在Ingress的註解上配置Canary註解和Header匹配策略,同時需保證已存在另一個Ingress不含有Canary註解且存在相同的Host + Path訪問另一個叢集中的服務。即權重方式的Ingress不能單獨生效,需搭配使用另一個不指定權重的Ingress指向另一個叢集中的服務。

使用以下內容,建立ingress-weight.yaml檔案。
以下Ingress對象的YAML檔案中,替換YAML中的
${cluster1-id}為目的地組群ID。通過添加Annotations以實現網域名稱example.com下的/svc1-w路由規則暴露後端服務service1。mse.ingress.kubernetes.io/service-subset:服務的子版本名稱。建議定義為與目的地組群相關且可讀性強的值。mse.ingress.kubernetes.io/subset-labels:目標ACK叢集的ID。nginx.ingress.kubernetes.io/canary:設定為"true",表示開啟灰階發布能力。nginx.ingress.kubernetes.io/canary-weight:請求到該叢集的流量百分比(值為0~100的整數)。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-weight namespace: web-demo spec: ingressClassName: mse rules: - host: example.com http: paths: - path: /svc1-w pathType: Exact backend: service: name: service1 port: number: 80 --- 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-weight: "10" name: web-demo-weight-canary namespace: web-demo spec: ingressClassName: mse rules: - host: example.com http: paths: - path: /svc1-w pathType: Exact backend: service: name: service1 port: number: 80
執行以下命令,在ACK One Fleet執行個體中部署Ingress。
kubectl apply -f ingress-weight.yaml -nargocd執行以下命令,擷取多叢集網關對外IP。
kubectl get ingress web-demo -nargocd -ojsonpath="{.status.loadBalancer}"執行以下命令,查看流量的路由情況。
替換以下
XX.XX.XX.XX為上一步擷取的多叢集網關對外IP。for i in {1..50}; do curl -H "host: example.com" XX.XX.XX.XX/svc1-w; sleep 1; done預期輸出:
This is env cluster1 ! Config file is This is env cluster1 ! Config file is This is env cluster1 ! Config file is This is env cluster1 ! Config file is This is env cluster1 ! Config file is This is env cluster1 ! Config file is This is env cluster1 ! Config file is This is env cluster1 ! Config file is This is env cluster1 ! Config file is This is env cluster1 ! Config file is This is env cluster1 ! Config file is This is env cluster2 ! Config file is This is env cluster1 ! Config file is This is env cluster1 ! Config file is This is env cluster1 ! Config file is This is env cluster1 ! Config file is This is env cluster1 ! Config file is This is env cluster1 ! Config file is This is env cluster2 ! Config file is This is env cluster1 ! Config file is ...預期輸出表明,根據權重進行流量路由,90%的流量被路由到Cluster 1上,10%的流量被路由到Cluster 2上。