Day 3: Understanding Pods
What You'll Learn Today
- What Pods are and why Kubernetes uses Pods instead of bare containers
- Pod lifecycle and state transitions
- Multi-container Pod patterns
- Probes for health checking
What is a Pod?
A Pod is the smallest deployable unit in Kubernetes. It wraps one or more containers that share the same network namespace and storage volumes.
In Docker, individual containers were the management unit. In Kubernetes, you never manage containers directly β they are always wrapped in a Pod.
flowchart TB
subgraph Pod["Pod"]
C1["Container A"]
C2["Container B"]
NET["Shared Network\n(localhost)"]
VOL["Shared Volume"]
end
C1 --- NET
C2 --- NET
C1 --- VOL
C2 --- VOL
style Pod fill:#3b82f6,color:#fff
Pods vs. Docker Containers
| Property | Docker Container | Kubernetes Pod |
|---|---|---|
| Unit | Single container | One or more containers |
| Network | Independent per container | Shared within Pod (localhost) |
| Storage | Explicit volume sharing | Shared within Pod |
| IP Address | Per container | Per Pod |
| Scaling | Per container | Per Pod |
Pod Lifecycle
Pods go through the following phases.
flowchart LR
A["Pending"] --> B["Running"]
B --> C["Succeeded"]
B --> D["Failed"]
A --> D
style A fill:#f59e0b,color:#fff
style B fill:#22c55e,color:#fff
style C fill:#3b82f6,color:#fff
style D fill:#ef4444,color:#fff
| Phase | Description |
|---|---|
| Pending | Pod created but containers not yet running |
| Running | At least one container is running |
| Succeeded | All containers exited successfully |
| Failed | At least one container exited with an error |
| Unknown | Pod status cannot be determined (node failure) |
Container States
| State | Description |
|---|---|
| Waiting | Waiting to start (image pull, etc.) |
| Running | Container is executing |
| Terminated | Container has exited (success or failure) |
# Check Pod state in detail
kubectl describe pod my-nginx
Detailed Pod Definition
A more practical Pod definition.
apiVersion: v1
kind: Pod
metadata:
name: web-app
labels:
app: web
environment: development
annotations:
description: "Sample web application pod"
spec:
containers:
- name: web
image: nginx:1.27
ports:
- containerPort: 80
protocol: TCP
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
cpu: "250m"
memory: "256Mi"
env:
- name: APP_ENV
value: "development"
restartPolicy: Always
Labels
Labels are key-value pairs for identifying resources. Many Kubernetes features depend on labels.
metadata:
labels:
app: web
environment: prod
version: v1.0
# Filter by label
kubectl get pods -l app=web
kubectl get pods -l 'app=web,environment=prod'
# Add a label
kubectl label pod web-app tier=frontend
# Show labels
kubectl get pods --show-labels
Resources
Just like Docker resource limits, Kubernetes controls container resources with requests and limits.
| Setting | Description |
|---|---|
| requests | Guaranteed resources for the container. Used for scheduling |
| limits | Maximum resources the container can use |
resources:
requests:
cpu: "100m" # 0.1 CPU core
memory: "128Mi" # 128 MiB
limits:
cpu: "250m" # 0.25 CPU core
memory: "256Mi" # 256 MiB
CPU is specified in "millicores" (m).
1000m = 1 CPU.
Restart Policy
| Policy | Description |
|---|---|
| Always | Always restart on exit (default) |
| OnFailure | Restart only on failure |
| Never | Never restart |
Multi-Container Pods
A Pod can contain multiple containers that work closely together.
Sidecar Pattern
An auxiliary container that supports the main container.
flowchart LR
subgraph Pod["Pod"]
MAIN["Main Container\n(Web App)"]
SIDE["Sidecar\n(Log Collector)"]
VOL["Shared Volume\n(/var/log)"]
end
MAIN --> VOL
SIDE --> VOL
SIDE --> EXT["External Log\nSystem"]
style Pod fill:#3b82f6,color:#fff
style EXT fill:#8b5cf6,color:#fff
apiVersion: v1
kind: Pod
metadata:
name: web-with-sidecar
spec:
containers:
- name: web
image: nginx:1.27
volumeMounts:
- name: logs
mountPath: /var/log/nginx
- name: log-collector
image: busybox:1.37
command: ["sh", "-c", "tail -f /var/log/nginx/access.log"]
volumeMounts:
- name: logs
mountPath: /var/log/nginx
volumes:
- name: logs
emptyDir: {}
Multi-Container Patterns
| Pattern | Description | Example |
|---|---|---|
| Sidecar | Supports the main container | Log collection, proxy |
| Ambassador | Mediates external communication | DB connection proxy |
| Adapter | Transforms output formats | Metrics conversion |
Init Containers
Special containers that run before the main containers start. Used for initialization tasks like waiting for dependencies or running database migrations.
apiVersion: v1
kind: Pod
metadata:
name: app-with-init
spec:
initContainers:
- name: wait-for-db
image: busybox:1.37
command: ['sh', '-c', 'until nc -z db-service 5432; do echo waiting for db; sleep 2; done']
containers:
- name: app
image: my-app:1.0
flowchart LR
I1["Init Container 1\n(Wait for DB)"] --> I2["Init Container 2\n(Fetch Config)"]
I2 --> M["Main Container\n(App Start)"]
style I1 fill:#f59e0b,color:#fff
style I2 fill:#f59e0b,color:#fff
style M fill:#22c55e,color:#fff
Init Container characteristics:
- Run sequentially, one at a time
- All Init Containers must succeed before main containers start
- Retried on failure according to the restartPolicy
Probes (Health Checks)
Kubernetes monitors container health with three types of probes β an evolution of Docker's HEALTHCHECK.
| Probe | Purpose | On Failure |
|---|---|---|
| livenessProbe | Is the container alive? | Restart container |
| readinessProbe | Can it receive traffic? | Remove from Service |
| startupProbe | Has startup completed? | Disable other probes until done |
apiVersion: v1
kind: Pod
metadata:
name: web-with-probes
spec:
containers:
- name: web
image: nginx:1.27
ports:
- containerPort: 80
livenessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 5
periodSeconds: 10
readinessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 3
periodSeconds: 5
startupProbe:
httpGet:
path: /
port: 80
failureThreshold: 30
periodSeconds: 10
Probe Methods
| Method | Description | Use Case |
|---|---|---|
| httpGet | Expects 200-399 from an HTTP endpoint | Web servers |
| tcpSocket | Attempts TCP connection | Databases |
| exec | Runs a command, expects exit code 0 | Custom checks |
| grpc | gRPC health check protocol | gRPC services |
Working with Pods
Accessing Containers
# Shell access
kubectl exec -it web-app -- /bin/bash
# Specify container in multi-container Pod
kubectl exec -it web-with-sidecar -c log-collector -- /bin/sh
# Copy files from container
kubectl cp web-app:/etc/nginx/nginx.conf ./nginx.conf
# Copy files to container
kubectl cp ./index.html web-app:/usr/share/nginx/html/
Debugging Pods
# Detailed info and events
kubectl describe pod web-app
# Logs
kubectl logs web-app
kubectl logs web-app -f # Stream logs
kubectl logs web-app --previous # Previous container's logs
kubectl logs web-app -c log-collector # Specific container's logs
# Resource usage
kubectl top pod web-app
Summary
| Concept | Description |
|---|---|
| Pod | Smallest deployable unit wrapping one or more containers |
| Labels | Key-value pairs for identifying resources |
| Resources | Manage with requests (guaranteed) and limits (maximum) |
| Multi-container Pod | Sidecar, ambassador, and adapter patterns |
| Init Container | Runs before main containers for initialization |
| Probes | Three types: liveness, readiness, and startup |
Key Takeaways
- Kubernetes manages Pods, not individual containers. Containers in a Pod share network and storage
- Labels are foundational to many Kubernetes features. Design them carefully
- Properly configured probes let Kubernetes automatically maintain application health
Practice Exercises
Exercise 1: Basics
Write a YAML manifest for a Pod with:
- Name:
my-app - Image:
httpd:2.4 - CPU requests: 50m, limits: 100m
- Memory requests: 64Mi, limits: 128Mi
- livenessProbe and readinessProbe (httpGet, port 80)
Exercise 2: Multi-container
Create a Pod with a web server (nginx) and a log-forwarding sidecar (busybox) using a shared volume.
Challenge
Design a Pod with an Init Container that creates a "welcome.html" file before the main nginx container starts, serving that file to visitors.
References
Next up: In Day 4, you'll learn about "ReplicaSets and Deployments." Instead of creating Pods directly, you'll manage them through Deployments.