Pods
Kubernetes does not schedule containers. It schedules Pods, and a Pod is one or more containers that are guaranteed to land on the same node and share a network namespace.
That guarantee is the entire reason Pods exist. Two containers in a Pod reach each other over localhost, share an IP address and a hostname, and can share volumes — which is exactly what a sidecar, a log shipper or a proxy needs. Containers in different Pods can make no such assumption.
Reference
- https://kubernetes.io/docs/concepts/workloads/pods/
- https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/
Terminology
- Pod — The smallest deployable unit: a group of containers with shared network and storage, scheduled together on one node.
- Sandbox (pause) container — Every Pod has one, and it does nothing but hold the network namespace open. The containers you care about join it. This is why a Pod keeps its IP even when all its application containers restart.
- Init container — Runs to completion, in order, before the main containers start. Used for setup that must finish first: waiting for a dependency, cloning a repository, fixing file ownership on a volume.
- Sidecar — A container that runs alongside the main one for the Pod’s whole lifetime. Log shippers, service-mesh proxies and config reloaders are sidecars.
- restartPolicy —
Always(the default, for long-running workloads),OnFailure, orNever. It applies to the whole Pod, and it is what distinguishes a Deployment from a Job. - Static Pod — A Pod managed directly by the kubelet from a file on the node rather than by the API server. The control plane’s own components are static Pods, which is worth knowing on Day 5.
The Shape of a Pod
apiVersion: v1
kind: Pod
metadata:
name: web
labels:
app: web
spec:
restartPolicy: Always
containers:
- name: web
image: docker.io/library/nginx:1.27
ports:
- containerPort: 80
volumeMounts:
- name: shared
mountPath: /usr/share/nginx/html
volumes:
- name: shared
emptyDir: {}Note what is not there: no replicas, no update strategy, no rollout. A bare Pod is a single, unmanaged thing. If its node dies, nobody replaces it.
The Lifecycle
| Phase | Means |
|---|---|
Pending | Accepted, but not yet running — usually scheduling, or pulling an image |
Running | At least one container is running |
Succeeded | Every container exited 0, and the Pod will not restart |
Failed | A container exited non-zero and the restart policy gave up |
Phases are coarse. When you need detail, look at the container states instead:
kubectl get pod web -o jsonpath='{.status.containerStatuses[*].state}{"\n"}'Waiting with reason ImagePullBackOff or CrashLoopBackOff is where most beginners’ problems live, and the reason string tells you which.
Exercises
Create a Pod and inspect it:
kubectl run web --image=docker.io/library/nginx:1.27 --port=80 kubectl get pod web -o wide kubectl get pod web -o jsonpath='{.status.podIP}{"\n"}'Two containers, one network namespace. Write a Pod with a
webcontainer and asidecarcontainer, both fromdocker.io/library/busybox, with the sidecar runningsleep 3600:kubectl exec -it web -c sidecar -- shFrom inside the sidecar,
wget -qO- localhost:80reaches the web container onlocalhost. Now checkhostname— both containers report the same one.Init containers run first, and run again on every Pod start. Add one that writes a file into a shared
emptyDirand have the main container read it:initContainers: - name: setup image: docker.io/library/busybox command: ["sh", "-c", "echo prepared > /work/state.txt"] volumeMounts: - name: work mountPath: /workIf the init container fails, the Pod restarts it and the main containers never start. That is the point: it is a gate.
Delete the Pod and watch it not come back. Then compare with a Deployment in the next module, where it does.
What to Take Away
- A Pod is a co-scheduling guarantee, not a container wrapper. That is why it exists.
- Containers in a Pod share an IP, a hostname and
localhost; containers in different Pods do not. - A bare Pod is unmanaged — nothing recreates it. Real workloads are owned by a Deployment, StatefulSet, DaemonSet or Job.
- When something is wrong, the container state and the events tell you more than the phase does.