You can split Istio traffic between two service versions and achieve A/B testing by configuring Istio’s VirtualService and DestinationRule resources.

Let’s say we have a service called my-app running two versions: v1 and v2. We want to send 90% of traffic to v1 and 10% to v2.

Here’s how you’d set that up:

First, the DestinationRule. This tells Istio where it can send traffic for my-app.

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: my-app-dest
spec:
  host: my-app
  subsets:
  - name: v1
    labels:
      version: v1
  - name: v2
    labels:
      version: v2

This DestinationRule defines two subsets, v1 and v2, for the my-app host. These subsets are distinguished by labels on the Kubernetes pods. If your pods for v1 have the label version: v1 and your pods for v2 have version: v2, Istio will know how to route to them.

Next, the VirtualService. This is where the traffic splitting logic lives.

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: my-app-vs
spec:
  hosts:
  - my-app
  http:
  - route:
    - destination:
        host: my-app
        subset: v1
      weight: 90
    - destination:
        host: my-app
        subset: v2
      weight: 10

This VirtualService tells Istio that for requests coming to my-app, 90% should be routed to the v1 subset (defined in the DestinationRule) and 10% to the v2 subset.

When a request arrives at the Istio ingress gateway or an Istio-enabled sidecar proxy, it consults the VirtualService. Based on the defined weights, it directs the request to the appropriate version of the my-app service. The DestinationRule ensures that the traffic is then sent to pods matching the specified subset labels.

You can dynamically change these weights without redeploying your application. For example, to increase traffic to v2 to 50%:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: my-app-vs
spec:
  hosts:
  - my-app
  http:
  - route:
    - destination:
        host: my-app
        subset: v1
      weight: 50
    - destination:
        host: my-app
        subset: v2
      weight: 50

Applying this updated VirtualService will immediately start shifting traffic.

Beyond simple percentage-based splitting, Istio’s VirtualService can also route traffic based on request headers, URIs, and other attributes. This is incredibly powerful for more sophisticated A/B testing scenarios. For instance, you could send all users with a specific user-agent header to v2, or all requests to a particular URI path.

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: my-app-vs-advanced
spec:
  hosts:
  - my-app
  http:
  - match:
    - headers:
        user-agent:
          regex: ".*Chrome.*" # Send Chrome users to v2
    route:
    - destination:
        host: my-app
        subset: v2
      weight: 100
  - match:
    - uri:
        prefix: "/feature-x" # Send requests to /feature-x to v2
      route:
      - destination:
          host: my-app
          subset: v2
        weight: 100
  - route: # Default route for all other traffic
    - destination:
        host: my-app
        subset: v1
      weight: 100

This example shows how you can use match conditions to create more granular traffic routing rules. The first match sends all Chrome users to v2. The second match sends requests to /feature-x to v2. If neither of these conditions is met, the final route block sends all other traffic to v1.

The real magic of Istio’s traffic management isn’t just in splitting percentages; it’s in the ability to define these splits based on arbitrary request characteristics. This allows you to target specific user segments or test features under particular conditions without modifying your application code.

What most people don’t realize is that the weight values in the VirtualService are not absolute guarantees but rather probabilities. When a request arrives, Istio’s proxy (Envoy) effectively rolls a weighted die for each request to decide which destination to send it to. For small numbers of requests, the distribution might not perfectly match the weights, but as the request volume increases, the observed traffic split will converge towards the configured percentages. This probabilistic nature is what makes it efficient and dynamic.

The next step after setting up A/B testing is typically implementing canary deployments, where you gradually roll out a new version to a small subset of users before a full release.

Want structured learning?

Take the full Istio course →