【阅读原文】戳:服务网格容灾系列场景(一):使用服务网格应对地域级故障容灾
地域级故障是云上业务可能遭遇的一种极端类型的故障。当地域级故障发生时,特定地域下任何可用区内的服务都面临着无法连接、数据丢失以及工作负载无法运行等风险。产生地域级故障的可能原因包括但不限于:
• 自然灾害:地震、洪水等灾害可能导致数据中心的结构受损、电力中断等故障。
• 电信网络问题:主要ISP出现故障,影响云服务的可达性,或是关键通信线路的光纤断裂导致网络中断。
• 人为错误:运维人员错误的操作指令导致一个地域内的工作负载无法正常运行等情况。
• 安全事件:如大规模的分布式拒绝服务攻击。
服务网格ASM支持将ASM入口网关部署在Kubernetes集群中或弹性容器实例ECI上、作为业务应用统一的流量入口,并在每个集群中拥有独立的流量入口IP地址。通过这种方式,ASM网关可以结合阿里云云解析DNS和全局流量管理GTM[1] ,在正常的时候,两个地域的ASM入口网关按照指定比例各自接收一部分流量;当其中一个地域发生故障的时候把故障IP剔除,并将流量全部转移到正常地域,以实现对地域级故障的容灾。
容灾架构一览
如上图,为验证应对地域级别的故障,需要在多地域环境下、每个地域分别准备一个Kubernetes集群(下文以双地域、双集群为例),并在每个集群中完全对等地部署业务云原生服务,服务之间通过k8s集群域名相互调用,并且每个集群中对等服务的名称保持完全相同。同时,每个地域的集群均需要部署ASM网关,并配置ASM网关通过公网CLB对外暴露一个公网入口IP地址,并使用云解析DNS和全局流量管理GTM,将域名分别解析到两个IP地址。
当发生地域级别的故障时,另一个健康地域中的业务不受影响、仍可正常工作。同时,由于ASM网关将工作负载分布式地部署在两个地域的集群中,部署在健康地域中的ASM网关仍可正常地接收流量,发挥作为流量入口的功能。此时,通过全局流量管理GTM可将故障地域IP剔除出解析池,并将流量全部解析至健康地域的ASM网关上。
您可以启用如下的服务网格功能,以妥善处理地域故障下的流量转移行为:
1. 可以为ASM网关启用扩缩容HPA:当突发流量到来时迅速扩容出更多的ASM网关实例,以承接突发流量。
2. 可以为ASM网关或集群中的关键服务配置限流:当突发流量到来时,ASM的限流功能能够拒绝掉超过集群内服务承受能力的请求、以防止健康地域中的应用服务被故障转移的大量流量打垮。同时,可以为ASM限流配置指标观测与告警,方便第一时间观测并发现故障事件、及时对健康地域中的服务工作负载进行扩容。
容灾配置实践
步骤一:在两个地域中分别部署一个Kubernetes集群
要实现地域级故障的容灾,必须通过跨地域的方式部署两个Kubernetes集群。
创建两个Kubernetes集群,分别命名为cluster-1和cluster-2,都设置为开启使用EIP暴露API Server。创建集群时,分别为cluster-1和cluster-2指定两个不同的地域。
具体操作,请参见创建ACK托管集群[2] 。
步骤二:基于两个集群构建多主控制面架构服务网格
在集Kubernetes集群创建完成后,需要创建服务网格ASM实例,并将Kubernetes集群加入服务网格ASM进行管理。
多主控制面架构是一种使用服务网格管理多个Kubernetes集群的架构模式。在这种架构中,多个服务网格实例分别管理各自的Kubernetes集群的数据面组件,并为集群中的网格代理分发配置。同时,这些实例依靠共享的信任根证书,实现跨集群的服务发现和通信。
在跨地域的集群部署环境中,尽管可以将两个集群都通过统一的服务网格实例进行管理,但构建多主架构的服务网格仍然是跨地域容灾方案的最佳实践,这是由于以下原因:
1. 拥有更好的配置推送延迟表现:在跨地域部署的情况下,使用多个服务网格实例分别连接到就近的Kubernetes集群中的网格代理拥有更好的配置推送性能表现。
2. 稳定性表现更佳:遇到地域不可用的极端故障时,一个服务网格控制面连接所有集群的方式,可能会出现集群因为无法连接到控制面而无法同步配置或启动的问题;而在多主控制面架构下,正常地域中的网格代理仍可正常连接到控制面,不影响服务网格配置的下发与网格代理的正常启动。这保证了正常地域中的ASM网关和业务服务在故障地域中的服务网格控制面不可连接的情况下仍然可以正常扩容。
有关构建多主架构服务网格的具体操作,请参见通过ASM多主控制面架构实现多集群容灾[3] ,完成其中的步骤一与步骤二。
构建完成后,将创建名为mesh-1和mesh-2的服务网格实例;其中,cluster-1集群中的网格代理将连接到mesh-1服务网格实例的控制平面,而cluster-2集群中的网格代理将连接到mesh-2服务网格实例的控制平面。
步骤三:在两个集群中分别部署ASM网关与示例服务
1)在mesh-1和mesh-2服务网格ASM实例中,分别创建名为ingressgateway的ASM入口网关。具体操作,请参见创建入口网关[4] (创建时,可选择性地开启扩缩容HPA,以实现ASM网关针对CPU和内存指标的自动扩缩容)。
2)在cluster-1和cluster-2集群中,分别部署bookinfo示例应用。具体操作,请参见在ASM实例关联的集群中部署应用[5] 。
示例应用Bookinfo是一个书评应用,其服务架构如下所示:
3)在mesh-1和mesh-2服务网格ASM实例中,分别创建网关规则和虚拟服务,将ASM网关作为Bookinfo应用的流量入口。具体操作,请参见使用Istio资源实现版本流量路由[6] 。
步骤四:在ASM实例中开启集群内流量保持功能
当同一个服务网格实例加入两个或以上的Kubernetes集群时,如未经任何配置,服务网格的默认负载均衡机制会导致服务有可能尝试调用对侧集群对等部署的服务。
在地域级故障容灾的情景下,我们期望当一切正常时、流量一直保持在单个集群中、不要产生跨集群调用;而当某个地域产生故障时、通常意味着该地域的集群中的工作负载全部不可用,此时同样不需要跨集群调用。因此,在地域级故障容灾的场景下,我们始终希望流量保持在单个集群中。
通过开启ASM集群内流量保持功能,可以将对服务的请求始终保持在本集群,满足上述诉求。具体操作,请参考按照全局开启集群内流量保持功能[7] 。
说明:
尽管使用集群内流量保持功能配置简单,且可以帮助应对地域级故障容灾场景,但当故障发生在更小的粒度时(例如:服务级故障、节点级故障),我们将会期望流量failover到其它地域/可用区上的正常的对等部署服务,此时集群内流量保持无法满足此类容灾诉求。
通过配置基于地理位置的故障转移,可以在更小的服务/节点等故障粒度上实现容灾:当一切正常时、流量一直保持在单个集群/地域中,而当集群中调用链路上某个服务发生故障时,可以通过跨集群调用的方式将流量failover到其它集群中的对等服务吗,具体请继续关注后续文章。
步骤五:配置全局流量管理GTM实现基于双ASM入口网关IP的跨地域容灾
ASM网关可以结合阿里云云解析DNS和全局流量管理GTM使用,在正常的时候,两个地域的ASM入口网关按照指定比例各自接收一部分流量,当其中一个地域发生故障的时候把故障IP剔除、将流量全部转移到正常地域,以实现对地域级故障的容灾。
在两个地域的集群中分别部署ASM网关以及对等的示例应用后,两个地域下集群中部署的ASM入口网关拥有各自的公网IP地址作为应用的流量入口IP。可进入服务网格ASM控制台,分别获取两个ASM网关的公网IP,有关获取ASM网关IP地址的具体操作,请参见获取入口网关地址[8] 。
将获取到的两个ASM网关IP作为应用的流量入口IP,都通过阿里云云解析DNS接入到相同的应用域名,并通过GTM配置多活负载和容灾。具体操作,参见GTM如何实现多活负载并容灾[9] 。
【可选】步骤六:为入口网关配置本地限流和基于限流的观测及告警
在mesh-1和mesh-2服务网格实例中,分别基于以下YAML配置,在ASM网关上创建本地限流规则。具体操作,参考为ASM入口网关配置本地限流[10] 。
apiVersion: istio.alibabacloud.com/v1beta1 kind: ASMLocalRateLimiter metadata: name: ingressgateway namespace: istio-system spec: configs: - limit: fill_interval: seconds: 1 quota: 100 match: vhost: name: '*' port: 80 route: name_match: gw-to-productage isGateway: true workloadSelector: labels: istio: ingressgateway
同时,分别为两个服务网格实例配置本地限流指标的采集与告警。具体操作,参考配置本地限流指标采集和告警[11] 。
地域级故障演练
1. 执行以下命令,通过fortio压测工具模拟向示例应用发送请求。其中域名需要替换为在GTM中配置的域名(执行前,需要参考fortio项目[12] 的安装说明,安装fortio压力测试工具)。
fortio load -jitter=False -c 1 -qps 100 -t 300s -keepalive=False -a http://{域名}/productpage
2. 该压力测试将持续5分钟,期间我们将通过删除入口网关工作负载的方式模拟地域发生故障的情况:
a. 进入容器服务Kubernetes版控制台,找到cluster-2集群,单击详情。
b. 单击无状态页签,选择istio-system命名空间。
c. 在无状态工作负载页面,找到istio-ingressgateway,在右侧操作中单击更多,再单击删除。
3. 等待压力测试结束,预期输出:
# range, mid point, percentile, count >= -261.054 <= -0.0693516 , -130.561 , 100.00, 3899 # target 50% -130.595 WARNING 100.00% of sleep were falling behind Aggregated Function Time : count 3899 avg 0.076910055 +/- 0.02867 min 0.062074583 max 1.079674 sum 299.872304 # range, mid point, percentile, count >= 0.0620746 <= 0.07 , 0.0660373 , 19.34, 754 > 0.07 <= 0.08 , 0.075 , 71.94, 2051 > 0.08 <= 0.09 , 0.085 , 96.08, 941 > 0.09 <= 0.1 , 0.095 , 99.23, 123 > 0.1 <= 0.12 , 0.11 , 99.62, 15 > 0.12 <= 0.14 , 0.13 , 99.82, 8 > 0.14 <= 0.16 , 0.15 , 99.92, 4 > 1 <= 1.07967 , 1.03984 , 100.00, 3 # target 50% 0.0758289 # target 75% 0.0812673 # target 90% 0.0874825 # target 99% 0.0992691 # target 99.9% 0.155505 Error cases : count 527 avg 0.074144883 +/- 0.07572 min 0.062074583 max 1.079674 sum 39.0743532 # range, mid point, percentile, count >= 0.0620746 <= 0.07 , 0.0660373 , 82.54, 435 > 0.07 <= 0.08 , 0.075 , 96.58, 74 > 0.08 <= 0.09 , 0.085 , 99.05, 13 > 0.09 <= 0.1 , 0.095 , 99.24, 1 > 0.12 <= 0.14 , 0.13 , 99.43, 1 > 1 <= 1.07967 , 1.03984 , 100.00, 3 # target 50% 0.0668682 # target 75% 0.0692741 # target 90% 0.0753108 # target 99% 0.0897923 # target 99.9% 1.06568 # Socket and IP used for each connection: [0] 3900 socket used, resolved to [121.41.113.220:80 (3373), 8.209.197.28:80 (527)], connection timing : count 3900 avg 0.038202153 +/- 0.03097 min 0.027057 max 1.07747175 sum 148.988395 Connection time histogram (s) : count 3900 avg 0.038202153 +/- 0.03097 min 0.027057 max 1.07747175 sum 148.988395 # range, mid point, percentile, count >= 0.027057 <= 0.03 , 0.0285285 , 13.28, 518 > 0.03 <= 0.035 , 0.0325 , 62.79, 1931 > 0.035 <= 0.04 , 0.0375 , 83.95, 825 > 0.04 <= 0.045 , 0.0425 , 86.13, 85 > 0.045 <= 0.05 , 0.0475 , 86.18, 2 > 0.05 <= 0.06 , 0.055 , 86.28, 4 > 0.06 <= 0.07 , 0.065 , 98.03, 458 > 0.07 <= 0.08 , 0.075 , 99.77, 68 > 0.08 <= 0.09 , 0.085 , 99.92, 6 > 1 <= 1.07747 , 1.03874 , 100.00, 3 # target 50% 0.0337079 # target 75% 0.0378848 # target 90% 0.0631659 # target 99% 0.0755882 # target 99.9% 0.0885 Sockets used: 3900 (for perfect keepalive, would be 1) Uniform: false, Jitter: false, Catchup allowed: true IP addresses distribution: 121.41.113.220:80: 3373 8.209.197.28:80: 527 Code -1 : 527 (13.5 %) Code 200 : 3372 (86.5 %) Response Header Sizes : count 3899 avg 178.19851 +/- 70.45 min 0 max 207 sum 694796 Response Body/Total Sizes : count 3899 avg 4477.7081 +/- 1822 min 0 max 5501 sum 17458584 All done 3899 calls (plus 1 warmup) 76.910 ms avg, 13.0 qps
可以看到有少量请求在模拟的地域故障下发生了无法连接的错误,但大部分请求成功,证明服务网格ASM结合GTM有效地对地域级别的故障完成了容灾。
在GTM控制台可以看到一侧的IP地址被自动剔除。
本场景使用GTM的健康检查能力自动地剔除不可用的IP地址来实现容灾,您也可以通过配置告警的方式,在IP不可用时接收告警,并人工剔除不可用IP地址,具体操作,参考告警配置[13] 。
相关链接:
[1] 全局流量管理GTM
[2] 创建ACK托管集群
[3] 通过ASM多主控制面架构实现多集群容灾
[4] 创建入口网关
https://help.aliyun.com/zh/asm/getting-started/create-an-ingress-gateway
[5] 在ASM实例关联的集群中部署应用
[6] 使用Istio资源实现版本流量路由
[7] 按照全局开启集群内流量保持功能
[8] 获取入口网关地址
[9] GTM如何实现多活负载并容灾
https://help.aliyun.com/zh/dns/how-does-gtm-implement-multi-live-load-and-disaster-tolerance
[10] 为ASM入口网关配置本地限流
https://help.aliyun.com/zh/asm/user-guide/configure-local-throttling-for-the-ingress-gateway
[11] 配置本地限流指标采集和告警
https://help.aliyun.com/zh/asm/user-guide/configure-local-throttling-in-the-traffic-manager
[12] fortio项目
https://github.com/fortio/fortio
[13] 告警配置
https://help.aliyun.com/zh/dns/alarm-configuration
我们是阿里巴巴云计算和大数据技术幕后的核心技术输出者。
获取关于我们的更多信息~