Kubernetes – Deployments

Kubernetes – Deployments

January 30, 2019 0 By Eric Shanks

After 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 podCode language: PHP (php)

Now we’ll deploy this configuration to our kubernetes cluster by running:

kubectl apply -f [manifest file].ymlCode language: CSS (css)

Once the deployment has been applied to our cluster, we’ll run:

kubectl get deploymentsCode 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 deploymentsCode 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].ymlCode language: CSS (css)