All Products
Search
Document Center

Alibaba Cloud Service Mesh:Use traffic lanes with separate routing and trace headers

Last Updated:Mar 11, 2026

When microservices call each other through a service mesh, traffic lane routing depends on a header that travels through the entire call chain. If your application already propagates a custom trace ID that differs from the header used for lane selection, you need to configure the lane group with two separate headers -- one for routing at the gateway, and one for maintaining lane affinity across inter-service calls.

This walkthrough sets up permissive-mode traffic lanes in this two-header scenario and verifies that fallback routing works correctly.

How it works

Two headers serve distinct purposes:

HeaderPurposePropagation
x-asm-prefer-tagRouting header -- the ASM gateway reads this header to select the target lane.Set by the client. Does not need to be propagated between services.
my-trace-idTrace pass-through header -- ASM uses this header to maintain lane affinity across inter-service calls.Must be propagated by every service in the chain.

The routing header determines which lane a request enters at the gateway. The trace header maintains lane context as services call each other. Without trace header propagation, downstream calls lose lane affinity and route to the wrong version.

Note

Header propagation is an application-level responsibility. Each service must read the incoming my-trace-id header and include it in all outbound requests. The Envoy sidecar does not propagate trace headers automatically.

Traffic flow and fallback

The following example uses three lanes (s1, s2, s3) and three services (mocka, mockb, mockc):

LaneServicesVersion
s1 (baseline)mocka, mockb, mockcv1
s2mocka, mockcv2
s3mockbv3

When a request with x-asm-prefer-tag: s2 enters the gateway:

  1. The gateway routes the request to mocka v2 in lane s2.

  2. mocka calls mockb. Since mockb does not exist in s2, ASM falls back to mockb v1 in the baseline lane s1.

  3. mockb calls mockc. Because the trace header my-trace-id carries the lane context, ASM routes the request back to mockc v2 in lane s2.

This fallback mechanism keeps the call chain intact even when a lane contains only a subset of services.

Prerequisites

Before you begin, make sure that you have:

  • An ASM instance with an associated ACK cluster

  • The mocka, mockb, and mockc sample services deployed in the default namespace

  • Services configured to propagate the my-trace-id request header through the call chain

Step 1: Create a lane group and lanes

Create a lane group

  1. Log on to the ASM console. In the left-side navigation pane, choose Service Mesh > Mesh Management.

  2. On the Mesh Management page, click the name of the ASM instance. In the left-side navigation pane, choose Traffic Management Center > Traffic Lane.

  3. On the Traffic Lane page, click Create Swimlane Group. In the Create Swimlane Group panel, configure the following parameters and click OK.

ParameterValue
Name of swim lane grouptest
Istio gateway for an ingress gatewaySelect ingressgateway.
Lane ModeSelect Permissive Mode.
Pass-through Mode of Trace ContextSelect Pass Through Trace ID.
Trace ID Request HeaderEnter my-trace-id. The sample services propagate this header through the call chain.
Routing Request HeaderEnter x-asm-prefer-tag. The ASM gateway uses this header to route traffic to lanes.
Swimlane ServicesSelect the ACK cluster from the Kubernetes Clusters drop-down list and select default from the Namespace drop-down list. Select mocka, mockb, and mockc from the service list and click the move icon to add them to the selected section.

After the lane group is created, ASM automatically generates a traffic label for each service. To view it, choose Traffic Management Center > TrafficLabel in the left-side navigation pane.

Example TrafficLabel YAML for mocka

apiVersion: istio.alibabacloud.com/v1beta1
kind: TrafficLabel
metadata:
  labels:
    asm-system: 'true'
    provider: asm
    swimlane-group: test
  name: asm-swimlane-test-mocka
  namespace: default
spec:
  rules:
    - labels:
        - name: asm-label
          valueFrom:
            - '$getExternalInboundRequestHeader(x-asm-prefer-tag, my-trace-id)'
  workloadSelector:
    labels:
      app: mocka

The $getExternalInboundRequestHeader(x-asm-prefer-tag, my-trace-id) function extracts the lane label from the routing header or the trace header, enabling lane affinity to persist across the call chain.

Create lanes

  1. In the Traffic Rule Definition section of the Traffic Lane page, click Create swimlanes.

  2. In the Create swimlanes dialog box, configure the following parameters and click OK.

ParameterValue
Swimlane NameCreate three lanes: s1, s2, and s3.
Configure Service TagLabel Key: Select ASM_TRAFFIC_TAG. Label Value: Select v1 for s1, v2 for s2, and v3 for s3.
Add Services1: Select mocka(default), mockb(default), and mockc(default). s2: Select mocka(default) and mockc(default). s3: Select mockb(default).

The following figure shows the s1 lane configuration.

s1 lane configuration

After the three lanes are created, they appear in the Traffic Rule Definition section.

All three lanes
Note

The first lane created in a lane group is the baseline lane by default. When a service does not exist in the target lane, traffic falls back to the baseline lane. To change the baseline lane, see Change the baseline lane.

ASM automatically generates a destination rule and a virtual service for each service in the lanes. To view them, choose Traffic Management Center > DestinationRule or VirtualService in the left-side navigation pane.

Example DestinationRule YAML for mocka

apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  labels:
    asm-system: 'true'
    provider: asm
    swimlane-group: test
  name: trafficlabel-dr-test-default-mocka
  namespace: istio-system
