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:
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 quicklykubectl 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 containerkubectl logs my-pod -c sidecar# Execute into a specific containerkubectl exec -it my-pod -c main -- /bin/sh# Check init container statuskubectl get pod my-pod -o jsonpath='{.status.initContainerStatuses}'
Practical Practice
Exam-style hands-on tasks for this topic. Complete each task before reviewing the solution. Time yourself — CKA tasks average 5–7 minutes.
Task 1: Create a Two-Container Pod
You are asked to create a Pod named api-cache with two containers: api using image nginx and cache using image redis:alpine.
Requirements: Use --dry-run=client -o yaml, edit the manifest to add the second container, then apply.
Verification:kubectl get pod api-cache and kubectl describe pod api-cacheSolution:
kubectl run api-cache --image=nginx --dry-run=client -o yaml > api-cache.yaml# Edit api-cache.yaml to add the redis:alpine container in spec.containerskubectl apply -f api-cache.yaml
Task 2: Add an Init Container that Waits for a Service
You are asked to add an init container to an existing Pod secure-app that waits until a Service named db is reachable on port 5432 before the main app starts.
Requirements: The init container must use busybox:1.36 and nc -z db 5432 in a loop.
Verification:kubectl get pod secure-app transitions from Init:0/1 to Running.
Solution:
kubectl get pod secure-app -o yaml > secure-app.yaml# Add spec.initContainers with busybox waiting for db:5432kubectl apply -f secure-app.yaml --force
Task 3: Adapter Pattern Sidecar
You are asked to create a Pod where the main nginx container writes logs to /var/log/nginx/access.log, and a sidecar busybox container tails that file and prints to stdout.
Requirements: Share an emptyDir volume between both containers mounted at /var/log/nginx.
Verification:kubectl logs <pod> -c sidecar shows nginx log lines.
Solution: