通过ACK One ALB多集群网关,结合ACK One GitOps或多集群应用分发,可以快速实现应用的同城多活容灾,保证应用高可用,并在故障发生时自动平滑迁移。本文介绍如何通过多集群网关构建同城容灾系统。
容灾概述
目前云上容灾主要分为以下三类:
同城跨AZ容灾:同城容灾包含同城多活容灾和同城主备容灾2种策略,同城中心之间物理距离较近,网络延迟低,可防范AZ级别性质的灾难损害,例如火灾、断网或断电等。此方案在实现数据备份和快速恢复方面相对简单,仍具备较强的实用意义。
跨地域多活容灾:跨地域多活容灾对于网络延迟相对较高,但可以防范地域性质的灾难损害,例如地震、水灾等。
两地三中心:两地三中心将同城双中心和跨地域灾备结合起来,兼具两者的优点,适用于应用与数据连续性和可用性要求高的场景。
从业务架构上来说,企业的业务系统自上而下通常分为接入层、应用层和数据层。
接入层:流量入口,负责接收流量,根据路由转发规则将流量转发到后端应用层。
应用层:应用服务,根据请求对数据进行处理,并返回给上游。
数据层:数据存储服务,为应用层提供数据和存储数据。
为了实现整个业务容灾,需对上述每一层实施相应的容灾处理措施。
接入层:ACK One多集群网关作为接入层,其自身支持同城跨AZ高可用。
应用层:ACK One多集群网关处理应用层容灾,可实现应用的同城多活/主备容灾、跨地域容灾。
数据层:数据层容灾和数据同步,需要依赖于中间件自身。
功能优势
基于ACK One多集群网关的容灾方案与基于DNS流量分发的容灾方案对比优势如下:
基于DNS流量分发的容灾方案需要多个LB IP(每个集群1个),而基于多集群网关的容灾方案在地域级别仅需要1个LB IP,且默认提供同地域多可用区的高可用性。
基于多集群网关的容灾支持七层路由转发能力,而基于DNS流量分发的容灾不支持七层路由转发。
基于DNS流量分发的容灾方案在IP切换时,通常会因客户端缓存造成服务短暂不可用,而基于多集群网关的容灾方案则可以更平滑地将流量Fallback到另一个集群的服务后端。
多集群网关是地域级别的,所有操作都仅需在Fleet实例中进行,无需在每个ACK集群中安装Ingress Controller和创建Ingress资源。它提供地域级全局流量管理能力的同时,还能减少多集群管理成本。
方案架构
本文以Web应用为示例,展示了通过ALB多集群网关实现同城容灾的方案架构,包括Deployment和Service资源,具体结构如下图所示。
在同一个地域两个不同可用区AZ 1和AZ 2中,分别创建一个ACK集群Cluster 1和Cluster 2。
通过ACK One GitOps将应用分发到已创建的Cluster 1和Cluster 2集群中。
在ACK One Fleet实例中通过AlbConfig资源来创建ALB多集群网关。
创建ALB多集群网关后,通过创建Ingress来实现按权重路由流量、根据Header将流量路由到指定集群的能力,当其中一个集群异常时,流量将自动路由到另一个集群中。
RDS数据同步需要依赖中间件自身能力。
前提条件
已从ACK One控制台获取Fleet实例的KubeConfig,并通过kubectl连接至Fleet实例。
步骤一:使用GitOps或应用分发部署应用到多个集群
ACK One支持多集群GitOps和多集群应用资源分发两种方式,方便您将应用部署到多个集群。请参见GitOps快速入门、创建多集群应用与应用分发快速入门。本步骤以GitOps的多集群应用分发为例。
登录ACK One控制台,在左侧导航栏选择 。
在多集群应用页面左上角,单击舰队名称后的按钮,在下拉列表中选择目标舰队。
单击
进入创建多集群应用 - GitOps页面。说明若您的ACK One Fleet实例未开启GitOps,请先开启GitOps。具体操作,请参见在ACK One Fleet实例中开启GitOps。
如需通过公网访问GitOps,请开通公网访问GitOps。
在YAML创建页签,将以下YAML内容复制到控制台,然后点击确定进行创建和部署应用。
说明以下YAML内容是将
web-demo
部署到所有关联集群中,您也可以通过快捷创建选择集群,变化会同步到YAML创建的内容。apiVersion: argoproj.io/v1alpha1 kind: ApplicationSet metadata: name: appset-web-demo namespace: argocd spec: template: metadata: name: '{{.metadata.annotations.cluster_id}}-web-demo' namespace: argocd spec: destination: name: '{{.name}}' namespace: gateway-demo project: default source: repoURL: https://github.com/AliyunContainerService/gitops-demo.git path: manifests/helm/web-demo targetRevision: main helm: valueFiles: - values.yaml parameters: - name: envCluster value: '{{.metadata.annotations.cluster_name}}' syncPolicy: automated: {} syncOptions: - CreateNamespace=true generators: - clusters: selector: matchExpressions: - values: - cluster key: argocd.argoproj.io/secret-type operator: In - values: - in-cluster key: name operator: NotIn goTemplateOptions: - missingkey=error syncPolicy: preserveResourcesOnDeletion: false goTemplate: true
步骤二:在舰队中通过kubectl创建ALB多集群网关
通过在ACK One Fleet实例中创建AlbConfig对象来创建一个ACK One ALB多集群网关,并为ALB多集群网关添加关联集群。
从ACK One舰队所在VPC,获取两个虚拟交换机ID。
使用以下内容,创建
gateway.yaml
文件。说明请将
${vsw-id1}
和${vsw-id2}
替换为您上一步获取的交换机ID,${cluster1}
、${cluster2}
替换为您待添加的关联集群ID。子集群
${cluster1}
、${cluster2}
的安全组的入方向需要允许该交换机网段的IP和所有端口通过。
apiVersion: alibabacloud.com/v1 kind: AlbConfig metadata: name: ackone-gateway-demo annotations: # 添加要处理流量的关联集群到ALB多集群实例。 alb.ingress.kubernetes.io/remote-clusters: ${cluster1},${cluster2} spec: config: name: one-alb-demo addressType: Internet addressAllocatedMode: Fixed zoneMappings: - vSwitchId: ${vsw-id1} - vSwitchId: ${vsw-id2} listeners: - port: 8001 protocol: HTTP --- apiVersion: networking.k8s.io/v1 kind: IngressClass metadata: name: alb spec: controller: ingress.k8s.alibabacloud/alb parameters: apiGroup: alibabacloud.com kind: AlbConfig name: ackone-gateway-demo
需要同步的参数及其说明如下表所示:
参数
是否必填
说明
metadata.name
是
AlbConfig的名称。
metadata.annotations:
alb.ingress.kubernetes.io/remote-clusters
是
表示待添加到ALB多集群网关的关联集群列表。此处所填的是已经关联到舰队实例的集群ID。
spec.config.name
否
ALB实例的名称。
spec.config.addressType
否
ALB实例的网络类型。取值如下:
Internet(默认值):公网类型。面向公网提供应用型负载均衡服务,公网可访问。
说明应用型负载均衡通过绑定弹性公网IP进行公网服务,使用公网类型ALB实例将收取弹性公网IP的实例费与带宽、流量费用,详情参见按量付费。
Intranet:私网类型。面向VPC内部提供应用型负载均衡服务,公网不可访问。
spec.config.zoneMappings
是
设置ALB交换机ID。创建交换机具体操作请参见创建和管理交换机。
说明指定的交换机必须在ALB当前所支持的可用区内,且与集群处于同一VPC。关于ALB支持的地域与可用区,请参见ALB支持的地域与可用区。
应用型负载均衡支持多可用区部署,若当前地域支持2个及以上可用区,为保障业务高可用,请至少选择2个或以上不同可用区的交换机。
spec.listeners
否
配置ALB的监听端口和协议。本文配置示例为端口8001的HTTP监听。
监听定义了流量进入负载均衡的方式和规则,此处建议保留该配置,否则您需要另行创建监听才可使用ALB Ingress。
执行以下命令,部署
gateway.yaml
,创建ALB多集群网关和IngressClass。kubectl apply -f gateway.yaml
执行以下命令,查看ALB多集群网关是否创建成功(1~3min)。
kubectl get albconfig ackone-gateway-demo
预期输出如下:
NAME ALBID DNSNAME PORT&PROTOCOL CERTID AGE ackone-gateway-demo alb-xxxx alb-xxxx.<regionid>.alb.aliyuncs.com 4d9h
确认关联集群是否添加成功,执行以下命令查看状态。
kubectl get albconfig ackone-gateway-demo -ojsonpath='{.status.loadBalancer.subClusters}'
预期输出为集群ID列表。
步骤三:使用Ingress实现同城容灾
多集群网关通过Ingress对多集群流量进行管理,您可以在ACK One Fleet实例中创建Ingress对象来实现同城多活容灾。
在舰队实例中创建Service所在的Namespace,本示例为
gateway-demo
。使用以下内容,创建
ingress-demo.yaml
文件。说明多个
alb.ingress.kubernetes.io/cluster-weight
注解权重总和必须等于100。通过域名
example.com
下的/svc1
路由规则暴露后端服务service1
。请先替换${cluster1-id}
和${cluster2-id}
。
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: annotations: alb.ingress.kubernetes.io/listen-ports: | [{"HTTP": 8001}] alb.ingress.kubernetes.io/cluster-weight.${cluster1-id}: "20" alb.ingress.kubernetes.io/cluster-weight.${cluster2-id}: "80" name: web-demo namespace: gateway-demo spec: ingressClassName: alb rules: - host: alb.ingress.alibaba.com http: paths: - path: /svc1 pathType: Prefix backend: service: name: service1 port: number: 80
执行以下命令,在ACK One舰队中部署Ingress。
kubectl apply -f ingress-demo.yaml -n gateway-demo
步骤四:验证同城多活容灾效果
流量按设置比例路由到各集群处理
访问服务的格式如下:
curl -H "host: alb.ingress.alibaba.com" alb-xxxx.<regionid>.alb.aliyuncs.com:<listeners port>/svc1
需要同步的参数及其说明如下表所示:
参数 | 说明 |
| 步骤二中获取的AlbConfig的 |
| AlbConfig中定义及Ingress中 |
执行以下命令后,从结果可以看出,请求按照20:80的比例发送到集群1(poc-ack-1)和集群2(poc-ack-2)处理。
for i in {1..500}; do curl -H "host: alb.ingress.alibaba.com" alb-xxxx.cn-beijing.alb.aliyuncs.com:8001/svc1; done > res.txt
某个集群应用异常时流量自动平滑迁移
执行以下命令后,我们手动将集群2的应用副本数设置为0,此时流量自动平滑迁移至集群1。
for i in {1..500}; do curl -H "host: alb.ingress.alibaba.com" alb-xxxx.cn-beijing.alb.aliyuncs.com:8001/svc1; sleep 1; done