Pods are the smallest deployable units in Kubernetes. But you rarely manage pods directly. Deployments manage stateless applications with rolling updates and rollbacks. StatefulSets manage stateful applications with stable network identities. DaemonSets run a pod on every node. In this lesson, you'll master all the controllers that manage your pods.
1. Learning Objectives
By the end of this lesson, you will be able to:
- Understand Pod lifecycle and multi-container pods
- Create and manage Deployments for stateless apps
- Perform rolling updates and rollbacks
- Use StatefulSets for stateful applications
- Run node-wide services with DaemonSets
- Understand ReplicaSets for pod replication
2. Why This Matters
Real-world scenario: Your web app needs 5 replicas for high availability. When you update the image, you want zero downtime. When something fails, you want automatic healing. Deployments give you all of this automatically.
3. Core Concepts
Pods (Deep Dive)
# pod.yaml - Single container pod
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
labels:
app: nginx
tier: frontend
spec:
containers:
- name: nginx
image: nginx:1.25
ports:
- containerPort: 80
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"
# multi-container-pod.yaml - Sidecar pattern
apiVersion: v1
kind: Pod
metadata:
name: app-with-sidecar
spec:
containers:
# Main application container
- name: app
image: nginx:alpine
volumeMounts:
- name: shared-logs
mountPath: /var/log/nginx
# Sidecar container (logs collector)
- name: log-collector
image: fluent/fluentd:latest
volumeMounts:
- name: shared-logs
mountPath: /logs
env:
- name: FLUENTD_CONF
value: "tail"
volumes:
- name: shared-logs
emptyDir: {}
# Create and manage pods
kubectl apply -f pod.yaml
kubectl get pods -w
kubectl describe pod nginx-pod
kubectl logs nginx-pod
kubectl exec -it nginx-pod -- /bin/bash
kubectl delete pod nginx-pod
Pod definitions and management
Pod Lifecycle and States
Pod States:
- Pending: Pod accepted, containers not running yet
- Running: Pod bound to node, all containers running
- Succeeded: All containers terminated successfully
- Failed: At least one container terminated with failure
- Unknown: Pod state unknown (usually node communication issue)
- CrashLoopBackOff: Container repeatedly crashing
- ImagePullBackOff: Image pull failed
Pod Conditions:
- PodScheduled: Pod assigned to node
- Initialized: Init containers completed
- ContainersReady: All containers ready
- Ready: Pod ready to serve traffic
# Check pod status
kubectl get pods
kubectl describe pod <pod-name>
kubectl get events --field-selector involvedObject.name=<pod-name>
Pod states and conditions
Deployments (Stateless Applications)
# deployment.yaml - Complete deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: webapp-deployment
namespace: default
labels:
app: webapp
version: v1
spec:
replicas: 3
selector:
matchLabels:
app: webapp
template:
metadata:
labels:
app: webapp
version: v1
spec:
containers:
- name: webapp
image: nginx:1.25
ports:
- containerPort: 80
env:
- name: ENVIRONMENT
value: "production"
livenessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 80
initialDelaySeconds: 5
periodSeconds: 5
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "256Mi"
cpu: "200m"
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
# Deployment commands
kubectl apply -f deployment.yaml
kubectl get deployments
kubectl get replicasets
kubectl get pods -l app=webapp
# Scale deployment
kubectl scale deployment webapp-deployment --replicas=5
kubectl autoscale deployment webapp-deployment --cpu-percent=50 --min=3 --max=10
# Rolling update
kubectl set image deployment/webapp-deployment webapp=nginx:1.26
kubectl rollout status deployment/webapp-deployment
# Rollback
kubectl rollout history deployment/webapp-deployment
kubectl rollout undo deployment/webapp-deployment
kubectl rollout undo deployment/webapp-deployment --to-revision=2
# Pause and resume (for canary)
kubectl rollout pause deployment/webapp-deployment
kubectl rollout resume deployment/webapp-deployment
Deployments for stateless applications
ReplicaSets (Under the Hood)
# replicaset.yaml (usually not created directly)
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: webapp-replicaset
spec:
replicas: 3
selector:
matchLabels:
app: webapp
template:
metadata:
labels:
app: webapp
spec:
containers:
- name: nginx
image: nginx:1.25
# ReplicaSet is managed by Deployment
# View ReplicaSets
kubectl get replicasets
kubectl describe replicaset webapp-deployment-xxx
# ReplicaSet ensures specified number of pod replicas running
# If pods die, ReplicaSet creates new ones
# Deployment manages ReplicaSet, ReplicaSet manages pods
ReplicaSets - the pod controller
StatefulSets (Stateful Applications)
# statefulset.yaml - For databases and stateful apps
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: postgres-statefulset
spec:
serviceName: postgres-hl
replicas: 3
selector:
matchLabels:
app: postgres
template:
metadata:
labels:
app: postgres
spec:
containers:
- name: postgres
image: postgres:15-alpine
ports:
- containerPort: 5432
env:
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: postgres-secret
key: password
volumeMounts:
- name: data
mountPath: /var/lib/postgresql/data
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 10Gi
# Headless service for StatefulSet
apiVersion: v1
kind: Service
metadata:
name: postgres-hl
spec:
clusterIP: None
selector:
app: postgres
ports:
- port: 5432
# StatefulSet features:
# - Stable, unique network identifiers (pod-0, pod-1, pod-2)
# - Stable, persistent storage per pod
# - Ordered, graceful deployment and scaling
# - Ordered, automated rolling updates
kubectl get statefulsets
kubectl get pods -w
# Pods created in order: postgres-statefulset-0, -1, -2
# Each pod gets its own persistent volume
StatefulSets for stateful applications
DaemonSets (Node-Wide Services)
# daemonset.yaml - Run on every node
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: fluentd
namespace: kube-system
spec:
selector:
matchLabels:
name: fluentd
template:
metadata:
labels:
name: fluentd
spec:
tolerations:
- key: node-role.kubernetes.io/master
effect: NoSchedule
containers:
- name: fluentd
image: fluent/fluentd:latest
volumeMounts:
- name: varlog
mountPath: /var/log
- name: dockercontainers
mountPath: /var/lib/docker/containers
readOnly: true
volumes:
- name: varlog
hostPath:
path: /var/log
- name: dockercontainers
hostPath:
path: /var/lib/docker/containers
# Common DaemonSet use cases:
# - Log collection (Fluentd, Logstash)
# - Monitoring (Prometheus Node Exporter, Datadog agent)
# - Network plugins (Calico, Flannel, Cilium)
# - Storage (Ceph, GlusterFS)
# - Security (Falco, Twistlock)
kubectl get daemonsets -n kube-system
kubectl describe daemonset fluentd -n kube-system
DaemonSets for node-wide services
4. Complete Project: Multi-Tier Application
# complete-app.yaml - Frontend + Backend + Database
---
# Backend Deployment (stateless)
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend-deployment
spec:
replicas: 3
selector:
matchLabels:
app: backend
template:
metadata:
labels:
app: backend
spec:
containers:
- name: backend
image: myapp/backend:latest
ports:
- containerPort: 5000
env:
- name: DATABASE_URL
value: postgresql://postgres:password@postgres-statefulset-0.postgres-hl:5432/app
resources:
requests:
memory: "256Mi"
cpu: "200m"
limits:
memory: "512Mi"
cpu: "400m"
livenessProbe:
httpGet:
path: /health
port: 5000
initialDelaySeconds: 30
readinessProbe:
httpGet:
path: /ready
port: 5000
initialDelaySeconds: 5
---
# Frontend Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend-deployment
spec:
replicas: 2
selector:
matchLabels:
app: frontend
template:
metadata:
labels:
app: frontend
spec:
containers:
- name: frontend
image: myapp/frontend:latest
ports:
- containerPort: 3000
env:
- name: API_URL
value: http://backend-service:5000
---
# Database StatefulSet
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: postgres-statefulset
spec:
serviceName: postgres-hl
replicas: 1
selector:
matchLabels:
app: postgres
template:
metadata:
labels:
app: postgres
spec:
containers:
- name: postgres
image: postgres:15-alpine
ports:
- containerPort: 5432
env:
- name: POSTGRES_PASSWORD
value: "password"
- name: POSTGRES_DB
value: "app"
volumeMounts:
- name: data
mountPath: /var/lib/postgresql/data
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 10Gi
---
# Headless Service for StatefulSet
apiVersion: v1
kind: Service
metadata:
name: postgres-hl
spec:
clusterIP: None
selector:
app: postgres
ports:
- port: 5432
---
# Backend Service
apiVersion: v1
kind: Service
metadata:
name: backend-service
spec:
selector:
app: backend
ports:
- port: 5000
targetPort: 5000
type: ClusterIP
---
# Frontend Service
apiVersion: v1
kind: Service
metadata:
name: frontend-service
spec:
selector:
app: frontend
ports:
- port: 80
targetPort: 3000
type: LoadBalancer
# Deploy
kubectl apply -f complete-app.yaml
# Monitor rollout
kubectl rollout status deployment/backend-deployment
kubectl rollout status deployment/frontend-deployment
kubectl rollout status statefulset/postgres-statefulset
# Test scaling
kubectl scale deployment backend-deployment --replicas=5
kubectl get pods -l app=backend
# Rolling update
kubectl set image deployment/backend-deployment backend=myapp/backend:v2
kubectl rollout status deployment/backend-deployment
# Rollback if needed
kubectl rollout undo deployment/backend-deployment
Complete multi-tier application with all controller types
5. Common Errors & Solutions
6. Summary Checklist
7. Next Steps
Next lesson: Kubernetes Lesson 6.3: Services & Networking
Comments (0)
This is exactly what I needed! The initContainer approach solved our migration issues completely. Thanks for the detailed guide!
ReplyLeave a Comment