Updated on 2025-07-29 GMT+08:00

Deployments

Overview of Deployments

A pod is the smallest unit that you create or deploy in Kubernetes. It is evicted when resources are tight and gone if its node fails. Kubernetes provides controllers to manage pods. These controllers create and manage pods, providing features like replica management, rolling upgrades, and self-healing. The most common controller is Deployment.

Figure 1 Relationship between a Deployment and pods

A Deployment runs one or more identical pods. Kubernetes load-balances traffic across them.

A Deployment handles rollout, rolling upgrades, scaling, and automatic replacement of failed pods. This enables zero-touch releases with minimal risk.

Creating a Deployment

In the following example, a Deployment named nginx launches two pods from nginx:latest, each reserving 100 mCPU and 200 MiB of memory.

apiVersion: apps/v1      # Use apps/v1 for Deployments. The setting is different from v1 for pods.
kind: Deployment         # The resource type is Deployment.
metadata:
  name: nginx            # The name of the Deployment
spec:
  replicas: 2            # The desired pod count. It indicates that there should be two running pods.
  selector:              # The label selector
    matchLabels:
      app: nginx
  template:              # The pod template. It defines the pods to be created.
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx:latest
        name: container-0
        resources:
          limits:
            cpu: 100m
            memory: 200Mi
          requests:
            cpu: 100m
            memory: 200Mi
      imagePullSecrets:
      - name: default-secret

In this example, the Deployment is named nginx. spec.replicas specifies the number of pods that the Deployment maintains (two in this example). spec.selector is a label selector that identifies pods with the label app=nginx. spec.template defines the pod specifications, which are identical to those defined in Pods.

Save the definition of the Deployment to deployment.yaml and use kubectl to create the Deployment.

Run kubectl get to view the Deployment and its pods. The command output shows that the READY value is 2/2. The first 2 indicates that two pods are running, while the second 2 indicates that the desired number of pods for this Deployment is two. The AVAILABLE value of 2 indicates that two pods are available.

$ kubectl create -f deployment.yaml
deployment.apps/nginx created

$ kubectl get deploy
NAME           READY     UP-TO-DATE   AVAILABLE   AGE
nginx          2/2       2            2           4m5s

How Does a Deployment Control Pods?

Obtain pods, shown as below:

$ kubectl get pods
NAME                     READY     STATUS    RESTARTS   AGE
nginx-7f98958cdf-tdmqk   1/1       Running   0          13s
nginx-7f98958cdf-txckx   1/1       Running   0          13s

A Deployment ensures that a specified number of pods are running at any given time. If you delete a pod, the Deployment will immediately create a new one to maintain the desired state of two running pods. Similarly, if a pod fails, the Deployment will restart it to ensure the desired number of pods is always met.

$ kubectl delete pod nginx-7f98958cdf-txckx

$ kubectl get pods
NAME                     READY     STATUS    RESTARTS   AGE
nginx-7f98958cdf-tdmqk   1/1       Running   0          21s
nginx-7f98958cdf-tesqr   1/1       Running   0          1s

In the example provided, the two pods are named nginx-7f98958cdf-tdmqk and nginx-7f98958cdf-tesqr. In the two names, nginx is the name of the Deployment, while -7f98958cdf-tdmqk and -7f98958cdf-tesqr are suffixes randomly generated by Kubernetes.

You may notice that the two suffixes share the same content 7f98958cdf. This is because the Deployment does not directly control the pods. Instead, it manages them through a controller called a ReplicaSet. You can obtain the ReplicaSet using the following command (where rs is the abbreviation for ReplicaSet):

$ kubectl get rs
NAME               DESIRED   CURRENT   READY     AGE
nginx-7f98958cdf   2         2         2         1m

The ReplicaSet is named nginx-7f98958cdf, where the suffix -7f98958cdf is randomly generated by Kubernetes.

Figure 2 shows how a Deployment controls pods via a ReplicaSet.

Figure 2 How does a Deployment control pods

