当您遇到跨可用区网络延迟导致的服务响应时间增加或成本上升等问题时,可以使用同可用区优先路由(简称同AZ路由)功能,优先保证服务请求在同一个可用区内完成处理,减少网络传输延迟,降低因跨区域流量产生的额外费用,提高整体服务的运行效率和稳定性。ASM支持在不需要修改应用代码的情况下实现同AZ路由。本文以入口网关访问httpbin应用为例,介绍如何使用同AZ路由。
前提条件
已添加集群到ASM实例。具体操作,请参见添加集群到ASM实例。
ACK集群中的节点存在至少两个可用区,本示例中分别使用cn-hongkong-b和cn-hongkong-c,您可以在容器服务管理控制台查看集群节点所对应的ECS所在地域及可用区。更多信息,请参见地域和可用区。
说明本示例中sleep应用部署在可用区cn-hongkong-b,helloworld-v1应用部署到可用区cn-hongkong-b中,helloworld-v2应用部署到可用区cn-hongkong-c中,您可以根据实际集群所使用的可用区进行替换。
注意事项
同可用区优先路由启用后,在同可用区存在可用目标的情况下,集群内部应用间的调用将不会跨可用区。因此,为了保证启用该能力后的负载均衡,您需要确保相关工作负载是均匀分布在多个可用区的。您可以通过topologySpreadConstraints使得工作负载在创建、扩容时被调度器尽可能均匀地分布到不同可用区。同时,如果您的工作负载存在扩缩容场景,需要进一步启用重调度(DeScheduling)以确保在缩容时工作负载仍然保持均匀分布。
背景信息
同AZ路由是指在客户端对一个目标服务的访问过程中,可以根据这个客户端所在的地域、可用区拓扑信息,优先路由到与该客户端在同一个节点或者可用区的目标服务上的路由行为。同AZ路由本身属于负载均衡策略的范畴,它能够使流量尽可能在同一个可用区内流转,以保证服务间的调用延迟最低。
步骤一:部署示例应用
使用以下内容,创建sleep.yaml。
说明如下示例中,sleep应用部署到可用区cn-hongkong-b,您可以根据实际集群所使用的可用区进行替换。
执行以下命令,在集群中部署sleep应用。
kubectl apply -f sleep.yaml
使用以下内容,创建helloworld.yaml。
说明如下示例中,helloworld-v1应用部署到可用区cn-hongkong-b中,helloworld-v2应用部署到可用区cn-hongkong-c中,您可以根据实际集群所使用的可用区进行替换。
执行以下命令,在集群中部署helloworld应用。
kubectl apply -f helloworld.yaml
执行以下命令,查询目标服务的注册信息。
kubectl exec "$(kubectl get pod -l app=sleep -o jsonpath='{.items[0].metadata.name}')" -c sleep -- curl localhost:15000/clusters | grep helloworld
预期输出:
outbound|5000||helloworld.default.svc.cluster.local::172.28.32.49:5000::region::cn-hongkong outbound|5000||helloworld.default.svc.cluster.local::172.28.32.49:5000::zone::cn-hongkong-b outbound|5000||helloworld.default.svc.cluster.local::172.28.32.49:5000::sub_zone:: outbound|5000||helloworld.default.svc.cluster.local::172.28.32.49:5000::canary::false outbound|5000||helloworld.default.svc.cluster.local::172.28.32.49:5000::priority::0 ....... outbound|5000||helloworld.default.svc.cluster.local::172.28.33.155:5000::region::cn-hongkong outbound|5000||helloworld.default.svc.cluster.local::172.28.33.155:5000::zone::cn-hongkong-c outbound|5000||helloworld.default.svc.cluster.local::172.28.33.155:5000::sub_zone:: outbound|5000||helloworld.default.svc.cluster.local::172.28.33.155:5000::canary::false outbound|5000||helloworld.default.svc.cluster.local::172.28.33.155:5000::priority::0
由预期输出得到,两个helloworld应用的优先级相同,均为
priority::0
。说明当sleep客户端调用helloworld服务时,两个helloworld应用的路由策略相同。
步骤二:设置同AZ优先路由
通过应用目标规则来解决优先级问题,为服务helloworld.default.svc.cluster.local
启用同AZ路由的能力。
您可以调整连续5xx错误(consecutive5xxErrors
)、间隔时间(interval
)以及最小的移除时间长度(baseEjectionTime
)参数,实现同可用区路由的优先调用。本示例将在第一个请求失败时触发故障转移。
使用以下内容,创建helloworld-failover.yaml。
apiVersion: networking.istio.io/v1beta1 kind: DestinationRule metadata: name: helloworld-failover namespace: default spec: host: helloworld.default.svc.cluster.local trafficPolicy: connectionPool: http: maxRequestsPerConnection: 1 loadBalancer: localityLbSetting: enabled: true simple: ROUND_ROBIN outlierDetection: baseEjectionTime: 1m consecutive5xxErrors: 1 interval: 1s
执行以下命令,查看工作负载的优先级。
kubectl exec "$(kubectl get pod -l app=sleep -o jsonpath='{.items[0].metadata.name}')" -c sleep -- curl localhost:15000/clusters | grep helloworld
预期输出:
outbound|5000||helloworld.default.svc.cluster.local::172.28.32.49:5000::region::cn-hongkong outbound|5000||helloworld.default.svc.cluster.local::172.28.32.49:5000::zone::cn-hongkong-b outbound|5000||helloworld.default.svc.cluster.local::172.28.32.49:5000::sub_zone:: outbound|5000||helloworld.default.svc.cluster.local::172.28.32.49:5000::canary::false outbound|5000||helloworld.default.svc.cluster.local::172.28.32.49:5000::priority::0 ....... outbound|5000||helloworld.default.svc.cluster.local::172.28.33.155:5000::region::cn-hongkong outbound|5000||helloworld.default.svc.cluster.local::172.28.33.155:5000::zone::cn-hongkong-c outbound|5000||helloworld.default.svc.cluster.local::172.28.33.155:5000::sub_zone:: outbound|5000||helloworld.default.svc.cluster.local::172.28.33.155:5000::canary::false outbound|5000||helloworld.default.svc.cluster.local::172.28.33.155:5000::priority::1
由预期输出得到,两个helloworld应用的优先级不同,分别为
priority::0
和priority::1
。说明当sleep客户端调用helloworld服务时,同AZ路由的策略生效。
步骤三:验证同AZ优先路由
从位于可用区cn-hongkong-b中的客户端sleep应用发送请求,调用helloworld服务。启用同AZ优先路由之后,所有流量都应指向同在可用区cn-hongkong-b中的helloworld-v1应用。其中,sleep应用部署在可用区cn-hongkong-b,helloworld-v1应用部署到可用区cn-hongkong-b中,helloworld-v2应用部署到可用区cn-hongkong-c中。
重复执行以下命令,访问helloworld服务。
kubectl exec -c sleep "$(kubectl get pod -l app=sleep -o jsonpath='{.items[0].metadata.name}')" -- curl -sSL helloworld:5000/hello
预期输出:
Hello version: v1, instance: helloworld-v1-6f88967849-sq2h2
由预期输出得到,返回结果始终为helloworld-v1服务。
缩容helloworld-v1服务。
执行以下命令,缩容helloworld-v1服务到0个Pod,模拟该服务不可用状态。
kubectl scale deploy helloworld-v1 --replicas=0
等待几秒后,重复执行以下命令,访问helloworld服务。
kubectl exec -c sleep "$(kubectl get pod -l app=sleep -o jsonpath='{.items[0].metadata.name}')" -- curl -sSL helloworld:5000/hello
预期输出:
Hello version: v2, instance: helloworld-v2-75db5f978d-s7v4k
由预期输出得到,当本可用区的helloworld-v1服务不可用时,会自动切换到另一可用区cn-hongkong-c中的helloworld-v2服务。
扩容helloworld-v1服务。
执行以下命令,扩容helloworld-v1服务到1个Pod,恢复可用区cn-hongkong-b中的helloworld-v1应用服务。
kubectl scale deploy helloworld-v1 --replicas=1
等待几秒后,重复执行以下命令,访问helloworld服务。
kubectl exec -c sleep "$(kubectl get pod -l app=sleep -o jsonpath='{.items[0].metadata.name}')" -- curl -sSL helloworld:5000/hello
预期输出:
Hello version: v1, instance: helloworld-v1-6f88967849-sq2h2
由预期输出得到,返回结果始终为helloworld-v1服务。