Version B is released to a subset of users, then proceed to a full rollout.
A canary deployment consists of gradually shifting production traffic from version A to version B. Usually the traffic is split based on weight. For example, 90 percent of the requests go to version A, 10 percent go to version B.
This technique is mostly used when the tests are lacking or not reliable or if there is little confidence about the stability of the new release on the platform.
In the following example we apply the poor man's canary using Kubernetes native features (replicas). If you want a finer grained control over traffic shifting, check the a/b testing example which contain an example of traffic shifting using Isio).
- 10 replicas of version 1 is serving traffic
- deploy 1 replicas version 2 (meaning ~10% of traffic)
- wait enought time to confirm that version 2 is stable and not throwing unexpected errors
- scale up version 2 replicas to 10
- wait until all instances are ready
- shutdown version 1
Deploy the first application:
$ kubectl apply -f app-v1.yaml
Wait until the service IP is available:
$ kubectl get svc my-app
Test if the deployment was successful:
$ curl $(kubectl get svc -o jsonpath="{.status.loadBalancer.ingress[0].ip}" my-app)
2018-01-28T00:22:04+01:00 - Host: host-1, Version: v1.0.0
Before deploying the new release, open a new terminal and run the following command To see the deployment in action:
$ watch kubectl get po
Then, in the previous terminal, deploy version 2 of the application:
$ kubectl apply -f app-v2.yaml
Only one pod with the new version should be running.
You can test if the second deployment was successful:
$ service=$(kubectl get svc -o jsonpath="{.status.loadBalancer.ingress[0].ip}" my-app)
$ while sleep 0.1; do curl "$service"; done
If you are happy with it, scale up the version 2 to 10 replicas:
kubectl scale --replicas=10 deploy my-app-v2
Then, when all pods are running, you can safely delete the old deployment:
kubectl delete deploy my-app-v1
$ kubectl delete all -l app=my-app