A/B Testing – DestinationRules in Practice

Traffic Management

Using the Envoy’s Istio provides a host of new capabilities to your cluster enabling:

  • Dynamic request routing: Canary deployments, A/B testing,
  • Load balancing: Simple and Consistent Hash balancing
  • Failure Recovery: timeouts, retries, circuit breakers.
  • Fault Injection: delays, abort requests etc.

In this series, we will showcase these capabilities in our application and get introduced to new concepts along the way. The first concept we will delve into is DestinationRules and using those to enable A/B Testing.

A/B Testing – Destination Rules in Practice

A/B Testing is used when we have two versions of an application (usually those differ visually) that we are not 100% sure which will increase user interaction and so we try both versions at the same time and collect metrics.

To demo this let’s deploy a second version of the frontend (a green button instead of the white one).  By executing the command below:

$ kubectl apply -f resource-manifests/kube/ab-testing/sa-frontend-green-deployment.yaml
deployment.extensions/sa-frontend-green created

The deployment manifest for the green version differs in two points:

  1. The image is based on a different tag: <image>:istio-green and
  2. Pods are labeled with version: green.

And as both deployments have the label app: sa-frontend requests routed by the virtual service sa-external-services to the service sa-frontend will be forwarded to all of them and will be load balanced using the round robin algorithm, which causes the issue presented in figure 1.

Fig. 1. Requested files are not found

The files are not found because they are named differently in the different versions of the app. Let’s verify that:

$ curl --silent http://$EXTERNAL_IP/ | tr '"' '\n' | grep main
/static/css/main.c7071b22.css
/static/js/main.059f8e9c.js

$ curl --silent http://$EXTERNAL_IP/ | tr '"' '\n' | grep main
/static/css/main.f87cd8c9.css
/static/js/main.f7659dbb.js

This means that for our app to work we need to introduce the restriction that “the version of the app that served the index.html, must serve subsequent files”.

We’ll achieve this using Consistent Hash Loadbalancing, which is the process that forwards requests from the same client to the same backend instance, using a predefined property, like an HTTP header.

The next Istio resource makes Consistent Hash Loadbalacing possible. Let’s dive into DestionatioRules.

DestinationRules

After a request gets routed by the VirtualService to the correct service, then using DestinationRules we can specify policies that apply to the traffic intended for the instances of this Service, as presented in figure 2.

Fig. 2. Istio resources affecting the network traffic

Note: Figure 2 visualizes how Istio resources are affecting the network traffic, in an easily understandable way. To be precise the decision to which pod to forward the request is done directly from the Ingress Gateway’s Envoy. And all the resources are configuring it.

Back to the main topic, using Destination Rules we can configure load balancing to have session affinity and ensure that the same user is responded by the same instance of the service. This is achievable with the following configuration:

  1. Generate a consistent hash according to the contents of the “version” header.

Apply the configuration by executing the command below and give it a try!

$ kubectl apply -f resource-manifests/istio/ab-testing/destinationrule-sa-frontend.yaml
destinationrule.networking.istio.io/sa-frontend created

Execute the command below and verify that you get the same files when specifying the version header:

$ curl --silent -H "version: yogo" http://$EXTERNAL_IP/ | tr '"' '\n' | grep main

Note: To test from the browser you can use this extension to add different values to the version header.

DestinationRules have even more LoadBalancing capabilities for all the details check out the official docs, and besides load balancing destination rules enable us to define service subsets, something very useful in upcomming sections.

Before moving on to explore VirtualService in more detail, remove the green version of the app and the destination rule by executing the commands below:

$ kubectl apply -f resource-manifests/kube/ab-testing/sa-frontend-green-deployment.yaml
deployment.extensions "sa-frontend-green" deleted
$ kubectl delete -f resource-manifests/istio/ab-testing/destinationrule-sa-frontend.yaml
destinationrule.networking.istio.io "sa-frontend" deleted
Shadowing – VirtualServices in Practice >>
If you enjoyed the article, please share and comment below!