Pods
Pods
The smallest schedulable unit. Not a container - an environment for one or more containers.
graph TB
subgraph pod [Pod - one IP, one network namespace]
C1[container: app]
C2[container: sidecar]
V[(shared volume)]
C1 --- V
C2 --- V
end
Containers in a Pod share the IP, ports and volumes, always run on the same
node, and talk over localhost.
Minimal manifest
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
labels:
app: web
spec:
containers:
- name: nginx
image: nginx:1.27
ports:
- containerPort: 80
resources:
requests: { cpu: "50m", memory: "64Mi" }
limits: { cpu: "200m", memory: "128Mi" }
Requests drive scheduling, limits are enforced at runtime - details on Day 3.
Lifecycle
| Phase / state | Meaning |
|---|---|
Pending | not scheduled yet, or waiting for image / volume |
ContainerCreating | placed on a node; kubelet pulls image, mounts volumes |
Running | at least one container runs |
Succeeded / Failed | all containers ended (exit 0 / non-zero) |
CrashLoopBackOff | container keeps dying; kubelet waits longer each time |
ImagePullBackOff | image name, tag or registry access is wrong |
restartPolicy: Always (default), OnFailure, Never.
Init containers and sidecars
spec:
initContainers:
- name: wait-for-db
image: busybox:1.36
command: ["sh", "-c", "until nc -z db 5432; do sleep 2; done"]
Init containers run to completion, in order, before the app containers start.
An init container with restartPolicy: Always is a native sidecar: it
starts first and keeps running next to the app.
Pods are cattle
Most of the Pod spec is immutable and a bare Pod is never rescheduled when its node dies. Use a controller (next chapter). Bare Pods are for debugging:
kubectl run tmp --image busybox:1.36 --restart=Never -it --rm -- sh