CKAD — Init Containers

3 minute read

What Are Init Containers?

Init containers run before the main application containers start. They run to completion, one at a time, in order. If an init container fails, Kubernetes restarts the Pod (subject to restart policy).

Init containers are defined in spec.initContainers — separate from spec.containers.

Common Use Cases

Use Case What the Init Container Does
Wait for a dependency Polls until a database or API is available
Download configuration Fetches config files before the app starts
Run database migrations Applies schema changes before the app connects
Set up file permissions Creates directories or adjusts ownership
Seed data Pre-populates a shared volume with required data

How Init Containers Work

  1. Init containers run sequentially — the second does not start until the first completes with exit code 0
  2. If an init container fails, Kubernetes restarts the Pod (all init containers run again from the beginning)
  3. The main containers do not start until ALL init containers complete successfully
  4. Init containers do not support readiness or liveness probes
  5. Init containers can use different images from the main containers

Example: Wait for a Service

apiVersion: v1
kind: Pod
metadata:
  name: web-app
spec:
  initContainers:
  - name: wait-for-db
    image: busybox:1.36
    command: ['sh', '-c']
    args:
    - |
      echo "Waiting for database..."
      until nslookup db-service.default.svc.cluster.local; do
        echo "DB not ready, retrying in 2s..."
        sleep 2
      done
      echo "Database is ready!"

  containers:
  - name: app
    image: nginx:1.27
    ports:
    - containerPort: 80

The init container keeps checking if db-service exists in DNS. The main app container only starts after the init container succeeds.

Example: Download Config Before App Starts

apiVersion: v1
kind: Pod
metadata:
  name: config-app
spec:
  initContainers:
  - name: download-config
    image: busybox:1.36
    command: ['sh', '-c']
    args:
    - |
      echo '{"database": "postgres://db:5432", "cache": "redis://cache:6379"}' > /config/app.json
      echo "Config downloaded"
    volumeMounts:
    - name: config-vol
      mountPath: /config

  containers:
  - name: app
    image: nginx:1.27
    volumeMounts:
    - name: config-vol
      mountPath: /etc/app
      readOnly: true

  volumes:
  - name: config-vol
    emptyDir: {}
kubectl apply -f config-app.yaml

# Verify the config was created
kubectl exec config-app -- cat /etc/app/app.json
# Expected: {"database": "postgres://db:5432", "cache": "redis://cache:6379"}

Multiple Init Containers

Init containers run sequentially — the second one does not start until the first completes successfully.

apiVersion: v1
kind: Pod
metadata:
  name: multi-init
spec:
  initContainers:
  - name: init-step-1
    image: busybox:1.36
    command: ['sh', '-c', 'echo "Step 1: Check network" && sleep 2']
  - name: init-step-2
    image: busybox:1.36
    command: ['sh', '-c', 'echo "Step 2: Download config" && sleep 2']
  - name: init-step-3
    image: busybox:1.36
    command: ['sh', '-c', 'echo "Step 3: Run migrations" && sleep 2']
  containers:
  - name: app
    image: nginx:1.27
kubectl apply -f multi-init.yaml

# Watch the init process
kubectl get pod multi-init -w
# Expected progression:
# NAME         READY   STATUS     RESTARTS   AGE
# multi-init   0/1     Init:0/3   0          1s
# multi-init   0/1     Init:1/3   0          3s
# multi-init   0/1     Init:2/3   0          5s
# multi-init   1/1     Running    0          7s

Init Container Failure Behavior

Scenario Behavior
Init container exits with code 0 Next init container starts (or main containers if last)
Init container exits with code 1 Pod restarts (all init containers re-run from scratch)
Init container hangs (never exits) Pod stays in Init:N/M state indefinitely
restartPolicy: Never with failed init Pod moves to Failed state (no retry)

Debugging Init Containers

# Check which init container is running or failed
kubectl describe pod <name> | grep -A 15 "Init Containers"

# View init container logs
kubectl logs <name> -c <init-container-name>

# Check Pod events for init failures
kubectl describe pod <name> | tail -20

Init Containers vs Main Containers

Feature Init Containers Main Containers
Defined in spec.initContainers spec.containers
Run order Sequential Parallel (all start together)
Must complete Yes (exit code 0) No (long-running)
Probes Not supported Liveness, readiness, startup
Restart on failure Entire Pod restarts Only the failed container restarts
Lifecycle Runs once, then done Runs for Pod lifetime
Shared volumes Yes Yes
Network access Yes (same Pod network) Yes (same Pod network)

Exam tip: Init containers are one of the most commonly tested multi-container patterns on the CKAD exam. Practice creating Pods with init containers that wait for services or set up configuration.


Next: Learn about proxy containers with Ambassador Pattern →

Updated: