Traffic splitting
Using HTTPRoutes, you can distribute traffic by percentage “weight”. This is useful for A/B tests and canary rollouts.
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.