When you run kubectl describe to view the details of a Deployment, you will see information about the ReplicaSet it controls, for example, NewReplicaSet: nginx-7f98958cdf (2/2 replicas created). In Events, you will see that the number of pods in the ReplicaSet is scaled out to 2. In practice, you typically do not interact with ReplicaSets directly. However, understanding that a Deployment controls pods by managing a ReplicaSet helps you troubleshoot issues more effectively.

$ kubectl describe deploy nginx
Name:                   nginx
Namespace:              default
CreationTimestamp:      Sun, 16 Dec 2018 19:21:58 +0800
Labels:                 app=nginx

...

NewReplicaSet:   nginx-7f98958cdf (2/2 replicas created)
Events:
  Type    Reason             Age   From                   Message
  ----    ------             ----  ----                   -------
  Normal  ScalingReplicaSet  5m    deployment-controller  Scaled up replica set nginx-7f98958cdf to 2

Upgrade

In real-world applications, upgrades are a common occurrence, and Deployments make application upgrades seamless and straightforward.

Available upgrade policies for Deployments:

  • RollingUpdate: New pods are created gradually, and old pods are deleted one by one. This is the default policy.
  • Recreate: All current pods are deleted first, and then new pods are created.

Deployments are upgraded in a declarative manner. You simply need to modify the YAML definition of the target Deployment. For example, you can run kubectl edit to change the image used by the sample Deployment to nginx:alpine. After making the modification, you can check the ReplicaSet and pods. The query result shows that a new ReplicaSet has been created, and the pods have been re-created to reflect the updated image.

$ kubectl edit deploy nginx

$ kubectl get rs
NAME               DESIRED   CURRENT   READY     AGE
nginx-6f9f58dffd   2         2         2         1m
nginx-7f98958cdf   0         0         0         48m

$ kubectl get pods
NAME                     READY     STATUS    RESTARTS   AGE
nginx-6f9f58dffd-tdmqk   1/1       Running   0          1m
nginx-6f9f58dffd-tesqr   1/1       Running   0          1m

Each Deployment can control the proportion of pods to be recreated during an upgrade using the maxSurge and maxUnavailable parameters. This method is useful in a wide range of scenarios. The configuration is as follows:

spec:
  strategy:
    rollingUpdate:
      maxSurge: 0.25
      maxUnavailable: 0.25
    type: RollingUpdate
  • maxSurge specifies the maximum number or percentage of pods that can exist above the desired number of pods (spec.replicas) during a rolling upgrade. This parameter determines the maximum number of new pods that can be created at a time to replace old pods. The default value is 25%. During an upgrade, the percentage is converted into an absolute number and rounded up.

    For example, if spec.replicas is set to 2, a maximum of one pod (2 x 0.25 = 0.5, rounded up to 1) can be created at a time by default. Therefore, during an upgrade, up to 3 pods can exist (2 desired + 1 surge).

  • maxUnavailable specifies the maximum number or percentage of pods that can be unavailable during a rolling upgrade. This also sets the limit for how many running pods can be below the expected number. The default value is 25%. During an upgrade, the percentage is converted into an absolute number and rounded down.

    For example, if spec.replicas is set to 2, no pods (2 x 0.25 = 0.5, rounded down to 0) can be unavailable. Therefore, during an upgrade, there will always be at least two pods running (2 desired - 0 unavailable). Each old pod is deleted only after a new one is created, ensuring that at least two pods are always running until all pods are updated.

Rollback

Rollback is the process of reverting an application to an earlier version if a fault occurs during an upgrade. Applications managed by Deployments can be easily rolled back to a previous version.

For example, if the image of an upgraded Deployment is faulty, you can run kubectl rollout undo to roll back the Deployment.

$ kubectl rollout undo deployment nginx
deployment.apps/nginx rolled back

A Deployment can be easily rolled back because it uses a ReplicaSet to control pods. After an upgrade, the previous ReplicaSet is retained. The Deployment is rolled back by using the previous ReplicaSet to recreate the pods. The maximum number of ReplicaSets stored in a Deployment can be controlled by the revisionHistoryLimit parameter. The default value is 10.