Modern Applications Deployment Strategies with Kubernetes¶
7 January 2019¶
Applications deployment is coming at the end of the CI/CD pipeline. Nowadays, we have multiple tools available to help us deploy safely and with the less possible negative impact on our final users. Here, I am mainly thinking of Spinnaker, Terraform or Kubernetes, but there are many other tools.
However, it is still the most feared part of the complete application release process, and that's because we are possibly impacting our end users.
I had recently the chance to experiment different types of deployments to Kubernetes and would like to share them with you. Here are the different deployment strategies available to you natively within Kubernetes today:
- rolling update
- recreate
- blue/green
Rolling Update¶
This strategy is the one used by default in Kubernetes. It consists in creating a new replicat of the application before removing an old one and repeat this operation as many time as needed.
The flow¶
- We have a
V1of an application already deployed on our cluster and served by a service:
- We apply an updated deployment definition, which create a
V2deployment and a firstV2pod, once thisV2first pod is healthy, Kubernetes begins to serve traffic:
- At this stage one of the
V1pods is not needed anymore and is removed:
- Kubernetes continues the rollout of the new version of our application by provisioning a new
V2instance:
- At the end we rollout all the pods of the
V2version of the app and have deleted all the pods of theV1version:
Pros¶
- Easy to put in place
- No downtime
Cons¶
- Slow deployments
The code¶
The deployment strategy has to be specified in the deployment manifest.
For the rolling update strategy we can tune 2 settings:
maxSurge: define how many pods we can add to the desired replica number at an instant tmaxUnavailable: define how many pods can be unavailable at an instant t
In large deployment with spare cpu and ram capacities, you can bump up the maxSurge number to speed up the new version release.
Here is what would such a deployment look like:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | |
Recreate¶
This strategy consists in creating new replica of the application after removing the old ones. In this case the additional resource consumption needed during the update is null and the operation can be fairly quick. However, updating using the Recreate strategy causes a downtime.
I found this type of update particularly useful if you need one pod to have access to one persistent volume at a time. You can find an example of this usage here{:target="_blank"}
The flow¶
- Again we have a
V1of an application already deployed on our cluster and served by a service:
- We apply the
V2version, which triggers the deletion of theV1deployment and pods:
- The
V2pods are created and served once healthy:
Pros¶
- Easy to put in place
- Fairly quick deployment
Cons¶
- Downtime
The code¶
The only manifest we need to modify here is the deployment one and there is not that much that we can customise.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | |
Blue/Green¶
The deployment strategy consists into first creating all the components of a V2 application before switching traffic to it and deleting the V1 application.
The flow¶
- As always, we have the same starting point, a
V1of an application already deployed on our cluster and served by a service:
- We begin by creating a new deployment of the
V2application:
- Once the
V2deployment is complete and healthy, we update our service to serve theV2application:
- Once we do not need the
V1deployment anymore (eg: we are sure we do not need to rollback), we delete theV1deployment:
Pros¶
- Quick roll back available
- No versioning/state issue
Cons¶
- High resource consumption
- Not native to Kubernetes (more steps to orchestrate manually)
The code¶
We will need to have 3 manifests in this case, one for the V1 deployment, a second one for the V2 deployment and a last one for the service used to expose the deployments.
Here is the V1 deployment to get the initial deployment:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | |
Our service manifest to expose our V1 deployment:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | |
When we want to update our app version, here is our V2 deployment:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | |
Once our V2 deployment is healthy and ready to serve traffic, we update our service manifest:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | |
Don't forget to delete the V1 deployment once you are sure it is not needed anymore
Conclusion¶
Choose the best strategy for your use case. The rolling update one will suits 90% of them, the recreate one will be particularly useful if you are managing state and a downtime is accessible, the blue/green one is certainly the safest.
If you want to have more control over your deployments, there are much more update strategies options that are available if you are using service mesh, the canary release one or the A/B testing one are some of the interesting ones.
