All Products
Search
Document Center

Alibaba Cloud Service Mesh:Use lanes for end-to-end canary release

Last Updated:Mar 11, 2026

Traffic lanes isolate specific service versions into independent runtime environments and route matching requests through an entire call chain -- without any application code changes. This enables end-to-end canary releases across multiple services simultaneously.

Why traffic lanes

Standard Kubernetes canary deployments couple traffic distribution with replica counts: sending 10% of traffic to a canary requires 1 canary replica alongside 9 stable replicas. This approach breaks down in two scenarios:

  • Multi-service call chains. A request flowing through services A, B, and C needs consistent version routing at every hop. Kubernetes provides no built-in mechanism for this.

  • Independent scaling. With lanes, traffic distribution and replica counts are fully decoupled. A single canary replica receives exactly the traffic percentage you specify, regardless of how many stable replicas are running.

ASM traffic lanes solve both problems by tagging requests at the ingress gateway and propagating the tag across the entire call chain.

How it works

Configuring lanes through the console generates three Istio resources automatically:

ResourcePurpose
TrafficLabelAssigns a label to each request based on the ASM_TRAFFIC_TAG pod label
DestinationRuleMaps lane names to service version subsets
VirtualServiceRoutes requests to the correct subset based on the x-asm-prefer-tag header and URI

Routing flow:

  1. A request arrives at the ingress gateway with the header x-asm-prefer-tag: <lane-name>.

  2. The VirtualService matches the header and URI, then routes the request to the corresponding subset of the first service.

  3. The TrafficLabel propagates the lane tag through subsequent service-to-service calls, keeping the request within the same lane for the entire call chain.

Scenario overview

This tutorial deploys three lanes (s1, s2, s3), each containing three services (mocka, mockb, mockc) bound to different versions:

LaneService tagServices
s1v1mocka, mockb, mockc
s2v2mocka, mockb, mockc
s3v3mocka, mockb, mockc

After setup, requests with x-asm-prefer-tag: s1 flow exclusively through v1 of all three services, requests with s2 through v2, and requests with s3 through v3.

Lane mode end-to-end canary release

Prerequisites

Before you begin, make sure that you have:

Sample Gateway YAML

apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
  name: ingressgateway
  namespace: istio-system
spec:
  selector:
    istio: ingressgateway        # Match the ASM ingress gateway
  servers:
    - port:
        number: 80               # Listen on port 80
        name: http
        protocol: HTTP
      hosts:
        - '*'                    # Accept traffic for all hosts

Step 1: Deploy sample services

Enable automatic sidecar proxy injection

  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 ASM Instance > Global Namespace.

  3. On the Global Namespace page, find the default namespace and click Enable Automatic Sidecar Injection in the Automatic Sidecar Injection column. In the Submit message, click OK.

For more information, see Enable automatic sidecar proxy injection.

Deploy the services

Deploy v1, v2, and v3 of the sample services in the ACK cluster:

kubectl apply -f https://alibabacloudservicemesh.oss-cn-beijing.aliyuncs.com/asm-labs/swimlane/v1/application-v1.yaml
kubectl apply -f https://alibabacloudservicemesh.oss-cn-beijing.aliyuncs.com/asm-labs/swimlane/v2/application-v2.yaml
kubectl apply -f https://alibabacloudservicemesh.oss-cn-beijing.aliyuncs.com/asm-labs/swimlane/v3/application-v3.yaml

Step 2: 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
Entrance gatewayingressgateway
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 in the service list, then click the move icon to add them to the selected section

After you create the lane group, ASM generates a TrafficLabel resource:

Generated TrafficLabel YAML

apiVersion: istio.alibabacloud.com/v1beta1
kind: TrafficLabel
metadata:
  labels:
    asm-system: 'true'
    provider: asm
  name: asm-trafficlabel-global
  namespace: istio-system
spec:
  rules:
    - labels:
        - name: asm-label
          valueFrom:
            - $getLabel(ASM_TRAFFIC_TAG)   # Reads the ASM_TRAFFIC_TAG label from each pod

Create lanes

Create three lanes (s1, s2, s3) and bind each to the corresponding service version. The following steps show how to create the s1 lane. Repeat the same process for s2 (service tag: v2) and s3 (service tag: v3).

  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 Names1
Configure Service Tagv1
Add ServiceSelect mocka(default), mockb(default), and mockc(default)
Note

Requests with the header x-asm-prefer-tag: s1 are routed to the v1 subset of each service.

Create lane

After you create all three lanes, the Traffic Rule Definition section displays them as follows:

Lanes overview

Each lane creation generates a DestinationRule. The following example shows the DestinationRule for the s1 lane:

Generated DestinationRule YAML (s1 lane)

apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  labels:
    asm-system: 'true'
    provider: asm
    swimlane-group: test                              # Belongs to the "test" lane group
  name: trafficlabel-dr-test-default-mocka
  namespace: istio-system
