Skip to content

DevOps Day 49: From Pods to Deployments - My First Kubernetes Application

Today was a massive leap in my Kubernetes journey. I graduated from creating a simple, single Pod to using a Deployment, which I learned is the standard and professional way to run applications in Kubernetes. This task was about creating a Deployment to manage an httpd web server.

This was a huge conceptual shift. I learned that I don't manage containers directly; I manage Pods. And I don't even manage Pods directly; I manage a Deployment that manages the Pods for me. It's a layer of abstraction that provides incredible power, like self-healing and scaling. This document is my very detailed, first-person guide to that entire process, written from the perspective of a complete beginner to Kubernetes.

Table of Contents


The Task

My objective was to create a Kubernetes Deployment to run a web server. The specific requirements were: 1. The Deployment must be named httpd. 2. It must deploy Pods using the httpd:latest Docker image.


My Step-by-Step Solution

The professional way to create resources in Kubernetes is with a YAML manifest file. I followed this declarative approach.

Phase 1: Writing the Deployment Manifest

  1. I connected to the jump host, where kubectl was pre-configured to talk to the cluster.
  2. I created a new file named httpd-deployment.yaml using vi.
  3. Inside the editor, I wrote the following YAML code, which is a declaration of the Deployment I wanted to create.
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: httpd
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: httpd_app
      template:
        metadata:
          labels:
            app: httpd_app
        spec:
          containers:
          - name: httpd-container
            image: httpd:latest
    
  4. I saved and quit the file.

Phase 2: Applying the Manifest and Verifying

  1. I used kubectl to send my manifest to the Kubernetes API server.

    kubectl apply -f httpd-deployment.yaml
    
    The command responded with deployment.apps/httpd created, my first sign of success.

  2. Verification: The final and most important step was to confirm that the Deployment was created and that it, in turn, created a Pod.

    • First, I checked the status of the Deployment.
      kubectl get deployment httpd
      
      The output showed my httpd deployment with READY 1/1, confirming it had successfully created its Pod.
    • For definitive proof, I listed the Pods.
      kubectl get pods
      
      The output showed a new Pod with a name like httpd-6c7c8c88c7-abcde with a STATUS of Running. This Pod was created and is being managed by my Deployment. This was the final proof of success.

Why Did I Do This? (The "What & Why" for a K8s Beginner)

- Kubernetes (K8s): Kubernetes is the "operating system for the cloud." It's an orchestrator that manages containerized applications across a fleet of servers (a "cluster"). - Pod vs. Deployment (The Core Lesson): This was the most important concept I learned. - A Pod is the smallest unit in Kubernetes. It's a wrapper for my container. A Pod is mortal. If it crashes or the server it's on fails, the Pod is gone. - A Deployment is a manager for Pods. It's a higher-level object that acts as a controller. My YAML file told the Deployment, "I desire to have 1 Pod running that looks like this." The Deployment's job is to work tirelessly to make that happen. If the Pod it creates dies, the Deployment's controller will notice and automatically create a new one. This is called self-healing, and it's one of the most powerful features of Kubernetes. - ReplicaSet: I learned that a Deployment doesn't manage Pods directly. When I create a Deployment, it creates another object called a ReplicaSet. The ReplicaSet's only job is to ensure that a specified number of replica Pods are always running. The Deployment then manages the ReplicaSet, which allows for advanced strategies like rolling updates. So the hierarchy is: Deployment -> ReplicaSet -> Pod -> Container. - Declarative Manifests (YAML): I am not telling Kubernetes how to create the Pod. I am writing a YAML file that describes the desired end state of my system. I give this "blueprint" to Kubernetes, and it's the cluster's job to figure out how to make reality match my blueprint. This is a powerful, version-controllable, and repeatable way to manage infrastructure.


Deep Dive: A Line-by-Line Explanation of My Deployment YAML File

The YAML file for a Deployment is more complex than for a Pod because it defines both the manager (the Deployment) and the blueprint for what it manages (the Pod template).

[Image of a Kubernetes Deployment managing multiple Pods]

# 'apiVersion' tells Kubernetes which API to use. 'apps/v1' is the modern,
# stable API group for workload resources like Deployments.
apiVersion: apps/v1

# 'kind' specifies the TYPE of object I want to create.
kind: Deployment

# 'metadata' contains data that identifies the Deployment object itself.
metadata:
  name: httpd

# 'spec' (Specification) describes the DESIRED STATE of the Deployment.
spec:
  # 'replicas' is the number of identical Pods I want to run. This is the key
  # to scalability. I can change this to 3, and the Deployment will automatically
  # create two more Pods.
  replicas: 1

  # 'selector' is CRITICAL. It tells the Deployment's controller HOW to find the
  # Pods that it is supposed to be managing.
  selector:
    # 'matchLabels' is a rule. It says, "Any Pod with the label 'app: httpd_app'
    # belongs to me." This link is essential.
    matchLabels:
      app: httpd_app

  # 'template' is the blueprint for the Pods that the Deployment will create.
  # This section looks almost exactly like a standalone Pod manifest.
  template:
    # The Pods created by this template will have their own metadata.
    metadata:
      # The labels here MUST match the 'matchLabels' in the selector above.
      # This is how the Pods get "adopted" by the Deployment.
      labels:
        app: httpd_app

    # This is the specification for the Pods themselves.
    spec:
      # It describes the containers that will run inside the Pods.
      containers:
      - name: httpd-container
        image: httpd:latest

Common Pitfalls for Beginners

- YAML Indentation Errors: YAML is extremely strict about indentation. A single wrong space can make the file invalid. - Selector/Label Mismatch: This is the most common and frustrating error for beginners. If the spec.selector.matchLabels of the Deployment do not exactly match the spec.template.metadata.labels of the Pod template, the Deployment will create the Pods, but it won't be able to "find" them. The Deployment will get stuck in a loop, endlessly creating new Pods because it thinks its desired replica count is zero. - Trying to name the Pod: The Deployment automatically generates names for the Pods it creates (e.g., httpd-<random-string>). You define the Pod's blueprint in the template, but not its specific name.


Exploring the Essential kubectl Commands

This task introduced me to a new set of commands for managing Deployments.

  • Creating & Updating:

    • kubectl apply -f [filename.yaml]: The standard way to create or update resources from a manifest file.
  • Viewing & Inspecting:

    • kubectl get pods: Lists a summary of all Pods.
    • kubectl get deployments (or kubectl get deploy): Lists a summary of all Deployments. The output is great for quickly checking the READY status.
    • kubectl get all: Shows a summary of all the most common resource types (Pods, Deployments, ReplicaSets, Services, etc.).
    • kubectl describe deployment [dep-name]: Describes a Deployment in detail, including its labels, replica count, and recent events. This is great for troubleshooting the Deployment itself.
    • kubectl describe pod [pod-name]: Describes a specific Pod in detail. This is essential for troubleshooting a Pod that is crashing or won't start.
  • Scaling (The Cool Part!):

    • kubectl scale deployment httpd --replicas=3: This is an imperative command that tells Kubernetes to scale my httpd Deployment to 3 replicas. The Deployment controller will see this change and immediately create 2 new Pods to match the new desired state.
  • Deleting:

    • kubectl delete deployment httpd: Deletes the Deployment. Because the Deployment is the "owner" of the ReplicaSet and the Pods, deleting the Deployment will trigger a cascade delete, and the ReplicaSet and all its Pods will also be automatically removed.