Multi-Container Pods
A comprehensive guide to running multiple containers inside a single Kubernetes Pod — the patterns, the YAML anatomy, and the exam traps. Synthesized from CKA Day 11 — Multi Container Pod Kubernetes: Sidecar vs Init Container.
Why Multi-Container Pods?
While the best practice is one container per Pod, there are legitimate cases where co-locating containers is necessary:
- Tight coupling: The auxiliary process must share the network namespace (
localhost) or filesystem with the main app - Co-scheduling guarantee: Both containers must always run on the same node
- Atomic lifecycle: The sidecar/init should be created/destroyed with the main app, not independently
Anti-pattern: Using a multi-container Pod as a substitute for a Deployment. If containers don’t need to share a network namespace or volume, they should be separate Pods (possibly in the same Deployment). Source: CKA Day 11
Shared Resources
Containers in the same Pod share:
| Resource | Implication |
|---|---|
| Network namespace | Same IP address, port space, and localhost. Containers can reach each other via localhost:<port> |
| Storage volumes | Volumes mounted in the Pod spec are accessible to all containers that mount them |
| IPC namespace | Optional shared memory and Unix domain sockets (set shareProcessNamespace: true) |
| UTS namespace | Same hostname |
Security note: Because containers share the network namespace, a compromised sidecar can sniff traffic bound for the main app. Use NetworkPolicies to restrict east-west traffic even within the same Pod when possible. Source: CKA Day 11
Container Roles
There are three distinct container roles inside a Pod:
| Role | Section in YAML | Lifecycle | Use Case |
|---|---|---|---|
| Init Container | spec.initContainers | Runs to completion before main containers start | Setup, validation, migration |
| Main Container | spec.containers | Long-running primary workload | Application server, database, worker |
| Sidecar Container | spec.containers | Long-running auxiliary workload | Logging, monitoring, proxy, config reloader |
Multi-Container Pod YAML Anatomy
apiVersion: v1
kind: Pod
metadata:
name: multi-container-demo
labels:
app: web
spec:
initContainers:
- name: init-permissions
image: busybox:1.36
command: ['sh', '-c', 'chmod 755 /shared']
volumeMounts:
- name: shared-data
mountPath: /shared
containers:
- name: nginx
image: nginx:alpine
ports:
- containerPort: 80
volumeMounts:
- name: shared-data
mountPath: /shared
- name: log-processor
image: fluentd:latest
volumeMounts:
- name: shared-data
mountPath: /shared
volumes:
- name: shared-data
emptyDir: {}Key ordering rules:
- All
initContainersrun in the order defined, one at a time - Only when all init containers succeed do the
containersstart - All
containersrun concurrently
Common Multi-Container Patterns
Sidecar (Logging/Monitoring)
The sidecar reads logs or metrics from a shared volume and forwards them to a central system.
containers:
- name: app
image: my-app
volumeMounts:
- name: logs
mountPath: /var/log/app
- name: log-shipper
image: fluentd
volumeMounts:
- name: logs
mountPath: /var/log/app
volumes:
- name: logs
emptyDir: {}Adapter (Output Transformation)
Transform the main app’s output into a format expected by downstream consumers.
containers:
- name: nginx
image: nginx
- name: nginx-exporter
image: nginx/nginx-prometheus-exporter
args: ["-nginx.scrape-uri", "http://localhost:8080/stub_status"]Ambassador (Proxy/Connection Pooling)
Proxy external connections so the main app thinks it’s talking to a local service.
containers:
- name: app
image: my-app
- name: redis-proxy
image: twemproxyTroubleshooting Multi-Container Pods
| Symptom | Diagnosis | Command |
|---|---|---|
Pod stuck Pending | Init container hasn’t finished | kubectl describe pod <name> |
Pod Init:Error | Init container failed | kubectl logs <pod> -c <init-container> |
CrashLoopBackOff | Main container exits repeatedly | kubectl logs <pod> -c <main-container> |
| Sidecar not working | Volume path mismatch | kubectl exec -it <pod> -c <sidecar> -- ls <mountPath> |
| OOMKilled | Memory limit too low | kubectl describe pod <pod> → check Last State |
CKA Exam Speed Patterns
# Create a multi-container Pod quickly
kubectl run multi --image=nginx --dry-run=client -o yaml > pod.yaml
# Then edit the YAML to add the second container and init container
# Get logs from a specific container
kubectl logs my-pod -c sidecar
# Execute into a specific container
kubectl exec -it my-pod -c main -- /bin/sh
# Check init container status
kubectl get pod my-pod -o jsonpath='{.status.initContainerStatuses}'Related Pages
- Init Containers — initialization workflows, ordering, and debugging
- Sidecar Pattern — architecture and use cases for auxiliary containers
- Pod Fundamentals — single-container Pod basics and lifecycle
- Kubernetes Environment Variables — configuration injection into multi-container Pods
- Pod Commands and Arguments — overriding container defaults
- Deployment, ReplicaSet & Replication Controller — controllers that manage multi-container Pod replicas
- Kubernetes Namespaces — isolating multi-container workloads
- CKA Certification — exam relevance and domains
- CKA Study Roadmap — Day 11 in the 40-day plan
Tags: kubernetes pod multi-container sidecar init-container cka devops patterns