Pods and Deployments¶
Pods are the runtime unit. Deployments are the lifecycle controller.
If you remember one rule, remember this: in production, you almost never run standalone pods. You run pods through a controller, usually a Deployment.
Pod fundamentals¶
A pod is one or more containers that share:
- one network namespace (same IP, localhost communication)
- declared storage volumes
- one scheduling decision
Most pods should contain one main application container. Add sidecars only when they provide clear value, such as logging, proxying, or telemetry.
Pod lifecycle¶
A pod moves through several phases during its lifetime:
stateDiagram-v2
[*] --> Pending : created
Pending --> Running : scheduled and containers start
Running --> Succeeded : all containers exit 0, no more restarts
Running --> Failed : terminated in failure, no more restarts
Running --> Unknown : node communication lost
- Pending: accepted by the API server but not yet scheduled, or images not yet pulled.
- Running: at least one container is running or starting.
- Succeeded: all containers exited successfully and will not be restarted (common for Jobs).
- Failed: all containers terminated and at least one failed, with no further restarts (only possible when
restartPolicyisNeverorOnFailureretries are exhausted). - Unknown: the node cannot be reached.
A crucial subtlety: with restartPolicy: Always (the default, and what Deployments use), a crashing container never moves the pod to Failed. The pod phase stays Running while the kubelet restarts the container with exponential backoff -- that's what CrashLoopBackOff is. It appears in the container state, not the pod phase. This is why kubectl get pods can show Running for a pod that is actually broken; check the READY column and container statuses, not just the phase.
Phase is deliberately coarse. The finer-grained truth lives in pod conditions (PodScheduled, Initialized, ContainersReady, Ready) and per-container states (Waiting, Running, Terminated), all visible in kubectl describe pod.
Why pods alone are not enough¶
Pods are disposable. They can disappear during node failure, eviction, rescheduling, or rollout. A naked pod does not self-heal.
That is why controllers exist.
What Deployments do¶
A Deployment manages a ReplicaSet, and the ReplicaSet manages pods.
Deployment responsibilities:
- keep the desired replica count running
- perform rolling updates
- support rollback to prior revisions
- expose rollout status and history
graph TD
A[Apply Deployment] --> B[Deployment controller]
B --> C[ReplicaSet]
C --> D[Pods]
D --> E[Node failure or pod crash]
E --> C
Example Deployment¶
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
spec:
replicas: 3
selector:
matchLabels:
app: web
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
maxSurge: 1
template:
metadata:
labels:
app: web
spec:
containers:
- name: web
image: ghcr.io/example/web:v1.2.0
ports:
- containerPort: 8080
readinessProbe:
httpGet:
path: /ready
port: 8080
periodSeconds: 5
Rolling update behavior¶
Here is what actually happens during an update. A Deployment never modifies pods in place -- it creates a new ReplicaSet for the new pod template and scales the two ReplicaSets in opposite directions:
graph LR
D[Deployment v2] --> RS1[ReplicaSet v1<br/>3 → 2 → 1 → 0]
D --> RS2[ReplicaSet v2<br/>0 → 1 → 2 → 3]
Each step waits for new pods to become ready (readiness probe passing) before continuing. The old ReplicaSet is kept at zero replicas afterward -- that retained history is what makes kubectl rollout undo instant: rollback is just scaling the previous ReplicaSet back up. revisionHistoryLimit (default 10) controls how many old ReplicaSets are kept.
Key controls:
maxUnavailable: how many old pods can be unavailable during rolloutmaxSurge: how many extra new pods can be created temporarily
With maxSurge: 1, maxUnavailable: 0, capacity never drops below the desired count -- the safest setting for latency-critical services, at the cost of needing headroom for one extra pod.
Two consequences worth knowing:
- A rollout with a failing readiness probe stalls rather than fails. The Deployment waits (
progressDeadlineSeconds, default 600s) before marking the rollout as not progressing. Old pods keep serving -- this is the safety net working as designed. - Only changes to
spec.templatetrigger a rollout. Scaling replicas or editing labels on the Deployment itself does not create a new ReplicaSet. Notably, changing a ConfigMap that pods reference does not restart them -- usekubectl rollout restartor a checksum annotation for that.
Standalone pod use cases¶
Standalone pods are still useful for short-lived debugging:
Do not use this pattern for long-running applications.
Graceful shutdown¶
When a pod is deleted, Kubernetes sends SIGTERM to containers and waits terminationGracePeriodSeconds (default 30s) before sending SIGKILL. Use the preStop lifecycle hook to drain connections cleanly before the signal arrives, especially for servers that need time to finish in-flight requests.
If your application needs more than 30 seconds to shut down, increase terminationGracePeriodSeconds.
Common mistakes¶
- Deploying applications with
kubectl runand no controller - Missing
resources.requests, which hurts scheduling quality - Missing readiness probes, which can route traffic to not-ready pods
- Using mutable image tags like
latestin production - Setting
imagePullPolicy: Alwayswithout understanding it pulls on every pod start, even for immutable tags - Not setting
terminationGracePeriodSecondslong enough for slow-draining services
Quick operations checklist¶
kubectl get deploy,rs,pods -l app=web
kubectl rollout status deploy/web
kubectl rollout history deploy/web
kubectl rollout undo deploy/web
Certification notes¶
- CKAD expects fast Deployment creation:
kubectl create deployment web --image=nginx --replicas=3 --dry-run=client -o yamlgives you a skeleton to edit. - Know the rollout command family cold:
rollout status,rollout history,rollout undo [--to-revision=N],rollout restart. - Understand why a pod shows
Runningbut0/1 READY-- readiness probe failure is the most common scenario-question answer.
Summary¶
Pods execute containers. Deployments enforce application availability and safe change management through ReplicaSet versioning. For production services, Deployment should be the default starting point.
Related Concepts¶
- Init Containers for startup dependencies
- Jobs and CronJobs for batch and scheduled workloads
- StatefulSets for stateful applications
- Horizontal Pod Autoscaling for dynamic scaling
- Scheduling and Placement for where pods land