Pages

Monday, August 13, 2018

Kubernetes Deployment Strategy - Blue/Green

In this 3 post we will see how to do a blue/green deployment. A blue/green deployment is different from the rolling update in which a green version of the application is deployed along with the blue version. After testing the green version and once satisfied we will update the service to point to the green version. This way we will route the traffic from blue version to green version. This is done by playing with the labels in the selector fields. Once the traffic is moved to the green version, the blue version pods are terminated.

Lets create the blue deployment first as,
[root@manja17-I13330 kubenetes-config]# cat  blue-deployment.yml
apiVersion: v1
kind: Service
metadata:
  name: testing-service
  labels:
    app: testing-service
spec:
  type: NodePort
  ports:
  - name: http
    port: 80
    targetPort: http

  # Note here that we match both the app and the version
  selector:
    app: testing-service
    version: "1.0"
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: testing-service-v1
  labels:
    app: testing-service
spec:
  replicas: 3
  selector:
    matchLabels:
      app: testing-service
      version: "1.0"
  template:
    metadata:
      labels:
        app: testing-service
        version: "1.0"
    spec:
      containers:
      - name: testing-service
        image: docker.io/jagadesh1982/testing-service
        ports:
        - name: http
          containerPort: 9876
        env:
        - name: VERSION
          value: "1.0"

[root@manja17-I13330 kubenetes-config]# kubectl apply -f blue-deployment.yml
service "testing-service" created
deployment.apps "testing-service-v1" created

[root@manja17-I13330 kubenetes-config]# kubectl get pods
NAME                                             READY      STATUS    RESTARTS   AGE
testing-service-v1-bc6866889-g8zrr    1/1        Running      0              5m
testing-service-v1-bc6866889-lj8f7     1/1        Running      0              5m
testing-service-v1-bc6866889-qnr2r   1/1         Running      0              5m

[root@manja17-I13330 kubenetes-config]# kubectl get svc
NAME                TYPE          CLUSTER-IP       EXTERNAL-IP   PORT(S)           AGE
kubernetes        ClusterIP    10.96.0.1           <none>          443/TCP           1d
testing-service   NodePort    10.110.200.110  <none>          80:30009/TCP   5m

[root@manja17-I13330 kubenetes-config]# curl 10.99.143.66/info
{"host": "10.99.143.66", "version": "1.0", "from": "10.32.0.1"}

Lets run the green deployment,with the below manifest file,
[root@manja17-I13330 kubenetes-config]# cat green-deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: testing-service-v2
  labels:
    app: testing-service
spec:
  replicas: 3
  selector:
    matchLabels:
      app: testing-service
      version: "2.0"
  template:
    metadata:
      labels:
        app: testing-service
        version: "2.0"
    spec:
      containers:
      - name: testing-service
        image: docker.io/jagadesh1982/testing-service
        ports:
        - name: http
          containerPort: 9876
        env:
        - name: VERSION
          value: "2.0"

[root@manja17-I13330 kubenetes-config]# kubectl apply -f green-deployment.yml
deployment.apps "testing-service-v2" created

[root@manja17-I13330 kubenetes-config]# kubectl get pods
NAME                                              READY     STATUS    RESTARTS   AGE
testing-service-v1-bc6866889-g8zrr    1/1       Running             0          8m
testing-service-v1-bc6866889-lj8f7     1/1       Running             0          8m
testing-service-v1-bc6866889-qnr2r    1/1       Running            0          8m
testing-service-v2-7f966d5d4c-mb2fk  1/1       Running            0          2m
testing-service-v2-7f966d5d4c-qs6fz   1/1       Running             0          2m
testing-service-v2-7f966d5d4c-z4tj4   1/1       Running             0          2m

Side by side, 3 pods are running with version 2 but the service still send traffic to the first deployment. If necessary, you can manually test one of the pod by port-forwarding it to your local environment. Once your are ready, you can switch the traffic to the new version by patching the service to send traffic to all pods with label version=v2.0.0:

[root@manja17-I13330 kubenetes-config]# kubectl patch service testing-service -p '{"spec":{"selector":{"version":"2.0"}}}'
service "testing-service" patched

[root@manja17-I13330 kubenetes-config]# kubectl get svc
NAME              TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
kubernetes        ClusterIP   10.96.0.1        <none>          443/TCP            1d
testing-service   NodePort    10.99.143.66  <none>          80:30126/TCP   3m

[root@manja17-I13330 kubenetes-config]# curl 10.99.143.66/info
{"host": "10.99.143.66", "version": "2.0", "from": "10.32.0.1"}

If you want to rollback to the older version , we can use
[root@manja17-I13330 kubenetes-config]# kubectl patch service testing-service -p '{"spec":{"selector":{"version":"1.0"}}}'
service "testing-service" patched

[root@manja17-I13330 kubenetes-config]# kubectl get svc
NAME              TYPE           CLUSTER-IP     EXTERNAL-IP   PORT(S)          AGE
kubernetes        ClusterIP   10.96.0.1         <none>          443/TCP           1d
testing-service   NodePort   10.99.143.66   <none>          80:30126/TCP   4m

[root@manja17-I13330 kubenetes-config]# curl 10.99.143.66/info
{"host": "10.99.143.66", "version": "1.0", "from": "10.32.0.1"}

[root@manja17-I13330 kubenetes-config]# kubectl get deploy
NAME                    DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
testing-service-v1   3               3                 3                 3                5m
testing-service-v2   3               3                 3                 3                2m

Once we are happy with the green version, delete the blue deployment using,
[root@manja17-I13330 kubenetes-config]# kubectl delete deploy testing-service-v1
deployment.extensions "testing-service-v1" deleted

Now check the pods ,
[root@manja17-I13330 kubenetes-config]# kubectl get pods
NAME                                                READY     STATUS        RESTARTS   AGE
testing-service-v1-bc6866889-dthrt      1/1         Terminating      0             5m
testing-service-v1-bc6866889-nk282    1/1         Terminating      0             5m
testing-service-v1-bc6866889-rxdtz      1/1         Terminating      0             5m
testing-service-v2-76dcdbd6bc-g56bh   1/1         Running           0             3m
testing-service-v2-76dcdbd6bc-jbvkw    1/1         Running           0             3m
testing-service-v2-76dcdbd6bc-s4zg2    1/1         Running           0             3m

We can see the blue version of pods are being terminated and green version are up and running. This is how we will be doing a blue/green deployment in kubernetes.

More to Come, Happy learning :-)

No comments :

Post a Comment