4.05 Multi Container Pods
Multi-container Pods allow multiple containers to run inside a single Kubernetes Pod when they must be tightly coupled and operate together.
Instead of merging everything into one large container image, Kubernetes lets you package helper components alongside the main application container.
Typical real-world examples:
- App + reverse proxy
- App + log shipper
- App + metrics exporter
- App + config reloader
- App + dependency checker
- App + service mesh proxy
π― What Makes Multi-Container Pods Special
Containers inside the same Pod share:
- β Lifecycle (start and stop together)
- β
Network namespace (same IP, use
localhost) - β Storage volumes
- β Scheduling & node placement
- β Restart behavior
Success
Multi-container Pods are meant for tightly coupled helper containers, not unrelated services.
π§ When You SHOULD Use Multi-Container Pods
Use multi-container Pods when containers must:
- Always run together
- Scale together
- Share files directly
- Communicate via localhost
- Be deployed as one unit
Warning
If components can scale independently β use separate Deployments, not one Pod.
π§± Basic Multi-Container Pod Example
The containers field is a list β this allows multiple containers in one Pod.
apiVersion: v1
kind: Pod
metadata:
name: simple-webapp
spec:
containers:
- name: web-app
image: web-app
ports:
- containerPort: 8080
- name: main-app
image: main-app
Behavior:
- Both containers start together
- Both run together
- Both stop together
- No startup order guarantee
Note
Kubernetes does not guarantee which container starts first in this pattern.
π§© Multi-Container Pod Design Patterns
There are three core patterns you must know:
- CoβLocated Containers
- Init Containers
- Sidecar Containers
1οΈβ£ CoβLocated Containers Pattern
Two or more containers:
- Run for full Pod lifecycle
- No guaranteed startup order
- All are long-running
Use when:
- Containers depend on each other
- No strict startup sequencing required
Note
Good for helper daemons, lightweight proxies, or tightly bound services.
2οΈβ£ Init Containers Pattern
Init containers run before main containers start.
Rules:
- Must complete successfully
- Run sequentially
- Main containers wait until init completes
Used for:
- Database readiness checks
- Schema migrations
- Config downloads
- Dependency validation
π Init Container β DB Readiness Template
apiVersion: v1
kind: Pod
metadata:
name: app-pod
spec:
initContainers:
- name: db-wait
image: busybox
command:
- sh
- -c
- >
until nc -z db-service 5432;
do echo "Waiting for DB...";
sleep 2;
done
containers:
- name: app
image: my-app
Tip
Prefer init containers over sleep loops inside your main app.
π Multiple Init Containers β Ordered Execution
Init containers run one-by-one in order:
initContainers:
- name: db-checker
image: busybox
command: ["sh","-c","./wait-for-db.sh"]
- name: api-checker
image: busybox
command: ["sh","-c","./wait-for-api.sh"]
Execution order:
3οΈβ£ Sidecar Containers Pattern
Sidecar containers:
- Run alongside main container
- Support main container
- Run for full Pod lifecycle
- Provide helper capabilities
Used for:
- Log shipping
- Metrics exporting
- Security monitoring
- Config reloaders
- Service mesh proxies
Success
Sidecars extend app behavior without modifying app code.
π§± Sidecar Pattern β Logging Example
A common production use case:
App + Log Shipper Sidecar
Flow:
This ensures:
- Startup logs captured
- Runtime logs streamed
- Crash/termination logs preserved
βοΈ Sidecar Pattern YAML
apiVersion: v1
kind: Pod
metadata:
name: simple-webapp
labels:
name: simple-webapp
spec:
containers:
- name: web-app
image: web-app
ports:
- containerPort: 8080
initContainers:
- name: log-shipper
image: busybox
command: 'setup-log-shipper.sh'
restartPolicy: Always
π About restartPolicy
-
restartPolicyset to always for Sidecar Pattern in Init Containers. So this will also ensure the init container is terminated after the main application stops. -
That way the log shipper can catch the startup and termination logs of the main container.
Valid restartPolicy values:
- Always
- OnFailure
- Never
π§ Sidecar vs Init Container β Difference
| Feature | Init Container | Sidecar Container |
|---|---|---|
| Runs before app | β | β |
| Stops before app starts | β | β |
| Runs during app lifecycle | β | β |
| Used for | Setup / checks | Continuous support |
Note
Init containers execute setup tasks and terminate, while sidecars provide continuous support services and run as long as the Pod is running.
π Production Use Cases
- Log shippers (Fluent Bit, Filebeat)
- Metrics exporters
- Security agents
- Service mesh proxies (Envoy)
- Config reload helpers
π§ͺ Troubleshooting Multi-Container Pods
Always debug per-container.
Describe Pod
Logs per container
Exec into specific container
kubectl -n elastic-stack exec -it app -- cat /log/app.log
# Pod Name: app
# Command to execute: cat /log/app.log
Tip
Most βPod failuresβ are actually one container failing.
π Production Best Practices
Success
Keep each container single-purpose
Success
Use init containers for readiness logic
Success
Use sidecars for logging & metrics
Success
Define resource limits per container
Success
Add readiness & liveness probes
Success
Use shared volumes carefully
β Production Donβts
Danger
Do not group unrelated services
Danger
Do not assume container start order
Danger
Do not put business logic in sidecars
Danger
Do not skip health probes