Oftentimes you'll want to have multiple instances of the same Pod.

  • Multiple Pods inherently confer resiliency to your application, since if one were to become unavailable, others would be there to prevent downtime.
  • If your application is under a heavy load, you'll want to be able to add more Pods having the same container image in order to spread the load.
  • Or, if you're doing a canary release, you'd want there to be a certain number of instances of a Pod.

You can accomplish all these through Deployments. Deployments are Kubernetes objects that manage replicas of Pods. They know a desired number of replicas to maintain, and will bring Pods up or down to reach that number.

An image showing the relation between containers, Pods, Deployments, Namespaces, and Nodes

Up until this point we've been creating Pods individually. But this is usually not what you'll want to do. Instead, you'll create a Deployment whose manifest also contains that of a Pod, and the Deployment will bring up instances of that Pod as necessary.

Before trying this out, use kubectl delete pods -n ecommerce --all to clear all Pods from the ecommerce namespace.

Then create a file called nginx-dep.yml and put in it the following manifest:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-dep
  namespace: ecommerce
spec:
  replicas: 3
  selector:
    matchLabels:
      depLabel: my-app-nginx
  template:
    metadata:
      name: nginx-pod
      labels:
        component: webserver
        depLabel: my-app-nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.17-alpine
        ports:
        - containerPort: 80

Some points of interest about this manifest:

  • The apiVersion is apps/v1. Until this point, this field has mostly had just v1, except for the Ingress, which had networking.k8s.io/v1. The value of this field signifies an API Group. Deployments are part of the "apps" API Group and Ingresses the "networking.k8s.io" group. All others used so far are part of the core API Group and so don't need their API Group specified.
  • The contents of the template section looks like a Pod definition, and that's what it is. These Pods will be created by the Deployment.
  • The count of replicas is 3. The Deployment will create and manage 3 Pods.

Use kubectl apply -f nginx-dep.yml. Then take a look at the status of the deployment with kubectl get deployment nginx-dep -n ecommerce, and have a look at the Pods it's created with kubectl get pods -n ecommerce.

$ kubectl get deployment nginx-dep -n ecommerce
NAME        READY   UP-TO-DATE   AVAILABLE   AGE
nginx-dep   3/3     3            3           31s
$ kubectl get pods -n ecommerce
NAME                        READY   STATUS    RESTARTS   AGE
nginx-dep-564bb8756-qxm7r   1/1     Running   0          44s
nginx-dep-564bb8756-62qkt   1/1     Running   0          44s
nginx-dep-564bb8756-69jlq   1/1     Running   0          44s

The Deployment has spawned its 3 Pods. These Pods are each given a name consisting of the Deployment's name plus a random string.

If you still have nginx-service running, you'll notice that the Deployment-created Pods can receive requests through it. That's because the Service's selector still matches the label given to the Pods.

Adding and removing replicas

Try the following: increase the number of replicas in the nginx-dep manifest to 4, and then run kubectl apply -f nginx-dep.yml && kubectl get pods -n ecommerce. You should see an output like the following:

$ kubectl apply -f nginx-dep.yml && kubectl get pods -n ecommerce
deployment.apps/nginx-dep configured
NAME                        READY   STATUS              RESTARTS   AGE
nginx-dep-564bb8756-qxm7r   1/1     Running             0          10m
nginx-dep-564bb8756-62qkt   1/1     Running             0          10m
nginx-dep-564bb8756-69jlq   1/1     Running             0          10m
nginx-dep-564bb8756-49gdw   0/1     ContainerCreating   0          0s

The cluster now knows that the number of replicas should be 4. It already has 3, so those remain, and it creates a fourth one. Now edit the nginx-dep manifest again, lowering the replica count to 2, and run kubectl apply -f nginx-dep.yml && kubectl get pods -n ecommerce again.

$ kubectl apply -f nginx-dep.yml && kubectl get pods -n ecommerce
deployment.apps/nginx-dep configured
NAME                        READY   STATUS        RESTARTS   AGE
nginx-dep-564bb8756-qxm7r   1/1     Running       0          14m
nginx-dep-564bb8756-62qkt   1/1     Running       0          14m
nginx-dep-564bb8756-69jlq   1/1     Terminating   0          14m
nginx-dep-564bb8756-49gdw   1/1     Terminating   0          4m6s

There are 4 Pods when there should now be 2, so the cluster picks 2 of them to terminate. Running kubectl get pods -n ecommerce shortly thereafter will show that the Pods have been removed.

Making changes to Pods in an active Deployment

If you make a change to the Pod's portion of a Deployment manifest and then apply it, the cluster will create new Pods and terminate old ones, with the end result being that the previous Pods are replaced. Change the image used in nginx-dep from nginx:1.17-alpine to nginx:1.16-alpine. Then apply it, and use kubectl get pods -n ecommerce to track what's happening.

$ kubectl apply -f nginx-dep.yml && kubectl get pods -n ecommerce
deployment.apps/nginx-dep configured
NAME                         READY   STATUS              RESTARTS   AGE
nginx-dep-db769cff9-dptmm    0/1     ContainerCreating   0          0s
nginx-dep-564bb8756-qxm7r    1/1     Running             0          22m
nginx-dep-564bb8756-62qkt    1/1     Running             0          22m
$ kubectl get pods -n ecommerce
NAME                         READY   STATUS        RESTARTS   AGE
nginx-dep-db769cff9-dptmm    1/1     Running       0          8s
nginx-dep-db769cff9-r47ds    1/1     Running       0          4s
nginx-dep-564bb8756-62qkt    0/1     Terminating   0          22m

It creates the new Pods and terminates the old ones. Two things to know about this process:

  1. By default, the cluster will make sure when updating a Deployment that some Pods remain running at all times. The specifics of this process are beyond the scope of this document, but the terms to search for if you want to understand more are "RollingUpdate strategy", "maxSurge", and "maxUnavailable".
  2. The replacement of Pods will happen if there's any change whatsoever to the Pod spec. This includes even seemingly superficial changes such as new labels.