Canary Deployment with Kubernetes
Tags: canarydeployment, deployment, kubernetes, k8s
Published: 2023-04-01 10:43:39

In this post, we will learn how to do canary deployment using Kubernetes. In a canary deployment, a small set of users or requests are directed to a new version of the software while the majority of the traffic is still being handled by the old version. This allows us to test new versions of software in production without risking the entire system.

### Advantage of Canary Deployment

Canary deployment is a deployment strategy where a new version of an application is gradually rolled out to a small subset of users or servers before it is released to the entire user base. The advantages of canary deployment include:

1. Early detection of issues: Canary deployment allows you to test new features or changes on a small scale before rolling them out to your entire user base. This helps you to detect and fix any issues or bugs early on, minimizing the impact on your users.

2. Reduced risk: With canary deployment, you are reducing the risk of deploying new features or changes by limiting the scope of the rollout. This makes it easier to recover from any issues that may arise.

3. Better user experience: By gradually rolling out changes to a small subset of users, you can gather feedback and make adjustments before releasing the changes to your entire user base. This ensures a better user experience for your customers.

4. Improved performance: Canary deployment can improve the performance of your application by allowing you to test and optimize new features or changes on a small scale before rolling them out to your entire user base.

5. Increased agility: Canary deployment enables you to be more agile in your development process by allowing you to release new features or changes more frequently and with less risk. This can help you to stay ahead of the competition and meet the changing needs of your users.


### Steps to demontrate Canary Deployment

Let’s start by creating two nginx deployments with labels version=v1 and version=v2 to differentiate. We will call our first deployment nginx-app-1 and use the following command:

```bash
kubectl create deploy nginx-app-1 --image=nginx --replicas=3 --dry-run=client -o yaml > deploy-1.yaml
```

Next, we will edit the `deploy-1.yaml` file and add a label `app=v1` to the `metadata.labels` section. We will also add an `initContainers` section for the busybox pod:

```bash
initContainers:
  - name: install
    image: busybox:1.28
    command:
      - /bin/sh
      - -c
      - "echo version-1 > /work-dir/index.html"
    volumeMounts:
      - name: workdir
        mountPath: "/work-dir"
```

Now, let’s create a service for the deployment to be accessible:

```bash
apiVersion: v1
kind: Service
metadata:
  name: nginx-app-svc
  labels:
    app: nginx-app
spec:
  type: ClusterIP
  ports:
    - name: http
      port: 80
      targetPort: 80
  selector:
    app: nginx-app
```

We can test the deployment by running:

```bash
kubectl run -it --rm --restart=Never busybox --image=gcr.io/google-containers/busybox --command -- wget -qO- nginx-app-svc
```

Now, let’s create another similar deployment with one replica, but with a label value of `app=v2`. We will call this deployment `nginx-app-2`:

```bash
kubectl create deploy nginx-app-2 --image=nginx --replicas=1 --dry-run=client -o yaml > deploy-2.yaml
```

We will also edit the `deploy-2.yaml` file and add a label `app=v2` to the `metadata.labels` section. We will deploy this new version of the software by running:

```bash
kubectl apply -f deploy-2.yaml
```

We can continuously call the service to see how the load balancer diverts the traffic between the two versions. To do this, we can run:

```bash
kubectl run -it --rm --restart=Never busybox --image=gcr.io/google-containers/busybox -- /bin/sh -c 'while sleep 1; do wget -qO- nginx-app-svc; done'
```

Once we determine that `nginx-app-2` is stable and we would like to deprecate `nginx-app-1`, we can delete the old deployment by running:

```bash
kubectl delete deploy nginx-app-1
```

All traffic will then be directed to nginx-app-2. We can also scale nginx-app-2 to four replicas by running:

```bash
kubectl scale --replicas=4 deploy nginx-app-2
```

To check the traffic, we can run the following command:

```bash
while sleep 0.1; do curl $(kubectl get svc nginx-app-svc -o jsonpath="{.spec.clusterIP}"); done
```

In summary, canary deployment is a powerful tool that can help you to deploy new features or changes with more confidence and less risk. By gradually rolling out changes and gathering feedback, you can improve the user experience, performance, and agility of your application.