If you encounter issues such as increased service response time or increased costs caused by cross-zone network latency, you can use the zone aware routing feature to ensure that service requests are preferentially processed in the same zone. This decreases network transmission latency, reduces extra costs incurred by cross-zone traffic, and improves the overall efficiency and stability of services. Service Mesh (ASM) allows you to use the zone aware routing feature (also called intra-zone routing) without the need to modify the application code. This topic describes how to use this feature. In the following example, an ingress gateway is used to enable access to an HTTPBin application.
Prerequisites
The cluster is added to the ASM instance. For more information, see Add a cluster to an ASM instance.
Nodes in the Container Service for Kubernetes (ACK) cluster reside in at least two zones. In this topic, the cn-hongkong-b and cn-hongkong-c zones are used. You can view the region and zone where the Elastic Compute Service (ECS) instance that corresponds to a cluster node resides in the Container Service for Kubernetes (ACK) console. For more information, see Regions and zones.
NoteIn this example, sleep and helloworld-v1 applications are deployed in cn-hongkong-b, and the helloworld-v2 application is deployed in cn-hongkong-c. Use the zones where your applications reside.
Usage notes
After zone aware routing feature is enabled, the request from an application is preferentially routed to other applications in the same zone whenever possible. In this case, to ensure load balancing, you need to ensure that workloads are evenly distributed across different zones. You can configure topologySpreadConstraints to spread workloads across zones by using schedulers. In addition, to scale in or out your workloads, you need to enable DeScheduling to ensure that workloads are evenly distributed during scale-in.
Background information
When a client initiates a request to access a service, the request is preferentially routed to the service on the same node or in the same zone as the client based on the topology information about the region and zone where the client resides. This is how the zone aware routing feature works. Zone aware routing is a load balancing feature. It makes traffic flow in the same zones to reduce service latency.
Step 1: Deploy sample applications
Create a sleep.yaml file that contains the following content:
NoteIn the following example, the sleep application is deployed in cn-hongkong-b. You can deploy your application in a zone based on your business requirements.
Run the following command to deploy the sleep application in the ACK cluster:
kubectl apply -f sleep.yaml
Create a helloworld.yaml file that contains the following content.
NoteIn the following example, the helloworld-v1 application is deployed in cn-hongkong-b and the helloworld-v2 application is deployed in cn-hongkong-c. You can deploy your application in a zone based on your business requirements.
Run the following command to deploy the helloworld applications in the ACK cluster:
kubectl apply -f helloworld.yaml
Run the following command to query the registration information about the service to be accessed:
kubectl exec "$(kubectl get pod -l app=sleep -o jsonpath='{.items[0].metadata.name}')" -c sleep -- curl localhost:15000/clusters | grep helloworld
Expected output:
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
The output shows that the two helloworld applications have the same priority
priority::0
. Therefore, when the sleep client calls the helloworld service, the two helloworld applications have the same routing policies.
Step 2: Enable the zone aware routing feature
Use a destination rule to prioritize the helloworld application in the zone of the client. Enable the zone aware routing feature for the helloworld.default.svc.cluster.local
service.
You can enable this feature by configuring the following parameters: consecutive5xxErrors
, interval
, and baseEjectionTime
. In this example, a failover is triggered when the first request fails.
Create a helloworld-failover.yaml file that contains the following content:
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
Run the following command to view the pod priorities:
kubectl exec "$(kubectl get pod -l app=sleep -o jsonpath='{.items[0].metadata.name}')" -c sleep -- curl localhost:15000/clusters | grep helloworld
Expected output:
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
In the output, the priorities of the two helloworld applications are different, which are
priority::0
andpriority::1
, respectively. The output indicates that the zone aware routing feature takes effect when the sleep client calls the helloworld service.
Step 3: Verify the zone aware routing feature
Send a request to call the helloworld service from the sleep application on the client located in the cn-hongkong-b zone. After the zone aware routing feature is enabled, all traffic is routed to the helloworld-v1 application in the same zone with the client. The sleep and helloworld-v1 applications are deployed in cn-hongkong-b, and the helloworld-v2 application is deployed in cn-hongkong-c.
Run the following command multiple times to access the helloworld service:
kubectl exec -c sleep "$(kubectl get pod -l app=sleep -o jsonpath='{.items[0].metadata.name}')" -- curl -sSL helloworld:5000/hello
Expected output:
Hello version: v1, instance: helloworld-v1-6f88967849-sq2h2
The output indicates that the returned result is always the helloworld-v1 application.
Scale in the helloworld-v1 application.
Run the following command to scale in the helloworld-v1 application to zero pods and make the application unavailable:
kubectl scale deploy helloworld-v1 --replicas=0
Wait for a few seconds and run the following command multiple times to access the helloworld service:
kubectl exec -c sleep "$(kubectl get pod -l app=sleep -o jsonpath='{.items[0].metadata.name}')" -- curl -sSL helloworld:5000/hello
Expected output:
Hello version: v2, instance: helloworld-v2-75db5f978d-s7v4k
The output indicates that the request is routed to the helloworld-v2 application in the cn-hongkong-c zone when the helloworld-v1 application in the same zone as the client becomes unavailable.
Scale out the helloworld-v1 application.
Run the following command to scale out the helloworld-v1 application to one pod and restore the helloworld-v1 application:
kubectl scale deploy helloworld-v1 --replicas=1
Wait for a few seconds and run the following command multiple times to access the helloworld service:
kubectl exec -c sleep "$(kubectl get pod -l app=sleep -o jsonpath='{.items[0].metadata.name}')" -- curl -sSL helloworld:5000/hello
Expected output:
Hello version: v1, instance: helloworld-v1-6f88967849-sq2h2
The output indicates that the returned result is always the helloworld-v1 application.