Lesson: Sidecars & Init Containers
What you'll learn
- Why some Pods hold more than one container, and what those containers share.
- The sidecar pattern: a helper container that supports the main one.
- Init containers: setup steps that must finish before the app starts.
- How containers in a Pod talk over localhost and a shared volume.
Skill gained: you can compose multi-container Pods for setup and helper tasks.
The lesson
Most Pods run a single container. But a Pod can hold several, and they get special powers because they share the same environment. This lesson shows the two patterns you will actually use: sidecars and init containers.
1. What containers in a Pod share
Containers in the same Pod share two things that separate containers do not:
- A network namespace — they share one IP address and can reach each other over
localhost. If the main app listens on port 8080, a sidecar reaches it at127.0.0.1:8080. - Volumes — any volume defined on the Pod can be mounted into multiple containers, so they read and write the same files.
Pod (one IP: 10.x.x.x)
+---------------------------------------+
| shared volume: /data |
| ^ ^ |
| | | |
| +--------+ +---------+ |
| | app |<------>| sidecar | |
| | :8080 | local | :9090 | |
| +--------+ host +---------+ |
+---------------------------------------+
2. The sidecar pattern
A sidecar is a second container that runs alongside the main app to support it — without changing the app's own code. Common jobs:
- ship the app's logs somewhere,
- refresh a config or certificate file,
- proxy network traffic.
Here a simple writer app produces lines into a shared volume, and a sidecar reads and prints them:
apiVersion: v1
kind: Pod
metadata:
name: app-with-sidecar
spec:
volumes:
- name: shared
emptyDir: {} # scratch space that lives as long as the Pod
containers:
- name: app
image: busybox:1.36
command: ["sh", "-c", "while true; do echo \"$(date) hello\" >> /data/app.log; sleep 5; done"]
volumeMounts:
- name: shared
mountPath: /data
- name: log-shipper
image: busybox:1.36
command: ["sh", "-c", "tail -F /data/app.log"]
volumeMounts:
- name: shared
mountPath: /data
The emptyDir volume is created empty when the Pod starts and is shared by both containers. The app writes to /data/app.log; the sidecar tails the same file.
kubectl apply -f sidecar.yaml
kubectl logs app-with-sidecar -c log-shipper # -c selects which container
Note -c <container> — with multiple containers you must say which one's logs you want, or which one to exec into.
3. Init containers
An init container runs to completion before the app containers start. The Pod will not start its main containers until every init container has exited successfully, in order. Use them for setup that must happen first:
- wait for a dependency (a database) to be reachable,
- clone config or download a file the app needs,
- set permissions on a volume.
apiVersion: v1
kind: Pod
metadata:
name: app-with-init
spec:
volumes:
- name: web
emptyDir: {}
initContainers:
- name: fetch-content
image: busybox:1.36
command: ["sh", "-c", "echo '<h1>prepared by init</h1>' > /web/index.html"]
volumeMounts:
- name: web
mountPath: /web
containers:
- name: nginx
image: nginx:1.27
volumeMounts:
- name: web
mountPath: /usr/share/nginx/html
The init container writes index.html into the shared volume; then nginx starts and serves it. If the init container fails, the Pod keeps retrying it and the app never starts — which is exactly what you want when a prerequisite is missing.
Pod startup timeline:
[ init: fetch-content ] -- exits 0 --> [ app: nginx starts ] --> running
(must succeed first)
kubectl apply -f init.yaml
kubectl get pod app-with-init # shows Init:0/1 then Running
kubectl logs app-with-init -c fetch-content
4. Init container vs sidecar — don't confuse them
Init container Sidecar
-------------- -------
runs BEFORE the app runs ALONGSIDE the app
runs to completion runs as long as the app
for setup / waiting for ongoing help (logs, proxy)
app waits for it app and it run together
A quick test: "does this need to finish before my app starts?" -> init container. "Does this need to keep running to help my app?" -> sidecar.
5. Keep it simple
Multi-container Pods are powerful but easy to overuse. Rules of thumb for the internship:
- One main app per Pod. Reach for a second container only when it genuinely shares this app's lifecycle, network, or files.
- If two things could scale independently or live on their own, they should be separate Pods (separate Deployments) talking over a Service, not crammed into one Pod.
- Use
emptyDirfor short-lived shared scratch space; use a real persistent volume (see the Storage lesson) when data must survive the Pod.
You can apply these patterns to any workload object, not just bare Pods — a Deployment's template.spec can list initContainers and multiple containers exactly the same way. Try wrapping the sidecar example above in a Deployment as practice.
Dig deeper
Search terms
kubernetes multi container podkubernetes sidecar pattern explainedkubernetes init container examplekubernetes emptyDir shared volumekubectl logs specific container -c
Check yourself
- Name the two things containers in the same Pod share.
- At what address does a sidecar reach the main app's port 8080?
- What must happen before a Pod's main containers start, when init containers are present?
- Give one good use for an init container and one for a sidecar.
- Which
kubectl logsflag selects a specific container in a multi-container Pod?
No comments to display
No comments to display