Blue-green deployment involves simultaneously operating two application environments within a production cluster. In this deployment approach, the stable version of the application is deployed in the first environment (blue), while the new version is deployed in the second environment (green).
By default, Kubernetes performs a rolling update of a deployment. As part of the rollout process, the old version is replaced with the new version once the new version is up and running successfully. This happens without any interruption or very minimal impact. For specific applications, it may be necessary to maintain the old version in a “standby” mode for a period of time following the rollout of the new version. So that you can quickly switch to the older version in fraction of seconds.
In Kubernetes, you can achieve blue-green deployment by creating two identical environments, each with its own set of pods and services, and using a load balancer to route traffic between them. You can then deploy the new version of your software to the green environment and test it. Once you are satisfied that the new version is working correctly, you can switch the load balancer to route traffic to the green environment and make it the new live production environment. The blue environment then becomes the new test environment for future updates.
In this article, we will walk you through how blue-green deployments works using Kubernetes primitives.
1. Let’s deploy a new service in kubernetes. Create a manifest to deploy the nginx service.
uxpro-$ kubectl create deploy app1-blue --image=nginx:1.22.0 --dry-run=client -o yaml apiVersion: apps/v1 kind: Deployment metadata: creationTimestamp: null labels: app: app1 name: app1-blue spec: replicas: 1 selector: matchLabels: app: nginx strategy: {} template: metadata: creationTimestamp: null labels: app: app1 spec: containers: - image: nginx:1.22.0 name: nginx resources: {} status: {}
we can redirect the manifest to the file to edit it later.
uxpro-$ kubectl create deploy app1-blue --image=nginx --dry-run=client -o yaml > app1_deploy.yaml
2. Update the label like below. [ track: blue]
uxpro-$ cat app1_deploy.yaml apiVersion: apps/v1 kind: Deployment metadata: creationTimestamp: null labels: app: app1 track: blue name: app1-blue spec: replicas: 1 selector: matchLabels: app: app1 strategy: {} template: metadata: creationTimestamp: null labels: app: app1 spec: containers: - image: nginx:1.22.0 name: nginx resources: {} status: {}
3. Deploy the service using the updated manifest.
uxpro-$ kubectl create -f app1_deploy.yaml deployment.apps/app1-blue created uxpro-$ kubectl get deploy NAME READY UP-TO-DATE AVAILABLE AGE app1-blue 1/1 1 1 2m1s uxpro-$ uxpro-$ kubectl get all NAME READY STATUS RESTARTS AGE pod/app1-blue-58b85b46d9-5gkzp 1/1 Running 0 90s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/app1 NodePort 10.96.96.163 <none> 80:31288/TCP 68m NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/app1-blue 1/1 1 1 90s NAME DESIRED CURRENT READY AGE replicaset.apps/app1-blue-58b85b46d9 1 1 1 90s uxpro-$
4. Expose the nginx service to nodeport. In real production environment, you will have ingress setup to do that.
uxpro-$ kubectl expose --type=NodePort deployment app1 --port 80 service/app1 exposed uxpro-$ kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE app1 NodePort 10.96.96.163 <none> 80:31288/TCP 8s uxpro-$
5. Try to access the “nginx” instance from the node IP & port 31288.
root@k8s119-worker:/# curl 172.18.0.2:31288 <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> html { color-scheme: light dark; } body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Welcome to nginx!</h1> <p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p> <p>For online documentation and support please refer to <a href="http://nginx.org/">nginx.org</a>.<br/> Commercial support is available at <a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p> <h1> You are viewing Blue Deployment </h1> </body> </html>
6. Create a green deployment manifest like below.
apiVersion: apps/v1 kind: Deployment metadata: creationTimestamp: null labels: app: app1 track: green name: app1-green spec: replicas: 1 selector: matchLabels: app: app1 strategy: {} template: metadata: creationTimestamp: null labels: app: app1 spec: containers: - image: nginx:1.22.1 name: nginx resources: {} status: {}
7. Create a green deployment with an updated image version.
uxpro-$ kubectl create -f app1_deploy_v2.yaml deployment.apps/app1-green created uxpro-$ kubectl get all NAME READY STATUS RESTARTS AGE pod/app1-blue-58b85b46d9-5gkzp 1/1 Running 0 8m55s pod/app1-green-584f6b67c4-v88lb 1/1 Running 0 3s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/app1 NodePort 10.96.96.163 <none> 80:31288/TCP 75m NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/app1-blue 1/1 1 1 8m55s deployment.apps/app1-green 1/1 1 1 3s NAME DESIRED CURRENT READY AGE replicaset.apps/app1-blue-58b85b46d9 1 1 1 8m55s replicaset.apps/app1-green-584f6b67c4 1 1 1 3s
8. Currently we have two deployments up and running. But traffic is going to the blue deployments. To route the traffic to green deployment, we need to update the service.
uxpro-$ kubectl edit service/app1 apiVersion: v1 kind: Service metadata: creationTimestamp: "2023-03-26T01:16:56Z" labels: app: app1 track: green name: app1 namespace: default resourceVersion: "949529" selfLink: /api/v1/namespaces/default/services/app1 uid: ab2c9599-fa53-4798-85ee-66eb49210c88 spec: clusterIP: 10.96.96.163 externalTrafficPolicy: Cluster ports: - nodePort: 31288 port: 80 protocol: TCP targetPort: 80 selector: app: app1 sessionAffinity: None type: NodePort status: loadBalancer: {}
uxpro-$ kubectl edit service/app1 service/app1 edited uxpro-$
9. Try to access the “nginx” instance from the node IP & port 31288.
root@k8s119-worker:/# curl 172.18.0.2:31288 <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> html { color-scheme: light dark; } body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Welcome to nginx!</h1> <p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p> <p>For online documentation and support please refer to <a href="http://nginx.org/">nginx.org</a>.<br/> Commercial support is available at <a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p> <h1> You are viewing GREEN Deployment </h1> </body> </html> root@k8s119-worker:/#
We have successfully re-routed the traffic from blue deployments to green deployments. Kubernetes doesn’t support blue-green natively and we have duplicated the deployments to achieve this strategy. By using the blue-green deployment model, we can quickly re-route the traffic to the old deployment in case of any issues.
The drawback of this deployment strategy is resource duplication. It requires more resources since we are running two versions in parallel.
Hope this article is informative to you.
ramji ramagopalan says
Good one Lingesh