All Products
Search
Document Center

Alibaba Cloud Service Mesh:Migrate traffic from Nginx Ingress Controller to an ingress gateway

Last Updated:Mar 11, 2026

When you adopt Service Mesh (ASM) for traffic management, existing services behind Nginx Ingress Controller must continue to receive traffic without interruption. ASM lets you run both gateways behind the same Classic Load Balancer (CLB) instance and shift traffic gradually through weight-based routing, so you can validate each stage and roll back instantly if needed.

How it works

With Nginx Ingress Controller, a single Ingress resource handles both listener configuration (ports, hosts, TLS) and routing rules (paths, backends). Istio separates these into two resources:

  • Gateway -- Defines the infrastructure layer: which ports to expose, which protocols to accept, and which hosts to serve.

  • VirtualService -- Defines the routing layer: how to match incoming requests and where to send them.

During migration, both Nginx Ingress Controller and the ASM ingress gateway share the same CLB instance. A weight-based traffic split lets you shift traffic incrementally, verify behavior at each stage, and roll back by setting the weight to 0.

Traffic flow during migration

Prerequisites

Before you begin, make sure that you have:

  • An ASM instance of Enterprise Edition or Ultimate Edition, running the latest version. See Create an ASM instance

  • A Container Service for Kubernetes (ACK) cluster added to the ASM instance. See Add a cluster to an ASM instance

  • The CLB instance ID and vServer group IDs for your existing Nginx Ingress Controller setup

  • The CLB scheduling algorithm set to weighted round-robin (WRR)

Step 1: Create an ingress gateway that shares the existing CLB

Create an ASM ingress gateway that reuses the CLB instance already associated with Nginx Ingress Controller. This lets both gateways coexist behind the same load balancer during migration.

Add the following service annotations to the gateway YAML to bind the ingress gateway to your existing CLB:

AnnotationPurposeExample value
service.beta.kubernetes.io/alibaba-cloud-loadbalancer-idCLB instance to reuse"lb-xxxxx"
service.beta.kubernetes.io/alibaba-cloud-loadbalancer-force-override-listenersWhether to overwrite existing CLB listeners. Set to false to preserve Nginx Ingress listeners.'false'
service.beta.kubernetes.io/alibaba-cloud-loadbalancer-vgroup-portvServer groups to bind, in the format <vserver-group-id>:<port>. Separate multiple entries with commas."${YOUR_VGROUP_ID}:80"
service.beta.kubernetes.io/alibaba-cloud-loadbalancer-weightTraffic weight for the ingress gateway. Set to 0 when routing is not yet configured or when issues occur -- the CLB sends no traffic to the gateway at weight 0."0"

Sample gateway configuration:

serviceAnnotations:
  service.beta.kubernetes.io/alibaba-cloud-loadbalancer-id: "lb-xxxxx"
  service.beta.kubernetes.io/alibaba-cloud-loadbalancer-force-override-listeners: 'false'
  service.beta.kubernetes.io/alibaba-cloud-loadbalancer-vgroup-port: "${YOUR_VGROUP_ID}:80"
  service.beta.kubernetes.io/alibaba-cloud-loadbalancer-weight: "60"

Replace the placeholder values:

PlaceholderDescriptionWhere to find it
lb-xxxxxCLB instance IDCLB console > Instances
${YOUR_VGROUP_ID}vServer group IDCLB console > vServer Groups
Note

If you set the weight to 0, the ingress gateway no longer receives traffic. You can set the weight to 0 when routing rules have not been configured or when exceptions occur.

Note

For details on reusing CLB instances created with the LoadBalancer Service type, see FAQ.

Verify the gateway

Confirm that the ingress gateway pod is running and the CLB instance shows the new vServer group members:

kubectl get pods -n istio-system -l istio=ingressgateway

Expected output:

NAME                                   READY   STATUS    RESTARTS   AGE
istio-ingressgateway-xxxx-xxxxx        1/1     Running   0          1m

Step 2: Translate Ingress rules to Istio VirtualService and DestinationRule

Convert each Nginx Ingress resource into a pair of Istio resources: a Gateway (already created in Step 1) and a VirtualService. If you need traffic policies such as connection pool settings or outlier detection, also create a DestinationRule.

Example: rewrite-based Ingress rule

Original Ingress:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: helloworld
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
  rules:
    - http:
        paths:
          - backend:
              serviceName: helloworld
              servicePort: 80
            path: /helloworld(/|$)(.*)
      host: example.com

Equivalent VirtualService:

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: example-vs
spec:
  gateways:
  - istio-system/ingressgateway    # Reference your gateway name
  hosts:
  - example.com
  http:
  - name: route-helloworld
    match:
    - uri:
        prefix: /helloworld/
    - uri:
        prefix: /helloworld
    rewrite:
      uri: /
    route:
    - destination:
        host: helloworld
        port:
          number: 80

Key differences from the Ingress resource:

  • The rewrite-target annotation becomes a rewrite.uri field in the VirtualService.

  • The regex path /helloworld(/|$)(.*) becomes two explicit prefix matches: /helloworld/ and /helloworld.

  • The host and routing rules are defined separately (Gateway vs. VirtualService) rather than in a single resource.

Important

Deploy VirtualService and DestinationRule resources in the same namespace as the corresponding Kubernetes Service. If you deploy them in a different namespace, use the fully qualified domain name (FQDN) format for destination.host (for example, helloworld.default.svc.cluster.local).

Verify the routes

Apply the VirtualService and confirm that the routes are accepted:

kubectl apply -f virtualservice.yaml
kubectl get virtualservice example-vs -o yaml

Check that the status section shows no errors or warnings.

Step 3: Verify the configurations

Verify that the configurations are valid and take effect by checking the traffic flow. Create a CLB instance, send traffic to the CLB instance, and check whether the traffic flow meets expectations. For more information, see Traffic flow.

Step 4: Shift traffic gradually

After the routing configuration is verified, increase the ingress gateway weight incrementally to migrate traffic:

  1. Start with a low weight (for example, 1) and monitor for errors.

  2. Increase the weight in stages -- for example, 1 -> 10 -> 30 -> 60 -> 100.

  3. At each stage, verify that latency, error rates, and response content remain consistent.

  4. After all traffic routes through the ingress gateway, set the Nginx Ingress Controller weight to 0.

How to adjust weights

ComponentHow to adjust
ASM ingress gatewayEdit the service.beta.kubernetes.io/alibaba-cloud-loadbalancer-weight annotation in the gateway configuration.
Nginx Ingress ControllerEdit the service.beta.kubernetes.io/alibaba-cloud-loadbalancer-weight annotation on the related Kubernetes Service. If no weight annotation exists, adjust the weight in the CLB console.
Important

The CLB scheduling algorithm must be set to weighted round-robin (WRR) for weight-based traffic splitting to work.

Next steps

After all traffic flows through the ASM ingress gateway:

  • Configure TLS termination on the ASM ingress gateway

  • Set up monitoring and access logging for the ingress gateway

  • Remove the Nginx Ingress Controller deployment after confirming stable operation

  • Explore Istio traffic management features such as fault injection, circuit breaking, and canary releases