Skip to main content

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 at 127.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.

They do not share a filesystem by default (each container has its own image filesystem). Sharing files requires a shared volume.

            Pod  (one IP: 10.x.x.x)
   +---------------------------------------+
   |  shared volume:  /data                |
   |     ^                  ^              |
   |     |                  |              |
   |  +--------+        +---------+        |
   |  |  app   |<------>| sidecar |        |
   |  | :8080  | local  | :9090   |        |
   |  +--------+ host   +---------+        |
   +---------------------------------------+

This shared environment is exactly what makes the patterns below work.

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 emptyDir for 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 pod
  • kubernetes sidecar pattern explained
  • kubernetes init container example
  • kubernetes emptyDir shared volume
  • kubectl logs specific container -c

Check yourself

  1. Name the two things containers in the same Pod share.
  2. At what address does a sidecar reach the main app's port 8080?
  3. What must happen before a Pod's main containers start, when init containers are present?
  4. Give one good use for an init container and one for a sidecar.
  5. Which kubectl logs flag selects a specific container in a multi-container Pod?