A/B Testing with the Iter8 SDK¶
This tutorial describes how to do A/B testing of a backend component using the Iter8 SDK.
Before you begin
- Ensure that you have a Kubernetes cluster and the
kubectl
andhelm
CLIs. You can create a local Kubernetes cluster using tools like Kind or Minikube. - Have Grafana available. For example, Grafana can be installed on your cluster as follows:
kubectl create deploy grafana --image=grafana/grafana kubectl expose deploy grafana --port=3000
Install the Iter8 controller¶
helm install --repo https://iter8-tools.github.io/iter8 --version 0.1.12 iter8 controller
helm install --repo https://iter8-tools.github.io/iter8 --version 0.1.12 iter8 controller \
--set clusterScoped=true
kubectl apply -k 'https://github.com/iter8-tools/iter8.git/kustomize/controller/namespaceScoped?ref=v0.17.1'
kubectl apply -k 'https://github.com/iter8-tools/iter8.git/kustomize/controller/clusterScoped?ref=v0.17.1'
Deploy the sample application¶
A sample application using the Iter8 SDK is provided. Deploy both the frontend and backend components of this application as described in each tab:
Install the frontend component using an implementation in the language of your choice:
kubectl create deployment frontend --image=iter8/abn-sample-frontend-node:0.15.0
kubectl expose deployment frontend --name=frontend --port=8090
kubectl create deployment frontend --image=iter8/abn-sample-frontend-go:0.15.0
kubectl expose deployment frontend --name=frontend --port=8090
The frontend component is implemented to call Lookup()
before each call to the backend component. The frontend component uses the returned version number to route the request to the recommended version of the backend component.
Deploy an initial version of the backend component:
kubectl create deployment backend --image=iter8/abn-sample-backend:0.13-v1
kubectl label deployment backend iter8.tools/watch="true"
kubectl expose deployment backend --name=backend --port=8091
Describe the application¶
In order to support Lookup()
, Iter8 needs to know what the application component versions look like. A ConfigMap
is used to describe the make up of possible versions:
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ConfigMap
metadata:
name: backend
labels:
app.kubernetes.io/managed-by: iter8
iter8.tools/kind: routemap
iter8.tools/version: "v0.17"
immutable: true
data:
strSpec: |
versions:
- resources:
- gvrShort: svc
name: backend
namespace: default
- gvrShort: deploy
name: backend
namespace: default
- resources:
- gvrShort: svc
name: backend-candidate-1
namespace: default
- gvrShort: deploy
name: backend-candidate-1
namespace: default
EOF
In this definition, each version of the application is composed of a Service
and a Deployment
. In the primary version, both are named backend
. In any candidate version they are named backend-candidate-1
. Iter8 uses this definition to identify when any of the versions of the application are available. It can then respond appropriately to Lookup()
requests.
Generate load¶
In separate shells, port-forward requests to the frontend component and generate load for multiple users. A script is provided to do this. To use it:
kubectl port-forward service/frontend 8090:8090
curl -s https://raw.githubusercontent.com/iter8-tools/docs/v0.15.0/samples/abn-sample/generate_load.sh | sh -s --
Deploy candidate¶
Deploy the candidate version of the backend component, naming it backend-candidate-1
.
kubectl create deployment backend-candidate-1 --image=iter8/abn-sample-backend:0.13-v2
kubectl label deployment backend-candidate-1 iter8.tools/watch="true"
kubectl expose deployment backend-candidate-1 --name=backend-candidate-1 --port=8091
Until the candidate version is ready; that is, until all expected resources are deployed and available, calls to Lookup()
will return only the version number 0
; the existing version. Once the candidate version is ready, Lookup()
will return both version numbers (0
and 1
) so that requests can be distributed across versions.
Compare versions using Grafana¶
Inspect the metrics using Grafana. If Grafana is deployed to your cluster, port-forward requests as follows:
kubectl port-forward service/grafana 3000:3000
Open Grafana in a browser by going to http://localhost:3000
Add a JSON API data source default/backend
with the following parameters:
- URL:
http://iter8.default:8080/abnDashboard
- Query string:
namespace=default&application=backend
Create a new dashboard by import. Copy and paste the contents of the abn
Grafana dashboard into the text box and load it. Associate it with the JSON API data source above.
The Iter8 dashboard allows you to compare the behavior of the two versions of the backend component against each other and select a winner. Since user requests are being sent by the load generation script, the values in the report may change over time. The Iter8 dashboard will look like the following:
Once you identify a winner, it can be promoted, and the candidate version deleted.
Promote candidate¶
To promote the candidate version (backend-candidate-1
), first update the primary version, backend
, using the new image. You can also overwrite any metadata describing the version.
kubectl set image deployment/backend abn-sample-backend=iter8/abn-sample-backend:0.13-v2
Finally, delete the candidate version:
kubectl delete svc/backend-candidate-1 deploy/backend-candidate-1
Calls to Lookup()
will now recommend that all traffic be sent to the primary version backend
(currently serving the promoted version of the code).
Cleanup¶
Delete the sample application:
kubectl delete \
svc/frontend deploy/frontend \
svc/backend deploy/backend \
svc/backend-candidate-1 deploy/backend-candidate-1
Delete the application description:
kubectl delete cm/backend
Uninstall the Iter8 controller:
helm delete iter8
kubectl delete -k 'https://github.com/iter8-tools/iter8.git/kustomize/controller/namespaceScoped?ref=v0.17.1'
kubectl delete -k 'https://github.com/iter8-tools/iter8.git/kustomize/controller/clusterScoped?ref=v0.17.1'