We will perform the Canary deployment manually through GitOps and creating / modifying the main Kubernetes resources. This article is intended primarily for acquaintance with how deployment works in Kubernetes Canary, as there are more efficient ways to automate, which we will look at in future articles.
With the Canary strategy, updates are first applied to only a subset of users. Through monitoring, logging, manual testing, or other feedback channels, the release is tested before it is released to all users.
Kubernetes Deployment (rolling update)
The default strategy for Kubernetes Deployment is rolling-update, where a certain number of pods are launched with new image versions. If they were created without problems, the pods with the old versions of the images are terminated, and the new pods are created in parallel.
gitops
We are using GitOps in this example because we:
using Git as a single source of truth
use Git Operations to build and deploy (no commands other than git tag/merge needed)
Example
Let's take a good practice - to have one repository for application code and one for infrastructure.
Application repository
This is a very simple Python+Flask API that returns a JSON response. We will build the package via GitlabCI and push the result to the Gitlab Registry. In the registry, we have two different release versions:
wuestkamp/k8s-deployment-example-app:v1
wuestkamp/k8s-deployment-example-app:v2
The only difference between them is the change in the returned JSON file. We use this app to visualize as easily as possible which version we are talking to.
infrastructure repository
In this turnip, we will deploy via GitlabCI to Kubernetes, .gitlab-ci.yml as follows:
We push these changes to the repository from which the deployment will start (via GitlabCI) and see as a result:
Our Service will point to both deployments since both have the app selector. Due to the default random distribution in Kubernetes, we should see different responses for ~10% of requests:
The current state of our application (GitOps, taken from Git as Single Source Of Truth) is having two deployments with active replicas, one for each version.
~10% of users become familiar with the new version and unintentionally test it. Now it's time to check for errors in the logs and monitoring data to find problems.
Step 2: Release the new version to all users
We decided that everything went well and now we need to deploy the new version to all users. To do this, we simply update deploy.yaml installing a new version of the image and the number of replicas is 10. In deploy-canary.yaml we set the number of replicas back to 0. After deployment, the result will be as follows:
Summing up
For me, running a deployment manually in this way helps to understand how easily it can be configured with k8s. Since Kubernetes allows you to update everything through an API, these steps can be automated through scripts.
Another thing to implement is a tester entry point (LoadBalancer or via Ingress) through which only the new version can be accessed. It can be used for manual browsing.
In future articles, we'll check out other automated solutions that implement most of what we've done.