Kubernetes Pods Explained: Lifecycle, Types, Syntax & Hands-on Examples

Introduction

In Kubernetes, everything revolves around Pods. They are the smallest deployable unit in Kubernetes, acting as a wrapper for one or more containers. Understanding Pods is the first step toward mastering Kubernetes deployments.
In this article, we will cover:

  • What is a Pod?

  • Pod lifecycle (with diagrams)

  • Types of Pods

  • Pod YAML syntax

  • Creating a sample Pod (nginx)

  • Resource quotas for namespaces


1. What is a Pod?

A Pod is the smallest and simplest unit in the Kubernetes object model. It represents a single instance of a running process in your cluster and can host one or more containers.

  • If multiple containers are in the same Pod, they share the same network namespace and storage volumes.

  • Pods are ephemeral — once deleted, they cannot be restarted (instead, they’re recreated).


Example Use Cases

  • Hosting a single container app (like nginx)

  • Running multiple tightly coupled containers (like an app + log collector)


2. Pod Lifecycle (Step-by-Step)

Kubernetes Pod Lifecycle – Proper Flow

Step-by-Step Process

1. User Creates Pod Definition File

User writes a YAML file (e.g., demo.yaml) describing the pod specifications (containers, images, resources, etc.).

2. kubectl Sends Request to API Server

Command:

kubectl apply -f demo.yaml

This sends the pod specification to the Kubernetes API Server (part of the Control Plane) using a REST API call.

3. API Server Stores Configuration in etcd

The API Server validates the pod definition and stores its desired state in etcd (the cluster’s key-value database).

4. Scheduler Assigns Pod to a Node

The Kube-Scheduler watches for unscheduled pods.

It evaluates available nodes based on resources, affinity rules, taints/tolerations, and assigns the pod to the most suitable node.

5. Kubelet on Target Node Takes Over

The Kubelet on the assigned worker node notices a new pod scheduled for it.

It pulls the required container image from the registry.

6. Container Runtime Starts the Container

The Kubelet uses the Container Runtime Interface (CRI) (e.g., containerd, CRI-O, Docker) to start the pod’s container(s).

7. Pod Running & Status Updated

Once running, pod status is reported back to the API Server.

etcd stores the latest status, so kubectl get pods shows the pod’s live state.

Pod Lifecycle States

When you create a Pod, Kubernetes moves it through several phases:

PhaseDescription
PendingPod has been accepted but containers not yet created.
ContainerCreatingImages are being pulled and containers are starting.
RunningAll containers are up and running.
SucceededAll containers have exited successfully.
FailedContainers have terminated with an error.
UnknownPod state cannot be determined.

Pod Lifecycle Diagram

Pending → ContainerCreating → Running → (Succeeded / Failed)
                 ↓
              Unknown

3. Types of Pods

  1. Single-Container Pod

    • One container per Pod.

    • Example: nginx web server.

    • Use case: Simple microservice deployments.

  2. Multi-Container Pod

    • Multiple containers share resources in the same Pod.

    • Example: nginx + fluentd logging container.

    • Use case: Sidecar pattern, tightly coupled services.


Multi-Container Pod Diagram

pgsqlCopyEdit+--------------------- POD ---------------------+
| nginx container  | fluentd container          |
| Port: 80          | Port: 24224               |
+-----------------------------------------------+
| Shared Network Namespace & Storage Volumes    |
+-----------------------------------------------+

4. Pod YAML Syntax

A basic Pod YAML file structure:

apiVersion: v1
kind: Pod
metadata:
  name: <pod-name>
  namespace: <namespace-name>
spec:
  containers:
    - name: <container-name>
      image: <image-name:tag>
      ports:
        - containerPort: <port-number>

5. Creating a Sample Nginx Pod

File: vi nginx.yaml

apiVersion: v1
kind: Pod
metadata:
  name: nginxpod
  namespace: dev
spec:
  containers:
    - name: nginxcon
      image: nginx:1.14.2
      ports:
        - containerPort: 80

1. Execution Steps Dry run (client-side validation)

kubectl apply -f nginx.yaml --dry-run=client

Checks YAML syntax without contacting the API server.

2. Dry run (server-side validation)

kubectl apply -f nginx.yaml --dry-run=server

Validates on the API server without persisting.

  1. Create the Pod
kubectl apply -f nginx.yaml
  1. Check if the Pod is created

kubectl get po -n dev
  1. Describe the namespace

    Kubernetes will show detailed information about the dev namespace.
    The output typically includes:

kubectl describe ns dev

Explanation of Key Sections

  1. Name → Name of the namespace (dev).

  2. Labels → Key-value pairs for categorization.

  3. Annotations → Extra metadata (optional).

  4. Status → Usually Active, but can also be Terminating.

  5. Resource Quotas → Shows quota configurations (like CPU, memory, pods) and current usage.

  6. LimitRange → Default CPU/Memory limits for pods in this namespace (if set).

6. Creating a Resource Quota for a Namespace

A ResourceQuota limits the amount of compute resources (CPU, Memory, Pods) a namespace can consume.

File: quota.yaml

yamlCopyEditapiVersion: v1
kind: ResourceQuota
metadata:
  name: my-resource-quota
  namespace: dev
spec:
  hard:
    pods: "5"
    requests.cpu: "2"
    requests.memory: 4Gi
    limits.cpu: "4"
    limits.memory: 8Gi

Apply Quota:

kubectl apply -f quota.yaml

Verify Quota:

kubectl describe quota my-resource-quota -n dev

Conclusion

In Kubernetes, Pods are the foundation for running applications. By understanding lifecycle, types, and syntax, you can confidently deploy and manage workloads. Adding ResourceQuotas ensures fair usage of resources in shared clusters.

1
Subscribe to my newsletter

Read articles from Sandeep Lagishetti directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Sandeep Lagishetti
Sandeep Lagishetti