Kubernetes – Deployments
January 30, 2019After following the previous posts, we should feel pretty good about deploying our pods and ensuring they are highly available. We’ve learned about naked pods and then replica sets to make those pods more HA, but what about when we need to create a new version of our pods? We don’t want to have an outage when our pods are replaced with a new version do we? This is where “Deployments” comes into play.
Deployments – The Theory
If you couldn’t tell from the introduction to this post, Deployments are an amazing object for us to handle changes to our applications. While replica sets are used to ensure a desired number of pods are always running and handle our high availability concerns, Deployments ensure that we can safely rollout new versions of our pods safely and without outages. They also make it possible to rollback a deployment if there is some terrible issue with the new version.
Now, I want to make sure that we don’t think that Deployments replace replica sets because they don’t. Deployments are a construct a level above replica sets and actually manage the replica set objects.
So Deployments manage replica sets and replica sets manage pods and pods manage containers.
Deployments – In Action
Just as we have done with the other posts in this series we’ll start with creating a manifest file of our desired state configuration. Kubernetes will ensure that this desired state is applied and any items that need to be orchestrated will be handled to meet this configuration.
We’ll start by adding Deployment information to the replica set manifest we built previously. Remember that a Deployment sits at a level above replica sets so we can add the new construct to our manifest file we created in the replica set post. As usual, comments have been added to the file so it’s easier to follow.
apiVersion: apps/v1 #version of the API to use
kind: Deployment #What kind of object we're deploying
metadata: #information about our object we're deploying
name: nginx-deployment #Name of the deployment
labels: #A tag on the deployments created
app: nginx
spec: #specifications for our object
replicas: 2 #The number of pods that should always be running
selector: #which pods the replica set should be responsible for
matchLabels:
app: nginx #any pods with labels matching this I'm responsible for.
template: #The pod template that gets deployed
metadata:
labels: #A tag on the replica sets created
app: nginx
spec:
containers:
- name: nginx-container #the name of the container within the pod
image: nginx #which container image should be pulled
ports:
- containerPort: 80 #the port of the container within the pod
Code language: PHP (php)
Now we’ll deploy this configuration to our kubernetes cluster by running:
kubectl apply -f [manifest file].yml
Code language: CSS (css)
Once the deployment has been applied to our cluster, we’ll run:
kubectl get deployments
Code language: JavaScript (javascript)
The results of our deployment should look similar to the following screenshot.
There are several columns listed here but the gist of it is:
- DESIRED – 2 replicas of the application were in our configuration.
- CURRENT – 2 replicas are currently running.
- UP-TO-DATE – 2 replicas that have been updated to get to the configuration we specified.
- AVAILABLE – 2 replicas are available for use
This information may not seem to interesting at the moment, but remember that Deployments can take an existing set and perform a rolling update on them. When this occurs the information shown here may be more important.
Let’s try to update our deployment and see what happens. Let’s modify our deployment manifest file to increase the number of replicas and also change the version of nginx that is being deployed. The file below makes those changes for you.
apiVersion: apps/v1 #version of the API to use
kind: Deployment #What kind of object we're deploying
metadata: #information about our object we're deploying
name: nginx-deployment #Name of the deployment
labels: #A tag on the deployments created
app: nginx
spec: #specifications for our object
strategy:
type: RollingUpdate
rollingUpdate: #Update Pods a certain number at a time
maxUnavailable: 1 #Total number of pods that can be unavailable at once
maxSurge: 1 #Maximum number of pods that can be deployed above desired state
replicas: 6 #The number of pods that should always be running
selector: #which pods the replica set should be responsible for
matchLabels:
app: nginx #any pods with labels matching this I'm responsible for.
template: #The pod template that gets deployed
metadata:
labels: #A tag on the replica sets created
app: nginx
spec:
containers:
- name: nginx-container #the name of the container within the pod
image: nginx:1.7.9 #which container image should be pulled
ports:
- containerPort: 80 #the port of the container within the pod
Code language: PHP (php)
We can apply the configuration file again and then check our Deployment status using some familiar commands:
kubectl apply -f [new manifest file].yml
kubectl get deployments
Code language: JavaScript (javascript)
Now we see some more interesting information. Depending on how fast you were with your commands, you might get different results so use the screenshot below for this discussion.
Since I ran the get deployments command before the whole thing was finished, my desired state doesn’t match the current state. In fact, the current state has MORE replicas than are desired. The reason for this is that the new pods are deployed first and then the old pods are removed.
In the example below, you can see that we’re going to remove the version 1 containers while we spin up version 2. To do this we spin up one pod with the new version and then start terminating the old pods. When this is done, the next pod will be created in version 2 and eventually the last pod in version 1 will be removed.
The number of pods being deployed above desired state is configured in our manifest in the maxSurge specification. We could have made this number 2 and then two pods would be created at a time and two removed.
Now, sometimes you have a bigger update than the one we used for a demonstration. In that case you might not want to keep running the get deployments command. You can run:
kubectl rollout status deployment [deployment name]
Code language: CSS (css)
This command will show you a running list of whats happening with the rollout. I ran this during the deploy and here is an example of what you might see.
Summary
Deployments are just another step along the way in learning Kubernetes. We’ve gotten to a pretty good point here and now we know how we can deploy and update our deployments in our cluster. We STILL haven’t accessed our containers yet, but just hold on, we’re at the cusp of having a working container.
When you’re done messing around with your cluster you can delete the deployment by running:
kubectl delete -f [manifest file].yml
Code language: CSS (css)