spec:
  host: mocka.default.svc.cluster.local               # Target service
  subsets:
    - labels:
        ASM_TRAFFIC_TAG: v1                            # Lane s1 maps to version v1
      name: s1
    - labels:
        ASM_TRAFFIC_TAG: v1
      name: v1
    - labels:
        ASM_TRAFFIC_TAG: v2                            # Lane s2 maps to version v2
      name: v2
    - labels:
        ASM_TRAFFIC_TAG: v2
      name: s2
    - labels:
        ASM_TRAFFIC_TAG: v3                            # Lane s3 maps to version v3
      name: v3
    - labels:
        ASM_TRAFFIC_TAG: v3
      name: s3

Create ingress traffic rules

Create a traffic routing rule for each lane. The following steps show how to create a rule for the s1 lane. Repeat the same process for s2 and s3.

This example assumes all lane services share the inbound request path /mock.

  1. In the Traffic Rule Definition section of the Traffic Lane page, find the target 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.

ParameterValue
Ingress servicemocka.default.svc.cluster.local
Ingress traffic rulesName: r1, realm name: *
Matching request URIMethod: Exact, Content: /mock

After you create traffic routing rules for all three lanes, the Traffic Rule Definition section displays them as follows:

Ingress traffic rules

ASM generates a VirtualService that routes requests based on the x-asm-prefer-tag header:

Generated VirtualService YAML

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  labels:
    asm-system: 'true'
    istioGateway: ingressgateway
    provider: asm
  name: ingressgateway
  namespace: istio-system
spec:
  gateways:
    - istio-system/ingressgateway                      # Bind to the ingress gateway
  hosts:
    - '*'                                              # Match all hosts
  http:
    - match:
        - headers:
            x-asm-prefer-tag:
              exact: s1                                # Match requests tagged for lane s1
          uri:
            exact: /mock                               # Match the /mock path
      name: swimelane-ingress-route-test-s1-rule1
      route:
        - destination:
            host: mocka.default.svc.cluster.local      # Route to mocka
            subset: s1                                 # Use the s1 subset (version v1)
    - match:
        - headers:
            x-asm-prefer-tag:
              exact: s2                                # Match requests tagged for lane s2
          uri:
            exact: /mock
      name: swimelane-ingress-route-test-s2-rule2
      route:
        - destination:
            host: mocka.default.svc.cluster.local
            subset: s2                                 # Use the s2 subset (version v2)
    - match:
        - headers:
            x-asm-prefer-tag:
              exact: s3                                # Match requests tagged for lane s3
          uri:
            exact: /mock
      name: swimelane-ingress-route-test-s3-rule3
      route:
        - destination:
            host: mocka.default.svc.cluster.local
            subset: s3                                 # Use the s3 subset (version v3)

Step 3: Verify the end-to-end canary release

Get the gateway IP address

Get the public IP address of the ASM ingress gateway. For details, see Step 2 in Integrate the cloud-native inference service KServe with ASM.

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

export ASM_GATEWAY_IP=<gateway-ip-address>

Test each lane

Send 100 requests to each lane and verify that traffic stays within the expected service versions.

Lane s1 (expected: all v1):

for i in {1..100}; do curl -H 'x-asm-prefer-tag: s1' 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 return v1, confirming that requests tagged with x-asm-prefer-tag: s1 route exclusively through the s1 lane.

Lane s2 (expected: all v2):

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

Expected output:

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

Lane s3 (expected: all v3):

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

Expected output:

-> mocka(version: v3, ip: 172.17.0.132)-> mockb(version: v3, ip: 172.17.0.127)-> mockc(version: v3, ip: 172.17.0.69)

Troubleshoot routing issues

If any request returns a mismatched version, check the following:

SymptomPossible causeResolution
Response shows wrong versionASM_TRAFFIC_TAG pod labels do not match the service tag configured for the laneVerify pod labels with kubectl get pods --show-labels and confirm they match the lane configuration
No response or 404VirtualService route does not match the x-asm-prefer-tag header value or URICheck the VirtualService YAML to confirm header matching rules and URI path
Traffic leaks across lanesDestinationRule subsets do not correctly map lane names to version labelsInspect the DestinationRule YAML and verify each subset maps the correct ASM_TRAFFIC_TAG value
Intermittent routing failuresSidecar proxy not injected on some podsRun kubectl get pods -o jsonpath='{.items[*].spec.containers[*].name}' to confirm the istio-proxy container exists on all pods

(Optional) Step 4: Check the mesh topology

If Mesh Topology is enabled in the ASM console, inspect the topology graph to visualize the request paths across lanes. For more information, see Enable Mesh Topology to observe an ASM instance in the ASM console.

What to do next

  • Label traffic -- Learn more about traffic labeling concepts and advanced configurations