Blue Green Deployment with Kubernetes
Tags: kubernetes, bluegreendeployment, deploymentstrategy, deploy
Published: 2023-04-02 07:52:34

Blue-green deployment is a software deployment strategy that allows the release of new features or updates without any downtime or service disruption. In this approach, two identical environments are created, one being the active or live environment (blue) and the other being the idle environment (green) where the new changes are deployed and tested before switching the traffic to the new environment.

The process of blue-green deployment involves the following steps:

1. The initial production environment (blue) is running and actively serving customer traffic.
2. A new environment (green) is created with the updated codebase or application version.
3. The new environment is thoroughly tested to ensure that everything is working correctly and that the application is stable.
4. Once the new environment is deemed stable, traffic is switched from the old environment to the new environment, and the old environment is decommissioned.

The main advantages of blue-green deployment are:

1. Reduced downtime: Since the new environment is tested thoroughly before deploying to the live environment, there is minimal to no downtime during the actual deployment process.

2. Risk mitigation: In case of any issues or bugs that might have been missed during testing, the old environment can be quickly switched back to, reducing the risk of downtime or service disruption.

3. Fast rollback: If any problems occur after the new environment is deployed, the switch back to the old environment can be done instantly, ensuring fast rollback with minimal impact to the end-users.

4. Increased reliability: Blue-green deployment enables a reliable and consistent approach to application updates, ensuring that there is minimal disruption to the end-users.

5. Testing in production: Blue-green deployment also allows for testing in production, which is an efficient way of testing new changes while avoiding any impact on the live environment.

### Blue-Green vs Canary

There is another popular deployment strategy called '[Canary Deployment](https://dev.to/hiteshrepo/canary-deployment-with-kubernetes-22c8)'.

Although they share some similarities, there are significant differences between the two.

Canary deployment is a technique that allows you to deploy new changes to a small subset of users or servers, often referred to as the "canary group," and then gradually roll out the changes to the rest of the users or servers. This approach allows you to test the new changes on a small scale before making them available to the entire user base.

One of the main differences between the two is that in blue-green deployment, both the old and new versions of the application are running at the same time, while in canary deployment, only one version of the application is running at a time. Another difference is that blue-green deployment typically involves switching the entire traffic from one environment to another, while canary deployment gradually increases the traffic to the new version.

Both deployment strategies have their advantages and disadvantages, and the choice between the two depends on various factors such as the size of the user base, the criticality of the application, and the available resources. Blue-green deployment is preferred when there are a large number of users, and the application needs to be highly available, while canary deployment is a good option when you want to test new changes on a small scale before rolling them out to the entire user base.

### Steps to demonstrate blue-green deployment

** Create Blue deployment  **

- with pod label `app: blue`
- with an busybox initContainer
```bash
initContainers:
    - name: install
    image: busybox:1.28
    command:
    - /bin/sh
    - -c
    - "echo blue > /work-dir/index.html"
    volumeMounts:
    - name: workdir
        mountPath: "/work-dir"
```

Final blue deployment:

```bash
apiVersion: apps/v1
kind: Deployment
metadata:
  name: blue-1.10
spec:
  replicas: 3
  selector:
    matchLabels:
      name: nginx
      app: blue
  template:
    metadata:
      labels:
        name: nginx
        app: blue
    spec:
      initContainers:
      - name: install
        image: busybox:1.28
        command:
        - /bin/sh
        - -c
        - "echo blue > /work-dir/index.html"
        volumeMounts:
        - name: workdir
          mountPath: "/work-dir"
      containers: 
        - name: nginx
          image: nginx:1.10
          ports:
          - name: http
            containerPort: 80
          volumeMounts:
          - name: workdir
            mountPath: /usr/share/nginx/html
      volumes:
      - name: workdir
        emptyDir: {}
```

** Create a service to interact with the blue deployment **

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

** Create both deployment and service **
```bash
kubectl create -f blue-deploy.yaml
kubectl create -f blue-green-svc.yaml
```

** Validate both the objects **
```bash
kubectl get deploy

NAME         READY   UP-TO-DATE   AVAILABLE   AGE
blue-1.10   3/3     3            3           4m37s


kubectl get svc

NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
nginx        ClusterIP   10.109.140.77    <none>        80/TCP    57s

kubectl get po

NAME                          READY   STATUS    RESTARTS   AGE
blue-1.10-579857b89c-jvthn   1/1     Running   0          5m51s
blue-1.10-579857b89c-thq2z   1/1     Running   0          5m51s
blue-1.10-579857b89c-vhrvc   1/1     Running   0          5m51s
```