spec:
  host: mocka.default.svc.cluster.local
  subsets:
    - labels:
        ASM_TRAFFIC_TAG: v1
      name: s1
    - labels:
        ASM_TRAFFIC_TAG: v2
      name: s2

Each subset maps a lane name to a label selector. Istio uses these subsets to route traffic to the pod version that corresponds to the target lane.

Example VirtualService YAML for mocka

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  labels:
    asm-system: 'true'
    provider: asm
    swimlane-group: test
  name: trafficlabel-vs-test-default-mocka
  namespace: istio-system
spec:
  hosts:
    - mocka.default.svc.cluster.local
  http:
    - name: default
      route:
        - destination:
            host: mocka.default.svc.cluster.local
            subset: $asm-label
          fallback:
            target:
              host: mocka.default.svc.cluster.local
              subset: s1

$asm-label is resolved at runtime to the lane label extracted from the request headers. The fallback block is an ASM extension to the standard Istio VirtualService -- it specifies the baseline lane subset to use when the target lane does not contain the service.

Create ingress traffic rules

  1. In the Traffic Rule Definition section, find the lane and click Ingress traffic rules in the Actions column.

  2. In the Add drainage rule dialog box, configure the following parameters and click OK.

All services in this example use /mock as the inbound request path. Configure the same traffic routing rule for each lane.

ParameterValue
Ingress serviceSelect mocka.default.svc.cluster.local.
Ingress traffic rulesSet Name to r1, r2, and r3 for the three lanes respectively. Set realm name to *.
Matching request URISet Method to Exact and Content to /mock.

The following figure shows the traffic routing rule for the s1 lane.

s1 traffic routing rule

After traffic routing rules are created, they appear in the Traffic Rule Definition section.

All traffic routing rules

Example ingress VirtualService YAML for the s2 lane

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  labels:
    asm-system: 'true'
    provider: asm
    swimlane-group: test
  name: swimlane-ingress-vs-test-s2
  namespace: istio-system
spec:
  gateways:
    - istio-system/ingressgateway
  hosts:
    - '*'
  http:
    - match:
        - headers:
            x-asm-prefer-tag:
              exact: s2
          uri:
            exact: /mock
      name: r2
      route:
        - destination:
            host: mocka.default.svc.cluster.local
            subset: s2
          fallback:
            target:
              host: mocka.default.svc.cluster.local
              subset: s1

This VirtualService matches requests with the x-asm-prefer-tag: s2 header and the URI /mock, then routes them to the s2 subset of mocka. If s2 does not contain the target service, the fallback block routes to the s1 baseline subset.

Step 2: Verify the traffic lanes

  1. Get the public IP address of the ingress gateway. For more information, see Obtain the IP address of the ASM ingress gateway.

  2. Set the gateway IP as an environment variable. Replace <gateway-ip> with the actual IP address.

    export ASM_GATEWAY_IP=<gateway-ip>
  3. Send test requests to each lane and verify the output.

    Test lane s1 (baseline):

    for i in {1..100}; do
      curl -H 'x-asm-prefer-tag: s1' -H 'my-trace-id: x000'$i \
        http://${ASM_GATEWAY_IP}/mock
      echo ''
      sleep 1
    done

    Expected output:

    -> mocka(version: v1, ip: 172.17.0.54)-> mockb(version: v1, ip: 172.17.0.129)-> mockc(version: v1, ip: 172.17.0.130)

    All three services are in lane s1, so traffic stays within the baseline lane.

    Test lane s2:

    for i in {1..100}; do
      curl -H 'x-asm-prefer-tag: s2' -H 'my-trace-id: x000'$i \
        http://${ASM_GATEWAY_IP}/mock
      echo ''
      sleep 1
    done

    Expected output:

    -> mocka(version: v2, ip: 172.17.0.9)-> mockb(version: v1, ip: 172.17.0.129)-> mockc(version: v2, ip: 172.17.0.128)

    mocka (v2) and mockc (v2) are served from lane s2. mockb does not exist in s2, so it falls back to mockb (v1) in the baseline lane s1. After the fallback, mockc is still correctly routed to s2 because the my-trace-id header preserves lane context through the call chain.

    Test lane s3:

    for i in {1..100}; do
      curl -H 'x-asm-prefer-tag: s3' -H 'my-trace-id: x000'$i \
        http://${ASM_GATEWAY_IP}/mock
      echo ''
      sleep 1
    done

    Expected output:

    mocka(version: v1, ip: 192.168.1.103)-> mockb(version: v3, ip: 192.168.1.120)-> mockc(version: v1, ip: 192.168.1.105)

    mockb (v3) is served from lane s3. mocka and mockc do not exist in s3, so they fall back to v1 in the baseline lane s1.

Change the baseline lane

Note

You can change the baseline lane only in a permissive-mode lane group with at least two lanes.

  1. Log on to the ASM console. In the left-side navigation pane, choose Service Mesh > Mesh Management.

  2. On the Mesh Management page, click the name of the ASM instance. In the left-side navigation pane, choose Traffic Management Center > Traffic Lane.

  3. On the Traffic Lane page, click the tab of the target lane group. In the Traffic Rule Definition section, click the edit icon next to Baseline Lane.

  4. Select the new baseline lane and click confirm edit.

What's next