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:

  1. Colocation: Some containers need to be kept together
  2. Resource sharing: Containers in a pod share network and storage
  3. Atomic unit: All containers in a pod are scheduled together
  4. 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

  1. User creates pod (via kubectl or API)
  2. API Server validates and stores in etcd
  3. Scheduler watches for unscheduled pods
  4. Scheduler selects a node based on:
    • Resource requirements (CPU, memory)
    • Node selectors and affinity rules
    • Taints and tolerations
    • Current node load
  5. Scheduler binds pod to node
  6. 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.

Further Reading

← Back to Chapter Home