All Products
Search
Document Center

Alibaba Cloud Service Mesh:Enable the Intra-zone Provider First feature

Last Updated:Jun 05, 2023

Service Mesh (ASM) allows you to use the Intra-zone Provider First feature (also called intra-zone routing) without the need to modify the application code. This topic describes how to use this feature by using the ingress gateway to access an httpbin application as an example.

Prerequisites

  • An ASM instance is created. For more information, see Create an ASM instance.
  • An ACK managed cluster is created. For more information, see Create an ACK managed cluster.
  • The cluster is added to the ASM instance. For more information, see Add a cluster to an ASM instance.
  • Nodes in an Alibaba Cloud 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.

  • In 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.

Background information

When a client initiates an access request to a service, the request is routed to the service provider on the node or in the zone of the client. This is how the Intra-zone Provider First feature works. Intra-zone Provider First is a load balancing feature. It makes traffic flow in the same zones to reduce service latency.

Step 1: Deploy applications

  1. Create a sleep.yaml file that contains the following content:

    Note

    In the following example, the sleep application is deployed in cn-hongkong-b. You can deploy your application to a zone based on your business requirements.

    # Copyright Istio Authors
    #
    #   Licensed under the Apache License, Version 2.0 (the "License");
    #   you may not use this file except in compliance with the License.
    #   You may obtain a copy of the License at
    #
    #       http://www.apache.org/licenses/LICENSE-2.0
    #
    #   Unless required by applicable law or agreed to in writing, software
    #   distributed under the License is distributed on an "AS IS" BASIS,
    #   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    #   See the License for the specific language governing permissions and
    #   limitations under the License.
    
    ##################################################################################################
    # Sleep service
    ##################################################################################################
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: sleep
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: sleep
      labels:
        app: sleep
        service: sleep
    spec:
      ports:
      - port: 80
        name: http
      selector:
        app: sleep
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: sleep
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: sleep
      template:
        metadata:
          labels:
            app: sleep
        spec:
          affinity:
            nodeAffinity:
              requiredDuringSchedulingIgnoredDuringExecution:
                nodeSelectorTerms:
                - matchExpressions:
                  - key: failure-domain.beta.kubernetes.io/zone
                    operator: In
                    values:
                      - 'cn-hongkong-b'
          terminationGracePeriodSeconds: 0
          serviceAccountName: sleep
          containers:
          - name: sleep
            image: curlimages/curl
            command: ["/bin/sleep", "3650d"]
            imagePullPolicy: IfNotPresent
            volumeMounts:
            - mountPath: /etc/sleep/tls
              name: secret-volume
          volumes:
          - name: secret-volume
            secret:
              secretName: sleep-secret
              optional: true
  2. Run the following command to deploy the sleep application in the ACK cluster:

    kubectl apply -f sleep.yaml
  3. Create a helloworld.yaml file that contains the following content:

    Note

    In the following example, the helloworld-v1 application is deployed in cn-hongkong-b and the helloworld-v2 application in cn-hongkong-c. Use the zones where your applications reside.

    apiVersion: v1
    kind: Service
    metadata:
      name: helloworld
      labels:
        app: helloworld
        service: helloworld
    spec:
      ports:
      - port: 5000
        name: http
      selector:
        app: helloworld
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: helloworld-v1
      labels:
        app: helloworld
        version: v1
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: helloworld
          version: v1
      template:
        metadata:
          labels:
            app: helloworld
            version: v1
        spec:
          affinity:
            nodeAffinity:
              requiredDuringSchedulingIgnoredDuringExecution:
                nodeSelectorTerms:
                - matchExpressions:
                  - key: failure-domain.beta.kubernetes.io/zone
                    operator: In
                    values:
                      - 'cn-hongkong-b'
          containers:
          - name: helloworld
            image: docker.io/istio/examples-helloworld-v1
            resources:
              requests:
                cpu: "100m"
            imagePullPolicy: IfNotPresent #Always
            ports:
            - containerPort: 5000
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: helloworld-v2
      labels:
        app: helloworld
        version: v2
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: helloworld
          version: v2
      template:
        metadata:
          labels:
            app: helloworld
            version: v2
        spec:
          affinity:
            nodeAffinity:
              requiredDuringSchedulingIgnoredDuringExecution:
                nodeSelectorTerms:
                - matchExpressions:
                  - key: failure-domain.beta.kubernetes.io/zone
                    operator: In
                    values:
                      - 'cn-hongkong-c'
          containers:
          - name: helloworld
            image: docker.io/istio/examples-helloworld-v2
            resources:
              requests:
                cpu: "100m"
            imagePullPolicy: IfNotPresent #Always
            ports:
            - containerPort: 5000
                            
  4. Run the following command to deploy the helloworld applications in the ACK cluster:

    kubectl apply -f helloworld.yaml
  5. Run the following command to query the registration information of 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 Intra-zone Provider First feature

Use the destination rule to prioritize the helloworld application in the zone of the client. Enable the Intra-zone Provider First feature for the helloworld.default.svc.cluster.local service.

Note

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.

  1. 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
                            
  2. 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 and priority::1. The output shows that the Intra-zone Provider First feature can take effect when the sleep client calls the helloworld service.

Step 3: Verify the Intra-zone Provider First 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 Intra-zone Provider First feature is enabled, all traffic flows 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 in cn-hongkong-c.

  1. 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 shows that the returned result is always the helloworld-v1 application.

  2. Scale in the helloworld-v1 application.

    1. 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
    2. 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

      When the helloworld-v1 application in the same zone as the client becomes unavailable, the request is switched to the helloworld-v2 application in the cn-hongkong-c zone.

  3. Scale out the helloworld-v1 application.

    1. 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
    2. 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 shows that the returned result is always the helloworld-v1 application.