CKAD — Init Containers
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
- Init containers run sequentially — the second does not start until the first completes with exit code 0
- If an init container fails, Kubernetes restarts the Pod (all init containers run again from the beginning)
- The main containers do not start until ALL init containers complete successfully
- Init containers do not support readiness or liveness probes
- 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 →