** Test the deployment **
```bash
kubectl run -it --rm --restart=Never busybox --image=gcr.io/google-containers/busybox --command -- wget -qO- nginx

# o/p
blue
pod "busybox" deleted
```

** Create Green deployment **

Green deployment is same as blue except for label `app=green` and command echoing `green` instead of `blue`.

```bash
apiVersion: apps/v1
kind: Deployment
metadata:
  name: green-1.10
spec:
  replicas: 3
  selector:
    matchLabels:
      name: nginx
      app: green
  template:
    metadata:
      labels:
        name: nginx
        app: green
    spec:
      initContainers:
      - name: install
        image: busybox:1.28
        command:
        - /bin/sh
        - -c
        - "echo green > /work-dir/index.html"
        volumeMounts:
        - name: workdir
          mountPath: "/work-dir"
      containers: 
        - name: nginx
          image: nginx:1.10
          ports:
          - name: http
            containerPort: 80
          volumeMounts:
          - name: workdir
            mountPath: /usr/share/nginx/html
      volumes:
      - name: workdir
        emptyDir: {}
```

** Create green deployment **
```bash
kubectl create -f green-deploy.yaml
```

** Validate the green deployment **
```bash
kubectl get deployments

NAME         READY   UP-TO-DATE   AVAILABLE   AGE
blue-1.10    3/3     3            3           3m33s
green-1.10   3/3     3            3           2m29s

kubectl get po

NAME                          READY   STATUS    RESTARTS   AGE
blue-1.10-6c6ff57655-9p5pf    1/1     Running   0          3m52s
blue-1.10-6c6ff57655-knpf5    1/1     Running   0          3m52s
blue-1.10-6c6ff57655-wpgqp    1/1     Running   0          3m52s
green-1.10-7f754b7675-kfj89   1/1     Running   0          2m48s
green-1.10-7f754b7675-nd749   1/1     Running   0          2m48s
green-1.10-7f754b7675-nrd9m   1/1     Running   0          2m48s
```

** Update the selector of svc **

Change selector of service `nginx` from `app: blue` to `app: green`
```bash
apiVersion: v1
kind: Service
metadata: 
  name: nginx
  labels: 
    name: nginx
spec:
  ports:
    - name: http
      port: 80
      targetPort: 80
  selector: 
    name: nginx
    app: green
```

** Re-Apply the service object ***

```bash
kubectl apply -f blue-green-svc.yaml
```

** Test the deployment **
```bash
kubectl run -it --rm --restart=Never busybox --image=gcr.io/google-containers/busybox --command -- wget -qO- nginx

# o/p
green
pod "busybox" deleted
```


### Simple bash script to automate blue to green switch

```bash
#!/bin/bash

# bg-deploy.sh <service-name> <blue-deployment-name> <green-deployment-yaml-path> <green-deployment-name>

SERVICE=$1
BLUEDEPLOYMENTNAME=$2
GREENDEPLOYMENTFILE=$3
GREENDEPLOYMENTNAME=$2

kubectl apply -f $GREENDEPLOYMENTFILE

# Wait until the Green Deployment is ready by checking the MinimumReplicasAvailable condition.
READY=$(kubectl get deploy $GREENDEPLOYMENTNAME -o json | jq '.status.conditions[] | select(.reason == "MinimumReplicasAvailable") | .status' | tr -d '"')
while [[ "$READY" != "True" ]]; do
    READY=$(kubectl get deploy $GREENDEPLOYMENTNAME -o json | jq '.status.conditions[] | select(.reason == "MinimumReplicasAvailable") | .status' | tr -d '"')
    sleep 5
done

# Update the service selector with the new version
kubectl patch svc $SERVICE -p "{\"spec\":{\"selector\": {\"name\": \"${SERVICE}\", \"app\": \"green\"}}}"

# Delete blue deploy [optional]
kubectl delete deploy $BLUEDEPLOYMENTNAME

echo "Done."
```

In conclusion, blue-green deployment is an efficient and reliable approach to software deployment, allowing for the release of new features or updates with minimal to no downtime. With its ability to test in production, fast rollback, and reduced risk of service disruption, blue-green deployment is a preferred choice for applications that need to be highly available. While canary deployment shares some similarities with blue-green deployment, it differs in its approach to gradual rollout and testing on a small scale. The choice between the two deployment strategies depends on various factors, including the size of the user base, criticality of the application, and available resources. Overall, blue-green deployment is an excellent option for large applications that require high availability and reliability.