Interactive guide based on Lab 21. Explore ordered startup, dependency checks, shared volumes, multi-stage initialization, and failure handling before the main app container starts.
Init containers are specialized containers that run to completion before the regular application containers in a Pod are allowed to start.
k8s/labs/workloads/init2-container.yaml — Pod with multiple init containers and a main app container for ordered startup labs.| Feature | Init Container | Sidecar Container |
|---|---|---|
| When it runs | Before main containers | Alongside main containers |
| Lifecycle | Runs once and exits | Runs continuously |
| Execution order | Sequential | Parallel |
| Purpose | Setup and initialization | Support and monitoring |
| Failure impact | Pod startup is blocked | Pod may still continue |
Use `getent hosts`, `nslookup`, or similar checks so the app does not start before required services are available.
Init writes files to `emptyDir`; the main container later reads those files from the same volume.
Model startup as a series of smaller, auditable, ordered steps rather than one large boot script.
Click a stage to inspect what Kubernetes is doing at that point.
Kubernetes accepts the Pod and schedules it. Because init containers exist, the regular application container cannot start yet.
Step through the most important scenarios from `lab10-pod-init-containers.md`.
Only one init container can run at a time. Later stages wait until earlier ones complete successfully.
Init containers let you separate setup work from your application image and make the Pod's startup behavior easier to explain and debug.
Focused reference snippets from the markdown lab manual.
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
spec:
initContainers:
- name: init-myservice
image: registry.access.redhat.com/ubi8/ubi:latest
command: ['sh', '-c', 'until getent hosts myservice; do echo waiting for myservice; sleep 2; done;']
- name: init-mydb
image: registry.access.redhat.com/ubi8/ubi:latest
command: ['sh', '-c', 'until getent hosts mydb; do echo waiting for mydb; sleep 2; done;']
containers:
- name: myapp-container
image: registry.access.redhat.com/ubi8/ubi:latest
command: ['sh', '-c', 'echo The app is running! && sleep 3600']
kubectl apply -f init2-container.yaml kubectl get pod myapp-pod kubectl describe pod myapp-pod kubectl logs myapp-pod -c init-myservice kubectl logs myapp-pod -c init-mydb -f
initContainers:
- name: install-config
image: busybox
volumeMounts:
- name: workdir
mountPath: /work-dir
containers:
- name: main-app
image: busybox
volumeMounts:
- name: workdir
mountPath: /config
volumes:
- name: workdir
emptyDir: {}
apiVersion: v1
kind: Pod
metadata:
name: failing-init-pod
spec:
initContainers:
- name: init-success
image: busybox
command: ['sh', '-c', 'echo "Init 1 succeeded"; exit 0']
- name: init-failure
image: busybox
command: ['sh', '-c', 'echo "Init 2 failed"; exit 1']
containers:
- name: main-container
image: busybox
command: ['sh', '-c', 'echo "Main container running"; sleep 3600']
restartPolicy: Never
initContainers:
- name: wait-for-db
image: busybox
- name: run-migrations
image: busybox
volumeMounts:
- name: migration-status
mountPath: /migrations
containers:
- name: webapp
image: busybox
volumeMounts:
- name: migration-status
mountPath: /migrations
volumes:
- name: migration-status
emptyDir: {}
kubectl logs webapp-with-migration -c wait-for-db kubectl logs webapp-with-migration -c run-migrations kubectl logs webapp-with-migration
One init container per concern makes startup easier to understand and troubleshoot.
Use `emptyDir` when init needs to hand off generated files or status data to the app container.
When a Pod is stuck in `Init:*`, clear logs are usually the fastest way to find the bottleneck.
Readiness, liveness, and startup probes are not supported for init containers.
kubectl logs <pod> -c <init-container>
kubectl logs <pod> -c <init-container> -f
kubectl describe pod <pod>
kubectl get pod <pod> -w
kubectl get pod <pod> -o jsonpath='{.spec.initContainers[*].name}'
kubectl get pod <pod> -o jsonpath='{.status.initContainerStatuses[*].state}'