Skip to content

Now that we understand that our application container lives inside a Pod, we need a way to manage that Pod reliably.

Managing Your Application with Deployments

Section titled “Managing Your Application with Deployments”

In the last chapter, we established that Pods are ephemeral. If a Node fails or a Pod crashes, it’s gone. Relying on a single Pod to run your application is like building a house on sand. This raises several important questions:

  • What happens if the Pod running my application crashes? Does my app go down?
  • How do I scale my application to handle more traffic? Do I have to create each new Pod manually?
  • How do I update my application to a new version without causing downtime for my users?

The answer to all these questions is the Deployment object.

A Deployment is a higher-level Kubernetes object that manages a set of identical Pods. Its primary job is to ensure that a specified number of Pods are running at all times and to manage how updates are rolled out to them.

You don’t create Pods manually; you declare your desired state in a Deployment object, and the Deployment takes care of the rest. This is a core principle of Kubernetes: you tell the cluster what you want (e.g., “I want 3 replicas of my web server running version 1.2”), and Kubernetes figures out how to make it happen.

How Deployments Work: The Role of the ReplicaSet

Section titled “How Deployments Work: The Role of the ReplicaSet”

A Deployment doesn’t directly manage Pods. Instead, it uses another object called a ReplicaSet.

  1. You create a Deployment.
  2. The Deployment creates a ReplicaSet.
  3. The ReplicaSet’s job is to create and maintain the specified number of Pods. If a Pod dies, the ReplicaSet immediately creates a new one to replace it.

This division of labor is especially important for updates. When you update your application (e.g., change the container image), the Deployment creates a new ReplicaSet for the new version and slowly scales it up while scaling the old ReplicaSet down. This is called a rolling update, and it’s how Kubernetes achieves zero-downtime deployments.

Here is a diagram showing this relationship:

+--------------------------------------------+
| Deployment |
| (Your Desired State: |
| "3 replicas of my-app:v1") |
+--------------------+-----------------------+
|
| Manages
|
+--------------------v-----------------------+
| ReplicaSet |
| (Ensures 3 Pods Exist) |
+--+-----------------+-----------------+-----+
| | |
| Creates & | Creates & | Creates &
| Monitors | Monitors | Monitors
| | |
+--v--+ +--v--+ +--v--+
| Pod | | Pod | | Pod |
+-----+ +-----+ +-----+
  • Scalability: Need to handle more traffic? You simply update the replicas field in your Deployment from 3 to 10. The ReplicaSet will see this change and create 7 new Pods.
  • Self-Healing: If a Node hosting one of your Pods goes down, the Kubernetes Control Plane detects this. The ReplicaSet sees that it’s now short of its desired replica count and automatically creates a replacement Pod on a healthy Node. You don’t have to do anything.
  • Controlled Rollouts and Rollbacks: As mentioned, Deployments allow for seamless rolling updates. If you find a bug in your new version, you can just as easily tell the Deployment to “roll back” to the previous, stable version.

In Kubernetes, you define objects using YAML files. Here is a simplified example of what a Deployment file looks like:

# apiVersion: Specifies the Kubernetes API version to use
apiVersion: apps/v1
# kind: Specifies the type of object
kind: Deployment
# metadata: Data that helps uniquely identify the object, like its name
metadata:
name: my-webapp-deployment
# spec: This is where you define the DESIRED STATE
spec:
# replicas: How many identical Pods to run
replicas: 3
# selector: How the Deployment finds which Pods to manage
selector:
matchLabels:
app: my-webapp
# template: This is the blueprint for the Pods it will create
template:
metadata:
labels:
app: my-webapp # This label must match the selector above
spec:
containers:
- name: webserver-container
# image: The Docker container image to run
image: nginx:1.21.6
ports:
- containerPort: 80

Don’t worry about memorizing this format. The key fields to understand are:

  • replicas: We are asking for 3 Pods.
  • selector: This tells the Deployment how to identify the Pods it is supposed to manage (in this case, any Pod with the label app: my-webapp).
  • template.spec.containers.image: This specifies the container image that will be placed inside each Pod. This is where you would put your own application’s image (e.g., your-username/your-cool-app:1.0).


  1. Create a Deployment: Create a file named deployment.yaml with the content from the chapter example:

    deployment.yaml
    apiVersion: apps/v1
    kind: Deployment
    metadata:
    name: my-webapp-deployment
    spec:
    replicas: 3
    selector:
    matchLabels:
    app: my-webapp
    template:
    metadata:
    labels:
    app: my-webapp
    spec:
    containers:
    - name: webserver-container
    image: nginx:1.21.6
    ports:
    - containerPort: 80

    Apply it to your cluster:

    Terminal window
    kubectl apply -f deployment.yaml
  2. Check the Status: Now, check all the objects that were created.

    Terminal window
    # Check the deployment itself
    kubectl get deployment
    # See the ReplicaSet it created
    kubectl get replicaset
    # You can also use 'rs' as a shorthand for 'replicaset'
    # See the 3 Pods that the ReplicaSet created
    kubectl get pods

    You should see one Deployment, one ReplicaSet, and three Pods running.

  3. Test Self-Healing: Let’s manually delete one of the Pods to simulate a failure. Pick one of the Pod names from the get pods command.

    Terminal window
    # Replace <pod-name> with one of your actual pod names
    kubectl delete pod <pod-name>

    Now, very quickly, run kubectl get pods --watch. You will see that the Pod you deleted is “Terminating”, but the ReplicaSet immediately created a new one to bring the count back to 3! This is the self-healing power of a Deployment.

  4. Test Scaling: Let’s scale our application up to 5 replicas.

    Terminal window
    kubectl scale deployment my-webapp-deployment --replicas=5

    Check your Pods again (kubectl get pods), and you’ll see that two new Pods have been created, for a total of 5.

  5. Perform a Rolling Update: Let’s say you want to update your application to a new version.
    You can do this by changing the image in your Deployment.Now let’s update our Nginx version with zero downtime. We can do this directly from the command line.

    Terminal window
    # This tells the deployment to use a new image for the container
    kubectl set image deployment/my-webapp-deployment webserver-container=nginx:1.23.3

    To watch the rolling update happen in real-time, use the rollout status command:

    Terminal window
    kubectl rollout status deployment/my-webapp-deployment

    If you run kubectl get pods in another terminal while this is happening, you’ll see the Deployment terminating old Pods and creating new ones gracefully.

  6. Clean Up: To delete the entire application (the Deployment, ReplicaSet, and all Pods), just delete the Deployment object.

    Terminal window
    kubectl delete -f deployment.yaml

You are now ready for the next step. We have a robust, scalable application running. But it’s still locked inside the cluster.

Let me know when you’re ready for Chapter 3, where we will finally expose this application to the outside world using Services and Ingress.

  • You don’t manage individual Pods; you use a Deployment to manage them.
  • A Deployment ensures a specified number of Pods (replicas) are running and healthy.
  • Deployments use ReplicaSets to achieve this self-healing and scalability.
  • Deployments allow for zero-downtime rolling updates when you need to change your application’s version.
  • You define the desired state of your Deployment in a YAML file.

Now we have a way to run our application reliably and keep it running. But how do users access it? The Pods are running deep inside the cluster network. Let me know when you’re ready, and in Chapter 3, we’ll cover how to expose your application to the outside world using Services and Ingress.