Pods and Workloads
Understand pods, containers, labels, selectors, and how Kubernetes schedules and manages workload lifecycles.
Pod Basics
A Pod groups one or more containers together so they can run as a single unit on one node. Every container in a Pod shares the same network namespace (IP + ports) and can share storage volumes.
┌─────────────────────────────────────┐
│ Pod (shared IP: 10.244.0.5) │
│ │
│ ┌─────────────┐ ┌──────────────┐ │
│ │ app:nginx │ │ sidecar:log │ │
│ │ port 80 │ │ (read logs) │ │
│ └─────────────┘ └──────────────┘ │
│ │
│ shared volume: /var/log/nginx │
└─────────────────────────────────────┘
Your First Pod Manifest
# pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: my-nginx
labels:
app: my-nginx
env: dev
spec:
containers:
- name: nginx
image: nginx:1.25
ports:
- containerPort: 80
resources:
requests:
cpu: "100m"
memory: "64Mi"
limits:
cpu: "200m"
memory: "128Mi"
# Apply the pod manifest
kubectl apply -f pod.yaml
# Check it started
kubectl get pods
# Detailed view — events, container status, node assignment
kubectl describe pod my-nginx
# Stream logs
kubectl logs -f my-nginx
# Open an interactive shell
kubectl exec -it my-nginx -- bash
# Delete the pod
kubectl delete pod my-nginx
# or
kubectl delete -f pod.yaml
Multi-Container Pod (Sidecar Pattern)
# pod-sidecar.yaml
apiVersion: v1
kind: Pod
metadata:
name: app-with-sidecar
spec:
volumes:
- name: shared-logs
emptyDir: {}
containers:
- name: app
image: nginx:1.25
volumeMounts:
- name: shared-logs
mountPath: /var/log/nginx
- name: log-shipper
image: busybox:1.36
command: ["sh", "-c", "tail -f /logs/access.log"]
volumeMounts:
- name: shared-logs
mountPath: /logs
Both containers communicate over localhost since they share the same network namespace.
Labels and Selectors
Labels are the primary way Kubernetes objects find and relate to each other.
# Applying labels to a pod
metadata:
name: api-server
labels:
app: api # what app
version: v2 # which version
env: production # which environment
tier: backend # which tier
# List pods with their labels
kubectl get pods --show-labels
# Filter pods by label
kubectl get pods -l app=api
kubectl get pods -l env=production,tier=backend
# Add a label to a running pod (imperative)
kubectl label pod my-nginx region=us-east
# Remove a label
kubectl label pod my-nginx region-
# Select pods NOT matching a label
kubectl get pods -l 'env!=dev'
Pod Lifecycle
Pending → Running → Succeeded / Failed
↕
CrashLoopBackOff (if container keeps failing)
# Watch pod status transitions in real time
kubectl get pods --watch
# Check why a pod is in CrashLoopBackOff
kubectl describe pod <name> # look at Events section
kubectl logs <name> --previous # logs from previous (crashed) run
Init Containers
Init containers run to completion before main containers start — useful for waiting on databases or seeding config.
apiVersion: v1
kind: Pod
metadata:
name: app-with-init
spec:
initContainers:
- name: wait-for-db
image: busybox:1.36
command:
- sh
- -c
- "until nc -z postgres-service 5432; do echo waiting; sleep 2; done"
containers:
- name: app
image: my-api:1.0
ports:
- containerPort: 8080
Resource Requests and Limits
resources:
requests:
cpu: "250m" # 0.25 cores guaranteed
memory: "128Mi" # 128 MB guaranteed
limits:
cpu: "500m" # max 0.5 cores
memory: "256Mi" # max 256 MB (OOMKilled if exceeded)
# Check resource usage for pods
kubectl top pods
# Check resource usage for nodes
kubectl top nodes
Health Probes
spec:
containers:
- name: api
image: my-api:1.0
livenessProbe: # restart if this fails
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
readinessProbe: # only send traffic when this passes
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 3
periodSeconds: 5
| Probe | Failure action |
|---|---|
livenessProbe | Restart the container |
readinessProbe | Remove from Service endpoints (no traffic) |
startupProbe | Block liveness/readiness until startup completes |
Learning Outcomes
You should be able to:
- Write and apply a Pod manifest with
kubectl apply - Explain the sidecar pattern and when to use it
- Use labels and selectors to organize and filter resources
- Configure resource requests/limits and health probes
- Reason about why Services route to the right Pods
Frequently Asked Questions
What exactly is a Pod in Kubernetes?
A Pod is the smallest deployable unit in Kubernetes. It usually contains one container, but can contain multiple containers that share networking and storage.
Why do we use labels and selectors?
Labels tag objects with key/value metadata. Selectors let controllers (like Deployments and Services) find the Pods they should manage or route traffic to.