Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

3.1 What Is a Pod, Really?

⏱️ 5 min read · 5 min hands-on · 🟢 Beginner

TL;DR: A Pod is NOT a container. It’s a wrapper around one or more containers that share the same network namespace and can share storage volumes. It’s the smallest deployable unit in Kubernetes.

After this section you will be able to:

  • Explain why Pods are the fundamental atomic unit of deployment in Kubernetes
  • Describe how co-located containers share network namespaces (localhost) and storage volumes
  • Author, deploy, and inspect a minimal Pod manifest from scratch

The Key Insight: Pods Are Not Containers

🔗 Docker Parallel: In Docker, you deploy containers. In Kubernetes, you deploy Pods. A Pod can contain one container (usually) or multiple tightly-coupled containers that need to share a network stack.

Here’s the minimal pod definition:

# my-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: my-nginx
  labels:
    app: nginx
spec:
  containers:
  - name: nginx
    image: nginx:1.25
    ports:
    - containerPort: 80
kubectl apply -f my-pod.yaml
kubectl get pod my-nginx

What Containers in a Pod Share

This is what makes pods special. Every container in a pod shares:

graph TB
    subgraph "Pod"
        NET[Shared Network Namespace<br/>Same IP address<br/>Same localhost]
        subgraph "Container A<br/>nginx"
            PA[:80]
        end
        subgraph "Container B<br/>log-shipper"
            PB[:9000]
        end
        VOL[Shared Volume<br/>/var/log]
        PA --- NET
        PB --- NET
        PA --- VOL
        PB --- VOL
    end
ResourceShared?Meaning
Network namespace✅ YesSame IP, can talk via localhost
Ports✅ YesPort conflicts between containers ARE possible
VolumesOptionalVolumes must be explicitly mounted by each container
Filesystem❌ NoEach container has its own isolated filesystem
Process namespaceOptionalCan share via shareProcessNamespace: true

⚠️ Warning: Because containers in a pod share a network namespace, two containers cannot both listen on port 80. Plan your container ports carefully in multi-container pods.


Why Not Just Run Containers Directly?

Valid question. The answer is: pods add a layer of abstraction that gives Kubernetes useful guarantees.

  1. Atomic scheduling — all containers in a pod land on the same node together
  2. Shared lifecycle — pod-level restart policies apply to all containers
  3. Co-location guarantee — sidecar and main container are always on the same machine, eliminating network latency between them

📝 Note: In practice, 90% of pods contain exactly one container. Multi-container pods are for specific patterns (sidecar, init) covered in section 3.3.


The Pod YAML Anatomy

apiVersion: v1           # API group version — always v1 for Pods
kind: Pod                # Resource type
metadata:
  name: my-app           # Unique name within a namespace
  namespace: default     # Namespace (defaults to "default")
  labels:                # Key-value pairs for selecting/grouping
    app: my-app
    version: "1.0"
  annotations:           # Non-identifying metadata (not used for selection)
    description: "Demo pod"
spec:
  containers:            # List of containers (at least one required)
  - name: app            # Container name (unique within the pod)
    image: nginx:1.25    # Image:tag — always pin the tag!
    ports:
    - containerPort: 80  # Informational only — doesn't actually publish the port
    env:                 # Environment variables
    - name: ENV
      value: production
    resources:           # CPU/memory limits (covered in 3.4)
      requests:
        memory: "64Mi"
        cpu: "100m"
      limits:
        memory: "128Mi"
        cpu: "200m"
  restartPolicy: Always  # Always | OnFailure | Never

⚠️ Warning: containerPort in a pod spec is purely informational — it doesn’t actually open a firewall port or publish the container. Networking is handled by Services (Chapter 5).


Try It

# Apply the pod
cat <<'EOF' | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: my-nginx
  labels:
    app: nginx
spec:
  containers:
  - name: nginx
    image: nginx:1.25
    ports:
    - containerPort: 80
EOF

# Watch it start
kubectl get pod my-nginx -w

# Once Running — get full details
kubectl describe pod my-nginx

# Access it directly (no Service needed for testing)
kubectl port-forward pod/my-nginx 8080:80 &
curl http://localhost:8080
kill %1

# Cleanup
kubectl delete pod my-nginx

Key Takeaways

#ConceptOne-liner
1Pod ≠ ContainerA pod wraps 1+ containers that share network and optionally storage
2Shared networkContainers in a pod use localhost to talk to each other
3containerPort is cosmeticIt doesn’t publish anything — Services do the actual networking
4Always pin image tagsnginx:latest in production is a reliability disaster

✅ Quick Check

Q1: You have two containers in a pod. Container A listens on port 8080. Can Container B also listen on port 8080?

Answer No. They share a network namespace, which means they share the same port space. If both try to bind port 8080, the second one will fail to start. Treat the port space of a pod as if it were a single machine.

Q2: Container A in a pod writes a file to /tmp/data. Can Container B read it?

Answer No — not without explicitly sharing a volume. Containers have isolated filesystems. To share files between containers in a pod, you must define a `volume` in the pod spec and mount it in both containers.

Q3: You delete a pod. Does Kubernetes immediately create a new one?

Answer Only if the pod is managed by a controller (Deployment, ReplicaSet, etc.). A bare pod — one you created directly with `kubectl apply -f pod.yaml` — is gone when deleted. This is why you almost never create bare pods in production; you always use a Deployment.