ACK One多集群网关基于MSE Ingress提供了强大的多集群南北向流量的管理,可以快速帮您实现同城应用多活容灾、流量多集群负载均衡、基于Header路由流量到指定集群等能力。本文介绍如何通过多集群网关管理多集群应用的南北流量。
背景信息
多集群网关优势
在容器服务领域,管理集群内服务的南北向流量的常用方式是使用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.git
Revision
设置为HEAD
Path
设置为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 2
Ingress对象,然后再创建以下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上。