09-02 Pods and Workload Management Required
Pods are the smallest and most fundamental deployable units in Kubernetes. Understanding pods and how to manage them is essential for working with Kubernetes effectively.
What is a Pod?
Definition
A Pod is:
- The smallest deployable unit in Kubernetes
- A group of one or more containers
- Containers in a pod share resources
- Scheduled together on the same node
- Represents a single instance of an application
[!IMPORTANT] Can you deploy a container in Kubernetes?
NO (not directly). The smallest unit is a Pod, which contains one or more containers.
Why Pods, Not Containers?
Kubernetes uses pods instead of containers directly because:
- Colocation: Some containers need to be kept together
- Resource sharing: Containers in a pod share network and storage
- Atomic unit: All containers in a pod are scheduled together
- Lifecycle management: Pod represents a single logical application
┌─────────────────────────────────────┐
│ Pod │
│ ┌───────────┐ ┌───────────┐ │
│ │Container 1│ │Container 2│ │
│ │ (App) │ │ (Sidecar) │ │
│ └───────────┘ └───────────┘ │
│ │
│ Shared: │
│ • Network namespace (same IP) │
│ • IPC namespace │
│ • Volumes │
│ • Hostname │
└─────────────────────────────────────┘
Pod Characteristics
Shared Resources
Containers within the same pod share:
1. Network Namespace
- Same IP address and port space
- Communicate via localhost
- Share network ports (no conflicts allowed)
# Both containers share IP 10.244.1.5
Pod IP: 10.244.1.5
Container 1: localhost:8080
Container 2: localhost:9090
2. IPC Namespace
- Inter-Process Communication channels
- Can use System V IPC or POSIX message queues
- Enables fast communication between containers
3. Hostname
- All containers see the same hostname
- Hostname is the pod name
4. Volumes
- Shared storage mounted to pod
- All containers can access same volumes
- Enables data sharing between containers
Separate Resources
Each container has its own:
- cgroup (CPU and RAM allocation)
- Filesystem (unless using shared volumes)
- Process namespace (by default)
Pod Specification
Basic Pod YAML
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
labels:
app: web
env: prod
spec:
containers:
- name: nginx
image: nginx:1.21
ports:
- containerPort: 80
Complete Pod Example
apiVersion: v1
kind: Pod
metadata:
name: instructor-test-01
labels:
app: sklearn
tier: backend
spec:
restartPolicy: Never
containers:
- name: instructor-sklearn
image: crdsba6190deveastus001.azurecr.io/instructor_sklearn:latest
# Volume mounts
volumeMounts:
- name: datalake
mountPath: "/mnt/datalake/"
readOnly: false
# Command to run
command: ["/bin/bash", "-c", "--"]
args: ["while true; do sleep 30; done;"]
# Resource limits
resources:
limits:
memory: "2Gi"
cpu: "200m"
requests:
memory: "1Gi"
cpu: "100m"
# Image pull secrets
imagePullSecrets:
- name: acr-secret
# Volumes
volumes:
- name: datalake
persistentVolumeClaim:
claimName: pvc-datalake-class-blob
Key Spec Fields
| Field | Purpose |
|---|---|
containers |
List of containers in the pod |
volumes |
Storage volumes available to containers |
restartPolicy |
When to restart containers (Always, OnFailure, Never) |
imagePullSecrets |
Credentials for private registries |
nodeSelector |
Select which nodes can run this pod |
tolerations |
Allow pod to run on tainted nodes |
affinity |
Advanced scheduling rules |
When to Use Multiple Containers in a Pod
Use multiple containers in a pod when:
1. Impossible to Work on Different Machines
- Containers need to share local filesystem
- Containers use IPC for communication
- Very tight coupling required
2. Adapter Pattern
- One container facilitates communication for another
- Example: Log aggregator sidecar
3. Sidecar Pattern
- One container offers support for the main container
- Examples: Logging, monitoring, proxying
┌─────────────────────────────────────┐
│ Pod: Web Application │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ Main App │ │ Log Shipper │ │
│ │ (nginx) │ │ (fluentd) │ │
│ │ │ │ │ │
│ │ Writes logs │→ │ Ships logs │ │
│ │ to /var/log │ │ to central │ │
│ └──────────────┘ └──────────────┘ │
│ ↓ ↓ │
│ [Shared Volume: /var/log] │
└─────────────────────────────────────┘
4. Ambassador Pattern
- One container configures or proxies for another
- Example: Database proxy
Best Practice: Most pods should have one container. Only use multiple containers when there’s a strong reason.
Pod Lifecycle
Pod Phases
| Phase | Description |
|---|---|
| Pending | Pod accepted but not yet running |
| Running | Pod bound to node, containers running |
| Succeeded | All containers exited with status 0 |
| Failed | All containers terminated, at least one failed |
| Unknown | Pod state cannot be determined |
Pod Lifecycle Flow
Create Pod
↓
[Pending] → Scheduler assigns to node
↓
[Running] → Containers start
↓
├→ [Succeeded] → All containers exit 0
├→ [Failed] → Container exits non-zero
└→ [Unknown] → Communication lost
Pod Scheduling
How Pods are Scheduled
- User creates pod (via kubectl or API)
- API Server validates and stores in etcd
- Scheduler watches for unscheduled pods
- Scheduler selects a node based on:
- Resource requirements (CPU, memory)
- Node selectors and affinity rules
- Taints and tolerations
- Current node load
- Scheduler binds pod to node
- kubelet on node starts containers
Scheduling Constraints
apiVersion: v1
kind: Pod
metadata:
name: gpu-pod
spec:
# Node selector - simple key-value matching
nodeSelector:
gpu: nvidia
disktype: ssd
containers:
- name: cuda-app
image: nvidia/cuda
Pod Immutability
[!WARNING] Pods are immutable
Once a pod is scheduled to a node, it never moves. If the node dies, the pod must be deleted and recreated on another node.
This is why we use higher-level controllers (ReplicaSets, Deployments) instead of managing pods directly.
Pod Health Checks
Kubernetes provides three types of probes to monitor pod health:
1. Liveness Probe
Purpose: Is the application running?
- If fails → Kubernetes restarts the container
- Detects deadlocks and hung processes
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 15
periodSeconds: 10
2. Readiness Probe
Purpose: Is the application ready to serve traffic?
- If fails → Pod removed from service endpoints
- Application still running, just not receiving traffic
- Useful during startup or when temporarily overloaded
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
3. Startup Probe
Purpose: Has the application started?
- For slow-starting applications
- Disables liveness/readiness checks until startup succeeds
- If fails → Container restarted
startupProbe:
httpGet:
path: /startup
port: 8080
failureThreshold: 30
periodSeconds: 10
Probe Types
Probes can check health in three ways:
# 1. HTTP GET
livenessProbe:
httpGet:
path: /health
port: 8080
httpHeaders:
- name: Custom-Header
value: Awesome
# 2. TCP Socket
livenessProbe:
tcpSocket:
port: 8080
# 3. Exec Command
livenessProbe:
exec:
command:
- cat
- /tmp/healthy
Working with Pods
Creating Pods
# From YAML file
kubectl apply -f pod.yaml
# Imperative (quick testing)
kubectl run nginx --image=nginx --port=80
# With labels
kubectl run nginx --image=nginx --labels="app=web,env=prod"
Viewing Pods
# List all pods
kubectl get pods
# List pods with more details
kubectl get pods -o wide
# List pods with labels
kubectl get pods --show-labels
# Filter by label
kubectl get pods -l app=nginx
# Watch pods in real-time
kubectl get pods --watch
Inspecting Pods
# Detailed information
kubectl describe pod nginx-pod
# View logs
kubectl logs nginx-pod
# Logs from specific container (multi-container pod)
kubectl logs nginx-pod -c nginx
# Follow logs
kubectl logs -f nginx-pod
# Previous container logs (if restarted)
kubectl logs nginx-pod --previous
Interacting with Pods
# Execute command in pod
kubectl exec nginx-pod -- ls /
# Interactive shell
kubectl exec -it nginx-pod -- /bin/bash
# For multi-container pods, specify container
kubectl exec -it nginx-pod -c nginx -- /bin/bash
# Copy files to/from pod
kubectl cp nginx-pod:/var/log/nginx.log ./nginx.log
kubectl cp ./config.yaml nginx-pod:/etc/config.yaml
Deleting Pods
# Delete specific pod
kubectl delete pod nginx-pod
# Delete pods by label
kubectl delete pods -l app=nginx
# Delete all pods in namespace
kubectl delete pods --all
# Force delete (immediate, no graceful shutdown)
kubectl delete pod nginx-pod --grace-period=0 --force
Pod Templates
Higher-level controllers (Deployments, ReplicaSets) use Pod Templates:
# Pod Template (used in Deployment)
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.21
ports:
- containerPort: 80
Pod templates are pod specs with limited metadata. Controllers use these templates to create actual pods.
ConfigMaps and Secrets
ConfigMaps
Store configuration data for pods:
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
database_url: "postgresql://db:5432/myapp"
log_level: "info"
Use in Pod:
spec:
containers:
- name: app
image: myapp
envFrom:
- configMapRef:
name: app-config
Secrets
Store sensitive data (passwords, tokens):
apiVersion: v1
kind: Secret
metadata:
name: db-secret
type: Opaque
data:
password: cGFzc3dvcmQxMjM= # base64 encoded
Use in Pod:
spec:
containers:
- name: app
image: myapp
env:
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-secret
key: password
[!NOTE] Secrets are mounted as RAM disk
Secrets are not written to disk, only stored in memory for security.
Summary
Pods are the fundamental building blocks of Kubernetes:
- Smallest deployable unit containing one or more containers
- Share network, IPC, and volumes within the pod
- Scheduled atomically to a single node
- Immutable once scheduled (never moved)
- Health checks ensure application reliability
- Usually managed by higher-level controllers, not directly
In the next lecture, we’ll explore Services - how to provide stable network access to pods, and Deployments - how to manage pod replicas and updates.