[3/24] P is for Pods: The Basic Building Blocks of Kubernetes
π This is Post #3 in the Kubernetes A-to-Z Series
Reading Order: β Previous: Docker Fundamentals β Next: Deployments β
Series Progress: 3/24 complete | Difficulty: Beginner | Time: 15 min | Part 1/6: Foundation
Welcome to the third post in our Kubernetes A-to-Z Series! Today weβll explore Pods, the fundamental building blocks of Kubernetes. Understanding pods is crucial because everything in Kubernetes ultimately runs inside pods, whether itβs a single container or a complex multi-container application.
What is a Pod?
A Pod is the smallest deployable unit in Kubernetes. It represents a single instance of a running process in your cluster and can contain one or more containers that share storage, network, and specifications for how to run.
Pod vs Container
Container World (Docker):
βββββββββββββββββββββββ
β Container 1 β
β (nginx) β
βββββββββββββββββββββββ
βββββββββββββββββββββββ
β Container 2 β
β (node-app) β
βββββββββββββββββββββββ
Kubernetes World (Pods):
βββββββββββββββββββββββββββββββββββ
β Pod 1 β
β ββββββββββββ ββββββββββββ β
β βContainer β βContainer β β
β β(nginx) β β(sidecar) β β
β ββββββββββββ ββββββββββββ β
βββββββββββββββββββββββββββββββββββ
Key Pod Characteristics
- Single IP Address: All containers in a pod share the same IP address
- Shared Storage: Containers can share volumes and data
- Same Network Namespace: Containers can communicate via localhost
- Co-scheduled: All containers are scheduled together on the same node
- Shared Fate: If the pod dies, all containers die together
Pod Architecture and Components
Pod Structure
apiVersion: v1
kind: Pod
metadata:
name: my-app-pod
labels:
app: myapp
tier: frontend
spec:
containers:
- name: app
image: myapp:latest
ports:
- containerPort: 8080
env:
- name: DATABASE_URL
value: "postgres://localhost:5432/mydb"
- name: sidecar
image: logging-agent:latest
volumeMounts:
- name: shared-logs
mountPath: /var/log
volumes:
- name: shared-logs
emptyDir: {}
Pod Lifecycle Phases
# Check pod status
kubectl get pods
# NAME READY STATUS RESTARTS AGE
# my-app-pod 2/2 Running 0 5m
Pod Phases:
- Pending: Pod is created but not yet scheduled
- Running: Pod is scheduled and containers are running
- Succeeded: All containers completed successfully
- Failed: All containers terminated, at least one failed
- Unknown: Pod state cannot be determined
Creating and Managing Pods
Basic Pod Creation
# Create pod imperatively
kubectl run nginx --image=nginx:latest
# Create pod from YAML file
kubectl apply -f pod.yaml
# Get pod details
kubectl get pods
kubectl describe pod nginx
# Access pod logs
kubectl logs nginx
kubectl logs -f nginx # Follow logs
# Execute commands in pod
kubectl exec -it nginx -- /bin/bash
Pod YAML Configuration
# simple-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
labels:
app: nginx
environment: production
spec:
containers:
- name: nginx
image: nginx:1.21
ports:
- containerPort: 80
name: http
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"
env:
- name: NGINX_HOST
value: "example.com"
- name: NGINX_PORT
value: "80"
Multi-Container Pod Patterns
1. Sidecar Pattern
A helper container that extends the main containerβs functionality:
# sidecar-pattern.yaml
apiVersion: v1
kind: Pod
metadata:
name: webapp-with-logging
spec:
containers:
- name: webapp
image: myapp:latest
ports:
- containerPort: 8080
volumeMounts:
- name: logs
mountPath: /var/log/app
- name: log-collector
image: fluentd:latest
volumeMounts:
- name: logs
mountPath: /var/log/app
- name: fluentd-config
mountPath: /etc/fluentd
volumes:
- name: logs
emptyDir: {}
- name: fluentd-config
configMap:
name: fluentd-config
2. Adapter Pattern
Transforms the main containerβs interface:
# adapter-pattern.yaml
apiVersion: v1
kind: Pod
metadata:
name: metrics-adapter
spec:
containers:
- name: application
image: legacy-app:latest
ports:
- containerPort: 8080
- name: metrics-exporter
image: prometheus-exporter:latest
ports:
- containerPort: 9090
env:
- name: TARGET_APP
value: "localhost:8080"
3. Ambassador Pattern
A proxy that handles external communication:
# ambassador-pattern.yaml
apiVersion: v1
kind: Pod
metadata:
name: database-client
spec:
containers:
- name: app
image: myapp:latest
env:
- name: DATABASE_HOST
value: "localhost:5432"
- name: cloudsql-proxy
image: gcr.io/cloudsql-docker/gce-proxy:latest
command: ["/cloud_sql_proxy",
"-instances=<project>:<region>:<instance>=tcp:5432",
"-credential_file=/secrets/cloudsql/credentials.json"]
volumeMounts:
- name: cloudsql-instance-credentials
mountPath: /secrets/cloudsql
readOnly: true
volumes:
- name: cloudsql-instance-credentials
secret:
secretName: cloudsql-instance-credentials
4. Init Container Pattern
Containers that run before the main application:
# init-container-pattern.yaml
apiVersion: v1
kind: Pod
metadata:
name: app-with-init
spec:
initContainers:
- name: database-migration
image: migrate/migrate:latest
command: ['migrate', '-path', '/migrations', '-database', 'postgres://db/myapp', 'up']
volumeMounts:
- name: migrations
mountPath: /migrations
- name: wait-for-services
image: busybox:latest
command: ['sh', '-c', 'until nc -z database-service 5432; do sleep 1; done']
containers:
- name: app
image: myapp:latest
ports:
- containerPort: 8080
volumes:
- name: migrations
configMap:
name: database-migrations
Pod Networking
Network Model
# Get pod IP address
kubectl get pod nginx-pod -o wide
# NAME READY STATUS RESTARTS AGE IP NODE
# nginx-pod 1/1 Running 0 5m 10.244.1.5 node-1
Key Networking Concepts:
- Single IP per Pod: All containers share the same IP
- localhost Communication: Containers in same pod communicate via localhost
- Port Binding: Containers must bind to different ports within pod
- Network Policies: Control traffic between pods
Container Port Configuration
# networking-example.yaml
apiVersion: v1
kind: Pod
metadata:
name: multi-port-app
spec:
containers:
- name: web
image: nginx:latest
ports:
- containerPort: 80
name: http
- containerPort: 443
name: https
- name: metrics
image: prometheus/nginx-exporter:latest
ports:
- containerPort: 9113
name: metrics
env:
- name: SCRAPE_URI
value: "http://localhost/nginx_status"
Pod Storage and Volumes
Volume Types
# volumes-example.yaml
apiVersion: v1
kind: Pod
metadata:
name: storage-demo
spec:
containers:
- name: app
image: busybox:latest
command: ['sh', '-c', 'echo "Hello $(date)" >> /data/log.txt && sleep 3600']
volumeMounts:
- name: data
mountPath: /data
- name: reader
image: busybox:latest
command: ['sh', '-c', 'tail -f /data/log.txt']
volumeMounts:
- name: data
mountPath: /data
volumes:
- name: data
emptyDir: {}
Common Volume Types
# configmap-volume.yaml
apiVersion: v1
kind: Pod
metadata:
name: configmap-demo
spec:
containers:
- name: app
image: myapp:latest
volumeMounts:
- name: config
mountPath: /etc/config
volumes:
- name: config
configMap:
name: app-config
# secret-volume.yaml
apiVersion: v1
kind: Pod
metadata:
name: secret-demo
spec:
containers:
- name: app
image: myapp:latest
volumeMounts:
- name: secrets
mountPath: /etc/secrets
readOnly: true
volumes:
- name: secrets
secret:
secretName: app-secrets
# hostpath-volume.yaml
apiVersion: v1
kind: Pod
metadata:
name: hostpath-demo
spec:
containers:
- name: app
image: busybox:latest
command: ['sh', '-c', 'echo "Host data" >> /host-data/file.txt && sleep 3600']
volumeMounts:
- name: host-data
mountPath: /host-data
volumes:
- name: host-data
hostPath:
path: /tmp/host-data
type: DirectoryOrCreate
Pod Health Checks and Probes
Types of Probes
# health-checks.yaml
apiVersion: v1
kind: Pod
metadata:
name: health-check-demo
spec:
containers:
- name: webapp
image: myapp:latest
ports:
- containerPort: 8080
# Liveness probe - checks if container is alive
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
# Readiness probe - checks if container is ready to serve traffic
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
timeoutSeconds: 3
successThreshold: 1
# Startup probe - checks if application has started
startupProbe:
httpGet:
path: /startup
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 30
Probe Configuration Options
# Different probe types
livenessProbe:
# HTTP probe
httpGet:
path: /health
port: 8080
httpHeaders:
- name: X-Custom-Header
value: health-check
# OR TCP probe
tcpSocket:
port: 8080
# OR Exec probe
exec:
command:
- cat
- /tmp/healthy
# Common timing parameters
initialDelaySeconds: 30 # Wait before first probe
periodSeconds: 10 # How often to probe
timeoutSeconds: 5 # Timeout for each probe
successThreshold: 1 # Minimum consecutive successes
failureThreshold: 3 # Minimum consecutive failures
Pod Resource Management
Resource Requests and Limits
# resource-management.yaml
apiVersion: v1
kind: Pod
metadata:
name: resource-demo
spec:
containers:
- name: app
image: myapp:latest
resources:
requests:
memory: "256Mi" # Minimum guaranteed memory
cpu: "250m" # Minimum guaranteed CPU (250 millicores)
ephemeral-storage: "1Gi" # Storage requests
limits:
memory: "512Mi" # Maximum allowed memory
cpu: "500m" # Maximum allowed CPU
ephemeral-storage: "2Gi" # Storage limits
Quality of Service Classes
# Check QoS class
kubectl get pod resource-demo -o jsonpath='{.status.qosClass}'
# Output: Guaranteed, Burstable, or BestEffort
QoS Classes:
- Guaranteed: Both requests and limits set, and theyβre equal
- Burstable: Requests set, limits may be higher or unset
- BestEffort: No requests or limits set
Pod Scheduling and Node Selection
Node Selection
# node-selection.yaml
apiVersion: v1
kind: Pod
metadata:
name: node-selection-demo
spec:
# Node selector - simple node selection
nodeSelector:
disktype: ssd
zone: us-west-1a
containers:
- name: app
image: myapp:latest
Node Affinity
# node-affinity.yaml
apiVersion: v1
kind: Pod
metadata:
name: node-affinity-demo
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/arch
operator: In
values:
- amd64
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: disk-type
operator: In
values:
- ssd
containers:
- name: app
image: myapp:latest
Pod Affinity and Anti-Affinity
# pod-affinity.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-affinity-demo
spec:
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- webapp
topologyKey: kubernetes.io/hostname
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- database
topologyKey: kubernetes.io/hostname
containers:
- name: app
image: myapp:latest
Pod Disruption and Availability
Pod Disruption Budgets
# pdb.yaml
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: myapp-pdb
spec:
minAvailable: 2 # Minimum pods that must be available
# maxUnavailable: 1 # Alternative: maximum pods that can be unavailable
selector:
matchLabels:
app: myapp
Priority and Preemption
# priority-class.yaml
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: high-priority
value: 1000
globalDefault: false
description: "High priority class for critical pods"
# pod-with-priority.yaml
apiVersion: v1
kind: Pod
metadata:
name: high-priority-pod
spec:
priorityClassName: high-priority
containers:
- name: app
image: myapp:latest
Pod Troubleshooting
Common Issues and Solutions
# Pod stuck in Pending
kubectl describe pod <pod-name>
# Check events for scheduling issues
# Pod stuck in CrashLoopBackOff
kubectl logs <pod-name> --previous
# Check previous container logs
# Pod not ready
kubectl get pod <pod-name> -o yaml | grep -A 10 conditions
# Check readiness conditions
# Resource issues
kubectl top pod <pod-name>
# Check resource usage
# Network issues
kubectl exec -it <pod-name> -- nslookup kubernetes.default
# Test DNS resolution
Debugging Commands
# Get detailed pod information
kubectl get pod <pod-name> -o yaml
# Check events
kubectl get events --field-selector involvedObject.name=<pod-name>
# Access pod for debugging
kubectl exec -it <pod-name> -- /bin/bash
# Copy files from pod
kubectl cp <pod-name>:/path/to/file /local/path
# Port forward for testing
kubectl port-forward pod/<pod-name> 8080:80
# Run debugging pod
kubectl run debug --image=busybox --rm -it -- /bin/sh
Best Practices for Pods
1. Always Use Health Checks
livenessProbe:
httpGet:
path: /health
port: 8080
readinessProbe:
httpGet:
path: /ready
port: 8080
2. Set Resource Requests and Limits
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
3. Use Labels Consistently
metadata:
labels:
app: myapp
version: v1.0
environment: production
team: backend
4. Handle Graceful Shutdown
spec:
terminationGracePeriodSeconds: 30
containers:
- name: app
lifecycle:
preStop:
exec:
command: ["/bin/sh", "-c", "sleep 10 && nginx -s quit"]
5. Use Namespaces for Organization
kubectl create namespace production
kubectl config set-context --current --namespace=production
6. Use Init Containers for Setup
initContainers:
- name: setup
image: busybox:latest
command: ['sh', '-c', 'until nc -z database 5432; do sleep 1; done']
7. Configure Proper Restart Policies
spec:
restartPolicy: Always # Options: Always, OnFailure, Never
Key Takeaways
- Pods are the smallest deployable units in Kubernetes
- Multi-container pods share network, storage, and lifecycle
- Init containers run before main containers for setup tasks
- Health probes ensure application availability and correctness
- Resource management prevents resource contention and ensures QoS
- Scheduling controls determine where pods run in the cluster
- Volume types provide various storage options for different use cases
Command Reference Cheatsheet
# Pod Management
kubectl get pods # List pods
kubectl get pods --all-namespaces # List all pods
kubectl get pod <name> -o wide # Detailed pod info
kubectl describe pod <name> # Pod details and events
kubectl create -f pod.yaml # Create from YAML
kubectl apply -f pod.yaml # Apply/update from YAML
kubectl delete pod <name> # Delete pod
kubectl delete -f pod.yaml # Delete from YAML file
# Pod Operations
kubectl logs <pod-name> # View logs
kubectl logs -f <pod-name> # Follow logs
kubectl logs <pod-name> -c <container> # Specific container logs
kubectl logs <pod-name> --previous # Previous container logs
kubectl exec -it <pod-name> -- /bin/bash # Execute command
kubectl exec -it <pod-name> -c <container> -- bash # Specific container
kubectl cp <pod-name>:/remote/path /local/path # Copy from pod
kubectl cp /local/path <pod-name>:/remote/path # Copy to pod
kubectl port-forward pod/<name> 8080:80 # Port forward
kubectl attach -it <pod-name> # Attach to main process
# Pod Information
kubectl get pod <name> -o yaml # YAML output
kubectl get pod <name> -o json # JSON output
kubectl get pods --show-labels # Show labels
kubectl get pods --field-selector status.phase=Running # Filter by phase
kubectl get pods --sort-by=.metadata.creationTimestamp # Sort by creation time
# Health and Status
kubectl get events --field-selector involvedObject.name=<pod-name> # Events
kubectl top pod <name> # Resource usage
kubectl get pod <name> -o jsonpath='{.status.phase}' # Pod phase
kubectl get pod <name> -o jsonpath='{.status.podIP}' # Pod IP
kubectl get pod <name> -o jsonpath='{.spec.nodeName}' # Node name
# Labels and Annotations
kubectl label pod <name> app=myapp # Add label
kubectl label pod <name> app- # Remove label
kubectl annotate pod <name> description="My app" # Add annotation
kubectl get pods -l app=myapp # Filter by label
kubectl get pods --show-labels # Show all labels
Next Steps
Now that you understand pods, the basic building blocks of Kubernetes, youβre ready to explore Deployments in the next post. Weβll learn how to manage application lifecycle, perform rolling updates, and ensure high availability at scale.
Resources for Further Learning
- Official Kubernetes Pod Documentation
- Pod Lifecycle Guide
- Multi-Container Patterns
- Container Probes Best Practices
Series Navigation:
- Previous: C is for Containers: Docker Fundamentals
- Next: D is for Deployments: Managing Application Lifecycle
Complete Series: Kubernetes A-to-Z Series Overview