Traffic splitting

Traffic splitting

Using HTTPRoutes, you can distribute traffic by percentage “weight”. This is useful for A/B tests and canary rollouts.

Traffic splitting is supported at the edge of a cluster using a gateway, or when a workload is enrolled in the waypoint layer. Learn about the different configurations required in each case.

If you don’t already have a waypoint installed for the default namespace, install one:

$ istioctl waypoint apply --enroll-namespace --wait

Route to a single version

The Bookinfo sample application comes with three different versions of the reviews microservice:

$ kubectl get pods
NAME                             READY   STATUS    RESTARTS   AGE
details-v1-cf74bb974-nw94k       1/1     Running   0          42s
productpage-v1-87d54dd59-wl7qf   1/1     Running   0          42s
ratings-v1-7c4bbf97db-rwkw5      1/1     Running   0          42s
reviews-v1-5fd6d4f8f8-66j45      1/1     Running   0          42s
reviews-v2-6f9b55c5db-6ts96      1/1     Running   0          42s
reviews-v3-7d99fd7978-dm6mx      1/1     Running   0          42s

The corresponding Kubernetes Service is set up to target all pods with the label app: reviews.

apiVersion: v1
kind: Service
metadata:
  name: reviews
spec:
  ports:
  - port: 9080
    name: http
  selector:
    app: reviews

There are also version labels, but these are not used. Because of this, any calls to the reviews service will be load balanced between the three running pods. You can see this by accessing the application, and noting that on each reload, the book reviews alternate between showing no stars (v1), black stars (v2) or red stars (v3).

Using a HTTPRoute, we can set all requests to the reviews service to be sent to a particular version, or versions in a defined ratio. First, we have to create some more services, which more specifically target the versions:

apiVersion: v1
kind: Service
metadata:
  name: reviews-v1
spec:
  ports:
  - port: 9080
    name: http
  selector:
    app: reviews
    version: v1
---
apiVersion: v1
kind: Service
metadata:
  name: reviews-v2
spec:
  ports:
  - port: 9080
    name: http
  selector:
    app: reviews
    version: v2
---
apiVersion: v1
kind: Service
metadata:
  name: reviews-v3
spec:
  ports:
  - port: 9080
    name: http
  selector:
    app: reviews
    version: v3

There are now four services: reviews, reviews-v1, reviews-v2 and reviews-v3. The productpage service, that calls the reviews service, is hard-coded to only use the first.

To configure the mesh so that all traffic destined for reviews is sent to reviews-v1, create an HTTPRoute with a single backend:

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: reviews
spec:
  parentRefs:
  - group: ""
    kind: Service
    name: reviews
    port: 9080
  rules:
  - backendRefs:
    - name: reviews-v1
      port: 9080

Now, if you refresh the product page, you will always hit the version of reviews that does not show star ratings.

Traffic shifting

A HTTPRoute can contain more than one backend, which allows you to weight the routing of requests between more than one service.

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: reviews
spec:
  parentRefs:
  - group: ""
    kind: Service
    name: reviews
    port: 9080
  rules:
  - backendRefs:
    - name: reviews-v1
      port: 9080
      weight: 50
    - name: reviews-v3
      port: 9080
      weight: 50

Requests will now be balanced equally between v1 and v3 of the service. You can see this by refreshing the page, and noting you see red stars approximately 50% of the time.

When you decide that the new service is operating as expected, you can

Canary deployments

A more specific match will take precedence over a more generic match in a route rule. This can be used for canary deployment, where a group of users should see different behavior.

An easy way to demonstrate this is using an HTTP header. If you log into the Bookinfo application, the end-user header is set to the user you have chosen. You can use this to make routing decisions:

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: reviews
spec:
  parentRefs:
  - group: ""
    kind: Service
    name: reviews
    port: 9080
  rules:
  - backendRefs:
    - name: reviews-v1
      port: 9080
  - backendRefs:
    - name: reviews-v2
      port: 9080
    matches:
    - headers:
      - name: end-user
        value: blackstar

If you log in with the username blackstar (use any password) then your requests will be routed to the reviews-v2 service, which shows star ratings using black stars.