ACK One多集群網關基于MSE Ingress提供了強大的多集群南北向流量的管理,可以快速幫您實現(xiàn)同城應用多活容災、流量多集群負載均衡、基于Header路由流量到指定集群等能力。本文介紹如何通過多集群網關管理多集群應用的南北流量。
背景信息
多集群網關優(yōu)勢
在容器服務領域,管理集群內服務的南北向流量的常用方式是使用Ingress資源進行管理。但Ingress為單集群維度,無法獨立為多個集群中的應用流量進行管理,因此,ACK One基于MSE Ingress實現(xiàn)地域級的Global Ingress來統(tǒng)一處理多集群應用的南北向流量,并提供強大的流量管理能力,幫助您快速、低成本地實現(xiàn)同城應用多活容災、流量多集群負載均衡、基于Header路由流量到指定集群等能力。此外,多集群網關使用易上手的Ingress API進行管理,極大地降低了使用門檻。
使用多集群網關會產生一定的費用,關于多集群網關的計費信息,請參見普通實例計費概述。
MSE相關文檔
MseIngressConfig是由MSE Ingress Controller提供的CRD資源,用于管理MSE云原生網關實例的生命周期,配置Ingress監(jiān)聽選項以及全局配置。MseIngressConfig的常見用法,請參見配置MseIngressConfig。
MSE Ingress已支持Nginx-Ingress核心和常用的Annotation,并推出額外的Annotation來彌補Nginx-Ingress的不足。更多信息,請參見MSE Ingress支持的Annotation。
前提條件
已在ACK One Fleet實例中創(chuàng)建Namespace,該Namespace與關聯(lián)集群中部署應用的Namespace一致。
步驟一:在ACK One Fleet實例中創(chuàng)建多集群網關
在ACK One Fleet實例中創(chuàng)建一個多集群網關(網關默認可用區(qū)高可用),并將關聯(lián)集群添加至多集群網關
通過控制臺創(chuàng)建
登錄ACK One控制臺,在左側導航欄選擇 。
在多集群網關頁面右上角單擊創(chuàng)建網關。
在彈出的面板中,根據實際情況修改創(chuàng)建多集群網關的YAML文件,然后單擊創(chuàng)建。
通過命令行創(chuàng)建
獲取ACK One Fleet實例的虛擬交換機ID并記錄。
執(zhí)行以下命令,獲取交換機實例ID。
aliyun adcp DescribeHubClusterDetails --ClusterId <YOUR_FLEET_CLUSTERID>
從預期輸出的
VSwitches
中復制一個交換機實例ID。
使用以下內容,創(chuàng)建mseingressconfig.yaml文件。
替換以下
${vsw-id1}
為您上一步獲取的交換機ID。您也可以在創(chuàng)建網關時,通過添加Annotation同步指定待添加到多集群網關的關聯(lián)集群。apiVersion: mse.alibabacloud.com/v1alpha1 kind: MseIngressConfig metadata: name: ackone-gateway # 添加關聯(lián)集群到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
執(zhí)行以下命令,在ACK One Fleet實例中創(chuàng)建一個名為mse-ingress的網關。
kubectl apply -f mseingressconfig.yaml
執(zhí)行以下命令,驗證網關是否創(chuàng)建成功。
kubectl get mseingressconfig ackone-gateway
預期輸出:
NAME STATUS AGE ackone-gateway Listening 3m15s
預期輸出中網關狀態(tài)為Listening,表明云原生網關創(chuàng)建成功處于運行狀態(tài),并自動監(jiān)聽集群中IngressClass為
mse
的Ingress資源。通過MseIngressConfig創(chuàng)建的多集群網關會按照Pending、Running、Listening的狀態(tài)依次變化。各狀態(tài)說明如下:
Pending:表明云原生網關正在創(chuàng)建中,需等待3分鐘左右。
Running:表明云原生網關創(chuàng)建成功,并處于運行狀態(tài)。
Listening:表明云原生網關處于運行狀態(tài),并監(jiān)聽集群中Ingress資源。
Failed:表明云原生網關處于非法狀態(tài),可以查看Status字段中的Message來進一步明確原因。
步驟二:在多集群網關中添加關聯(lián)集群
通過控制臺添加
登錄ACK One控制臺,在左側導航欄選擇 。
在多集群網關頁面上方的下拉框中選擇要修改的目標多集群網關,然后在頁面右上角單擊編輯。
在彈出的面板中修改MseIngresConfig.yaml文件,修改
annotations
參數(shù)中的集群ID,然后單擊更新。示例如下:
annotations: mse.alibabacloud.com/remote-clusters: ${cluster1-id},${cluster2-id}
${cluster1-id}
,${cluster2-id}
為添加的關聯(lián)集群的ID,多個關聯(lián)集群以英文半角逗號(,)間隔,您可以通過修改集群ID來添加或刪除關聯(lián)的集群。若創(chuàng)建多集群網關時未添加關聯(lián)集群,則MseIngresConfig.yaml文件中沒有
annotations
參數(shù),添加關聯(lián)集群時,您需要將以上示例添加到MseIngresConfig.yaml文件的metadata
對象中,再修改集群ID。
通過命令行方式添加
在ACK One Fleet實例中,通過mseingressconfig對象的Annotation控制多集群網關中添加或刪除關聯(lián)集群。替換以下
${cluster1-id}
、${cluster2-id}
為您待添加的關聯(lián)集群的ID,添加多個關聯(lián)集群時,中間以英文半角逗號(,)間隔。annotations: mse.alibabacloud.com/remote-clusters: ${cluster1-id},${cluster2-id}
執(zhí)行以下命令,查看關聯(lián)集群是否已成功添加至多集群網關。
kubectl get mseingressconfig ackone-gateway -ojsonpath="{.status.remoteClusters}"
預期輸出:
[{"clusterId":"c7fb82****"},{"clusterId":"cd3007****"}]
預期輸出中已包含指定的ClusterID,并且無Failed信息,表明關聯(lián)集群已成功添加至多集群網關。
步驟三:使用GitOps部署Demo應用
使用GitOps將Demo應用部署到兩個關聯(lián)的ACK集群中。具體操作,請參見GitOps快速入門。
創(chuàng)建2個GitOps Application,分別對應2個關聯(lián)集群。示例:web-demo-cluster1、web-demo-cluster2。
Source
配置如下:Repository URL
設置為https://github.com/AliyunContainerService/gitops-demo.git
Revision
設置為HEAD
Path
設置為manifests/helm/web-demo
DESTINATION
分別選擇2個關聯(lián)集群,namespace
設置為web-demo
。Helm Values Files
中的參數(shù)名稱為envName
,value
分別為cluster1
、cluster2
。
部署后的Deployment和Service的YAML文件如下。
apiVersion: apps/v1 kind: Deployment metadata: labels: app: web-demo app.kubernetes.io/instance: web-demo-cluster1 name: web-demo namespace: web-demo spec: replicas: 1 selector: matchLabels: app: web-demo template: metadata: labels: app: web-demo spec: containers: - name: web-demo image: acr-multiple-clusters-registry.cn-hangzhou.cr.aliyuncs.com/ack-multiple-clusters/web-demo:0.4.0 env: - name: ENV_NAME value: cluster1 --- apiVersion: v1 kind: Service metadata: name: service1 namespace: web-demo spec: ports: - port: 80 protocol: TCP targetPort: 8080 selector: app: web-demo sessionAffinity: None type: ClusterIP
步驟四:使用MSE Ingress管理多集群流量
通過在Ingress中指定IngressClass來使用MSE Ingress,并且使用不同的Annotation實現(xiàn)不同的流量管理能力。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實例中創(chuàng)建以下Ingress對象,可以默認將流量負載均衡到所有集群的同名服務后端,所有副本均衡。路由到不同集群的流量比例等同于集群中的副本數(shù)量的比例,例如,Cluster 1和Cluster 2中副本數(shù)比例為9:1,則流量在Cluster 1和Cluster 2中的流量比也為9:1。本例使用1:1的副本數(shù)演示。拓撲如下所示:
使用以下內容,創(chuàng)建ingress-demo.yaml文件。
以下Ingress對象的YAML文件中,通過域名
example.com
下的/svc1
路由規(guī)則暴露后端服務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
執(zhí)行以下命令,在ACK One Fleet實例中部署Ingress。
kubectl apply -f ingress-demo.yaml
執(zhí)行以下命令,獲取多集群網關對外IP。
kubectl get ingress web-demo -nargocd -ojsonpath="{.status.loadBalancer}"
執(zhí)行以下命令,查看流量的路由情況。
替換以下
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實例中創(chuàng)建以下Ingress對象,可以將流量僅路由到Cluster 1的服務后端。拓撲如下所示:
使用以下內容,創(chuàng)建ingress-demo-cluster-one.yaml文件。
以下Ingress對象的YAML文件中,通過添加兩個Annotations
mse.ingress.kubernetes.io/service-subset
、mse.ingress.kubernetes.io/subset-labels
以實現(xiàn)域名example.com
下的/service1
路由規(guī)則暴露后端服務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
執(zhí)行以下命令,在ACK One Fleet實例中部署Ingress。
kubectl apply -f ingress-demo-cluster-one.yaml
執(zhí)行以下命令,獲取多集群網關對外IP。
kubectl get ingress web-demo -nargocd -ojsonpath="{.status.loadBalancer}"
執(zhí)行以下命令,查看流量的路由情況。
替換以下
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實例中創(chuàng)建Example 1
或者Example 2
Ingress對象,然后再創(chuàng)建以下Ingress對象(此Ingress對象無法單獨生效)。拓撲如下所示:
基于Header方式進行流量調度時,您需要在Ingress的注解上配置Canary注解和Header匹配策略,同時需確保已存在另一個Ingress中不包含Canary注解且存在相同的Host + Path訪問另一個集群中的服務。即Header方式的Ingress不能單獨生效,需搭配使用另一個不指定Header的Ingress指向另一個集群中的服務。
使用以下內容,創(chuàng)建ingress-demo-header.yaml文件。
以下Ingress對象的YAML文件中,通過域名
example.com
下的/service1
路由規(guī)則暴露后端服務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
執(zhí)行以下命令,在ACK One Fleet實例中部署Ingress。
kubectl apply -f ingress-demo-header.yaml
執(zhí)行以下命令,獲取多集群網關對外IP。
kubectl get ingress web-demo -nargocd -ojsonpath="{.status.loadBalancer}"
執(zhí)行以下命令,查看流量的路由情況。
替換以下
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:多集群應用跨集群容災
多集群網關具備多集群應用跨集群容災的能力,無需額外配置。例如,上述配置的多集群網關管理了兩個關聯(lián)的ACK集群的流量,如果其中一個集群的服務異常或被刪除,流量會自動轉到另一個可用集群。上述示例1、示例2、示例3均一樣,即使已經指定路由到某個集群,但當此集群上的應用異常后,也會被容災到其他集群上。
以下以示例3為例說明,在正常情況下,添加Header stage: gray
,您可以訪問到Cluster 2的后端,當Cluster 2的Deployment副本數(shù)被縮為0時,請求會切換至Cluster 1的后端。拓撲如下所示:
執(zhí)行以下命令,獲取多集群網關對外IP。
kubectl get ingress web-demo -nargocd -ojsonpath="{.status.loadBalancer}"
執(zhí)行以下命令,查看流量的路由情況。
替換以下
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中,您可以通過調節(jié)集群中副本數(shù)的比例,實現(xiàn)按比例路由流量到不同的集群。本示例介紹如何在Annotations中配置權重來按比例路由流量到不同的集群,也可以使用該方式進行灰度發(fā)布。您可以在ACK One Fleet實例中創(chuàng)建以下2個Ingress對象實現(xiàn)該能力,拓撲如下所示:
基于權重方式進行流量調度時,您需要在Ingress的注解上配置Canary注解和Header匹配策略,同時需保證已存在另一個Ingress不含有Canary注解且存在相同的Host + Path訪問另一個集群中的服務。即權重方式的Ingress不能單獨生效,需搭配使用另一個不指定權重的Ingress指向另一個集群中的服務。
使用以下內容,創(chuàng)建ingress-weight.yaml文件。
以下Ingress對象的YAML文件中,替換YAML中的
${cluster1-id}
為目標集群ID。通過添加Annotations以實現(xiàn)域名example.com
下的/svc1-w
路由規(guī)則暴露后端服務service1
。mse.ingress.kubernetes.io/service-subset
:服務的子版本名稱。建議定義為與目標集群相關且可讀性強的值。mse.ingress.kubernetes.io/subset-labels
:目標ACK集群的ID。nginx.ingress.kubernetes.io/canary
:設置為"true"
,表示開啟灰度發(fā)布能力。nginx.ingress.kubernetes.io/canary-weight
:請求到該集群的流量百分比(值為0~100的整數(shù))。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
執(zhí)行以下命令,在ACK One Fleet實例中部署Ingress。
kubectl apply -f ingress-weight.yaml -nargocd
執(zhí)行以下命令,獲取多集群網關對外IP。
kubectl get ingress web-demo -nargocd -ojsonpath="{.status.loadBalancer}"
執(zhí)行以下命令,查看流量的路由情況。
替換以下
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上。