1. Pods
A Pod is the smallest deployable unit in Kubernetes. It wraps one or more containers that share a network namespace (one IP), IPC, and optionally volumes. Most production apps run inside Deployments, but understanding Pods is essential.
┌─────────────────────────────────────────────┐
│ Pod 10.244.1.8 │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ app │ │ sidecar │ │
│ │ :8080 │ │ (logging) │ │
│ └─────────────┘ └─────────────┘ │
│ shared: localhost, volumes, hostname │
└─────────────────────────────────────────────┘
Single-container Pod
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.25
ports:
- containerPort: 80
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 256Mi
Multi-container Pod (sidecar pattern)
apiVersion: v1
kind: Pod
metadata:
name: app-with-logger
spec:
containers:
- name: app
image: myapp:1.0
volumeMounts:
- name: logs
mountPath: /var/log/app
- name: log-shipper
image: fluent/fluent-bit:2.2
volumeMounts:
- name: logs
mountPath: /var/log/app
readOnly: true
volumes:
- name: logs
emptyDir: {}
Pod lifecycle phases
| Phase | Meaning |
|---|---|
Pending | Accepted but not yet running (scheduling, image pull) |
Running | At least one container is running |
Succeeded | All containers terminated successfully (Jobs) |
Failed | At least one container failed |
Unknown | Node communication lost |
2. ReplicaSets
A ReplicaSet maintains a stable set of Pod replicas. It creates or deletes Pods to match spec.replicas and uses a label selector to identify managed Pods.
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: api-rs
labels:
app: api
spec:
replicas: 3
selector:
matchLabels:
app: api
tier: backend
template:
metadata:
labels:
app: api
tier: backend
spec:
containers:
- name: api
image: myregistry/api:1.0.0
ports:
- containerPort: 8080
You rarely create ReplicaSets directly. Deployments own ReplicaSets and handle rolling updates. ReplicaSets remain the mechanism underneath.
kubectl get rs
kubectl describe rs api-rs
# Pods owned by ReplicaSet show ownerReferences in metadata
3. Deployments
A Deployment is the standard way to run stateless applications. It manages ReplicaSets and supports declarative updates, rollbacks, and scaling.
Basic Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: api
namespace: production
spec:
replicas: 3
revisionHistoryLimit: 5
selector:
matchLabels:
app: api
template:
metadata:
labels:
app: api
spec:
containers:
- name: api
image: myregistry/api:2.0.0
ports:
- containerPort: 8080
Rolling update strategy
spec:
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1 # extra Pods above desired count during update
maxUnavailable: 0 # zero-downtime: always keep full capacity
minReadySeconds: 10
# Rollout commands
kubectl set image deployment/api api=myregistry/api:2.1.0
kubectl rollout status deployment/api
kubectl rollout history deployment/api
kubectl rollout undo deployment/api
kubectl rollout undo deployment/api --to-revision=2
Recreate strategy (brief downtime)
spec:
strategy:
type: Recreate # kill all old Pods, then start new ones
Deployment revision diagram
Deployment "api" (desired: 3 replicas, image v2)
│
├── ReplicaSet api-7d4f8b (rev 2, image v2) ← active, 3 Pods
└── ReplicaSet api-9a2c1e (rev 1, image v1) ← scaled to 0, kept for rollback
4. StatefulSets
StatefulSets manage stateful applications with stable network identities, ordered deployment, and persistent storage per replica. Use for databases, Kafka, ZooKeeper, Elasticsearch.
- Stable Pod names:
postgres-0,postgres-1,postgres-2 - Stable DNS:
postgres-0.postgres.default.svc.cluster.local - Ordered rollout and scale (0, then 1, then 2)
- PersistentVolumeClaim per Pod via
volumeClaimTemplates
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: postgres
spec:
serviceName: postgres # headless Service required
replicas: 3
podManagementPolicy: OrderedReady
selector:
matchLabels:
app: postgres
template:
metadata:
labels:
app: postgres
spec:
containers:
- name: postgres
image: postgres:16
ports:
- containerPort: 5432
volumeMounts:
- name: data
mountPath: /var/lib/postgresql/data
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: gp3
resources:
requests:
storage: 50Gi
# Headless Service for StatefulSet DNS
apiVersion: v1
kind: Service
metadata:
name: postgres
spec:
clusterIP: None
selector:
app: postgres
ports:
- port: 5432
kubectl delete statefulset postgres --cascade=orphan carefully, or delete PVCs explicitly when decommissioning data.
5. DaemonSets
A DaemonSet ensures one Pod copy runs on every node (or a subset via node selectors). Used for node-level agents: log collectors, monitoring, CNI plugins, storage drivers.
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: node-exporter
namespace: monitoring
spec:
selector:
matchLabels:
app: node-exporter
template:
metadata:
labels:
app: node-exporter
spec:
tolerations:
- operator: Exists # run on tainted nodes too
containers:
- name: exporter
image: prom/node-exporter:v1.7
ports:
- containerPort: 9100
resources:
requests:
cpu: 50m
memory: 64Mi
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Node 1 │ │ Node 2 │ │ Node 3 │
│ ┌──────┐ │ │ ┌──────┐ │ │ ┌──────┐ │
│ │ DS │ │ │ │ DS │ │ │ │ DS │ │
│ │ Pod │ │ │ │ Pod │ │ │ │ Pod │ │
│ └──────┘ │ │ └──────┘ │ │ └──────┘ │
└──────────┘ └──────────┘ └──────────┘
one DaemonSet Pod per eligible node
6. Jobs & CronJobs
Jobs run Pods to completion (batch, one-off tasks). CronJobs create Jobs on a schedule.
Job
apiVersion: batch/v1
kind: Job
metadata:
name: db-migrate
spec:
backoffLimit: 3
activeDeadlineSeconds: 600
template:
spec:
restartPolicy: OnFailure
containers:
- name: migrate
image: myregistry/api:2.0.0
command: ["python", "manage.py", "migrate"]
Parallel Job (work queue)
spec:
completions: 10 # 10 successful Pod completions required
parallelism: 3 # run 3 Pods at a time
template:
spec:
restartPolicy: OnFailure
containers:
- name: worker
image: batch-worker:latest
CronJob
apiVersion: batch/v1
kind: CronJob
metadata:
name: nightly-backup
spec:
schedule: "0 2 * * *" # 02:00 UTC daily
concurrencyPolicy: Forbid
successfulJobsHistoryLimit: 3
failedJobsHistoryLimit: 1
jobTemplate:
spec:
template:
spec:
restartPolicy: OnFailure
containers:
- name: backup
image: backup-tool:1.0
args: ["--target", "s3://backups/prod"]
kubectl get jobs
kubectl get cronjobs
kubectl create job manual-backup --from=cronjob/nightly-backup
7. Probes
Probes tell kubelet whether a container is alive, ready to receive traffic, or still starting up. Misconfigured probes are a top cause of CrashLoopBackOff and flapping Deployments.
| Probe | Purpose | Failure action |
|---|---|---|
| Liveness | Is the process healthy? | Restart the container |
| Readiness | Can it serve traffic? | Remove from Service endpoints |
| Startup | Has it finished booting? | Disable liveness until success; restart if fail |
HTTP probes
spec:
containers:
- name: api
image: myregistry/api:2.0.0
ports:
- containerPort: 8080
startupProbe:
httpGet:
path: /healthz
port: 8080
failureThreshold: 30
periodSeconds: 10 # up to 300s startup time
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 0
periodSeconds: 10
failureThreshold: 3
readinessProbe:
httpGet:
path: /ready
port: 8080
periodSeconds: 5
failureThreshold: 2
TCP and exec probes
livenessProbe:
tcpSocket:
port: 5432
periodSeconds: 15
readinessProbe:
exec:
command:
- pg_isready
- -U
- postgres
periodSeconds: 10
initialDelaySeconds on liveness delays crash detection. Startup probes protect the container during boot.
8. Horizontal Pod Autoscaler (HPA)
The HPA automatically scales Deployment (or StatefulSet) replicas based on observed metrics. Requires metrics-server (CPU/memory) or custom/external metrics (Prometheus adapter).
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: api-hpa
namespace: production
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: api
minReplicas: 2
maxReplicas: 20
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80
Custom metric (requests per second)
metrics:
- type: Pods
pods:
metric:
name: http_requests_per_second
target:
type: AverageValue
averageValue: "1000"
Scaling behaviour
behavior:
scaleDown:
stabilizationWindowSeconds: 300
policies:
- type: Percent
value: 10
periodSeconds: 60
scaleUp:
stabilizationWindowSeconds: 0
policies:
- type: Pods
value: 4
periodSeconds: 60
kubectl get hpa
kubectl describe hpa api-hpa
kubectl top pods -n production
HPA changes replica count; Cluster Autoscaler adds nodes when pending Pods cannot be scheduled. Together they scale the workload and the infrastructure.
9. Resource Requests & Limits
Every container should declare requests (used for scheduling) and limits (maximum allowed). Without requests, the scheduler cannot place Pods intelligently; without limits, one Pod can starve others.
| Field | Effect |
|---|---|
requests.cpu | Scheduler reserves this CPU on a node |
limits.cpu | Throttled via CFS quota when exceeded |
requests.memory | Scheduler reserves this memory |
limits.memory | OOMKilled if exceeded |
CPU and memory units
- CPU:
1= 1 core,500m= 0.5 core,100m= 0.1 core - Memory:
128Mi(mebibytes),1Gi(gibibytes)
Example container resources
spec:
containers:
- name: api
image: myregistry/api:2.0.0
resources:
requests:
cpu: 250m
memory: 256Mi
limits:
cpu: "1"
memory: 512Mi
QoS classes
| QoS | Condition | Eviction priority |
|---|---|---|
| Guaranteed | limits = requests for all containers | Last evicted |
| Burstable | At least one request or limit set | Middle |
| BestEffort | No requests or limits | First evicted |
LimitRange and ResourceQuota
# Namespace default for containers without resources
apiVersion: v1
kind: LimitRange
metadata:
name: defaults
namespace: production
spec:
limits:
- type: Container
default:
cpu: 500m
memory: 256Mi
defaultRequest:
cpu: 100m
memory: 128Mi
max:
cpu: "4"
memory: 4Gi
# Cap total namespace consumption
apiVersion: v1
kind: ResourceQuota
metadata:
name: prod-quota
namespace: production
spec:
hard:
requests.cpu: "20"
requests.memory: 40Gi
limits.cpu: "40"
pods: "50"
10. Cheat Sheet
| Task | Command |
|---|---|
| List Deployments | kubectl get deploy -A |
| Scale Deployment | kubectl scale deploy/api --replicas=5 |
| Rollout undo | kubectl rollout undo deploy/api |
| StatefulSet Pods | kubectl get pods -l app=postgres |
| Run one-off Job | kubectl create job test --image=busybox -- echo hi |
| CronJob schedule | kubectl get cronjobs |
| Check probes | kubectl describe pod <name> | grep -A5 Liveness |
| HPA status | kubectl get hpa |
| Pod resource usage | kubectl top pods |
| QoS class | kubectl get pod <name> -o jsonpath='{.status.qosClass}' |
Full cheat sheet: kubectl Cheat Sheet