Pods: The Atom of Kubernetes
Kubernetes doesn't run containers directly — it runs pods. This surprises newcomers: why wrap a container in another abstraction? Because the pod solves a real problem — some containers genuinely need to run together, sharing network and storage — and making the pod (not the container) the unit of scheduling is what makes the rest of Kubernetes coherent.
The last post explained containers; this post covers the smallest thing Kubernetes actually manages: the pod. A pod is one or more containers that run together — sharing network and storage — as a single unit. Kubernetes schedules, scales, and manages pods, not individual containers, and understanding why is key to understanding Kubernetes. This post covers what a pod is, why it exists, the sidecar pattern, and the pod lifecycle.
What a pod is
A pod is the smallest deployable unit in Kubernetes: one or more containers that are always scheduled together on the same node and share certain resources. The key facts:
- A pod usually holds one container — the common case is one app container per pod. So most of the time, “pod” ≈ “a running instance of your container.”
- But a pod can hold multiple containers that need to run together (the sidecar pattern, below).
- Containers in a pod share a network namespace — they share the same IP address and can talk to each other over
localhost. To the outside, the pod has one IP. - Containers in a pod can share storage — they can mount the same volumes, sharing files.
- A pod is scheduled as a unit — all its containers run on the same node, together, and are created and destroyed together.
So a pod is a wrapper that groups tightly-coupled containers into one co-located, co-scheduled unit with a shared network and storage. Kubernetes then manages pods as the atomic unit — it schedules pods onto nodes, scales by adding/removing pods, and reconciles the number of pods (from the desired-state model). The container is what runs your code; the pod is what Kubernetes manages.
Why not just containers?
The natural question: why add the pod abstraction instead of managing containers directly? Because some containers genuinely need to run together, sharing an environment, and a single-container-only model couldn’t express that. The pod exists so Kubernetes can schedule co-located, co-operating containers as one unit:
- Shared network — sometimes a helper container needs to communicate with the main container over localhost as if they were on the same host (they are — same pod, same network namespace). A pod makes that possible.
- Shared storage — sometimes a helper needs to read/write the same files as the main container (e.g. a log-shipper reading the app’s logs). A shared volume in the pod enables that.
- Shared lifecycle — sometimes helpers must live and die with the main container, on the same node. The pod guarantees co-scheduling and co-lifecycle.
If Kubernetes managed only individual containers, you couldn’t guarantee two related containers land on the same node, share a network/storage, and live together. The pod is the abstraction that provides “these containers are a unit.” Most pods have one container (you don’t need the grouping), but when you do need tightly-coupled containers together, the pod is the mechanism — and making the pod (not the container) the universal unit of scheduling keeps Kubernetes’s model uniform (everything schedules pods, whether they hold one container or several).
The sidecar pattern
The main reason a pod holds multiple containers is the sidecar pattern — running a helper container alongside the main application container in the same pod, to augment or support it:
Pod
├── app container (your application)
└── sidecar container (a helper: log shipping / proxy / config sync)
→ share network (localhost) and storage (volumes), scheduled together
Common sidecars:
- Log/metrics shippers — a sidecar reads the app’s logs (via a shared volume) and ships them to a logging system, so the app doesn’t need to know about the logging backend.
- Proxies — a sidecar proxy handles the app’s network traffic (this is how a service mesh works: a proxy sidecar in every pod manages networking, security, and observability transparently).
- Config/secret sync — a sidecar fetches and refreshes configuration or secrets for the app.
- Adapters — a sidecar translates between the app’s interface and what the rest of the system expects.
The sidecar pattern is powerful because it lets you add capabilities to a pod without changing the app — the app focuses on its job, and sidecars handle cross-cutting concerns (logging, networking, security) alongside it, sharing the pod’s network and storage. This is a big part of why pods allow multiple containers: it enables composing an application with helpers as a co-located unit. (Kubernetes also has init containers — containers that run to completion before the main container starts, for setup tasks — another use of multiple containers in a pod.)
The pod lifecycle and ephemerality
A crucial property to internalize: pods are ephemeral. They are created, they run, and they are destroyed — and Kubernetes creates new pods rather than resurrecting old ones. This shapes how you think about everything:
- Pods have a lifecycle — Pending (scheduled, waiting to start), Running, then Succeeded/Failed (terminated). Kubernetes reports pod status and uses probes (liveness/readiness) to know if a pod’s containers are healthy and ready for traffic.
- Pods are cattle, not pets — you don’t fix a sick pod; Kubernetes replaces it. If a pod’s node dies or the pod fails, Kubernetes (via controllers, the next post) creates a new pod elsewhere — a different pod, with a different IP. Pods come and go constantly.
- Pods are (usually) not created directly — you rarely create a bare pod yourself. Instead you declare a higher-level object (a Deployment, next post) that manages pods for you — creating, replacing, and scaling them per your desired state. Bare pods aren’t self-healing; the controllers that manage them provide that.
The ephemerality has big consequences that later posts address:
- Pods get new IPs when recreated, so you can’t rely on a pod’s IP — which is why Services (a later post) exist: to provide a stable address in front of ever-changing pods.
- Pods lose their local state when destroyed, so persistent data must live in volumes outside the pod (a later post) — the pod itself is disposable.
So the mental model: a pod is Kubernetes’s atomic, ephemeral unit — one-or-more co-located containers sharing network/storage, created and destroyed freely, managed by higher-level controllers, and treated as replaceable cattle. This ephemerality is fundamental to how Kubernetes self-heals and scales (just make more/fewer pods), and it’s why the concepts that follow — controllers (managing pods), services (stable addressing over changing pods), and volumes (state outside disposable pods) — exist. The next post covers what actually manages pods to achieve the desired state: controllers and the reconciliation loop.
Key takeaways
- A pod is Kubernetes’s smallest deployable unit: one or more containers scheduled together on the same node, sharing a network namespace (same IP, localhost communication) and able to share storage (volumes) — and Kubernetes manages pods, not individual containers.
- Most pods hold one container (pod ≈ a running instance of your app), but a pod can hold several that must run together — the pod exists so tightly-coupled containers can be co-located, co-scheduled, and share network/storage/lifecycle, which a container-only model couldn’t guarantee.
- The sidecar pattern (a helper container alongside the app in the same pod — log shipper, proxy/service-mesh, config sync, adapter) adds capabilities to a pod without changing the app, sharing the pod’s network and storage; init containers run setup to completion before the main container.
- Pods are ephemeral (cattle, not pets): created, run, destroyed, and replaced (not resurrected) with new pods that get new IPs — Kubernetes replaces sick pods rather than fixing them, and you usually don’t create bare pods but declare higher-level objects (Deployments) that manage them.
- Ephemerality is fundamental and drives the rest of Kubernetes: pods getting new IPs is why Services (stable addressing) exist, and pods losing local state is why Volumes (external persistence) exist — the pod is the disposable atom that self-healing and scaling operate on.
Further reading
- Containers from first principles (previous post)
- Kubernetes documentation — pods
- Distributed Systems — cattle-not-pets and designing for failure