Configuring Init Containers
1. Understanding Init Container Purpose
| Aspect | Description | Use Case |
|---|---|---|
| Initialization Phase | Executed before application containers start | Setting up environment, preparing dependencies |
| Sequential Execution | Init containers run in order, each must complete successfully | Ensuring dependencies are ready before app starts |
| Shared Resources | Can access volumes and network namespace of the pod | Copying config files, setting permissions |
| Failure Handling | If any init container fails, the pod is restarted | Ensuring consistent state before app launch |
Example: Init Container Setup
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
spec:
initContainers:
- name: init-config
image: alpine:latest
command: ["sh", "-c", "echo \"Initializing config...\""]
volumeMounts:
- name: config-volume
mountPath: /etc/config
containers:
- name: app-container
image: nginx:latest
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
emptyDir: {}
Note: Init containers are ideal for preparing the runtime environment before the main application starts.
2. Defining Init Containers
| Property | Description | Values | Notes |
|---|---|---|---|
| initContainers | List of init containers | Array |
Defined in Pod spec |
| name | Unique name for init container | string |
Must be unique within Pod |
| image | Container image to use | string |
Must be valid Docker image reference |
| command | Override default entrypoint | Array<string> |
Exec form: ["/bin/sh", "-c"] |
| args | Arguments to pass to command | Array<string> |
Exec form: ["echo hello"] |
| env | Environment variables to set | Array<object> |
Each object has name and value |
| volumeMounts | Mount volumes into container | Array<object> |
Each object has name and mountPath |
Example: Basic Init Container Definition
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
initContainers:
- name: init-container-1
image: busybox:1.35
command:
- /bin/sh
- -c
- echo "Initializing..."
containers:
- name: main-container
image: nginx:latest
Example: Init Container with Volume Mount
apiVersion: v1
kind: Pod
metadata:
name: pod-with-init
spec:
initContainers:
- name: copy-config
image: alpine:latest
command:
- /bin/sh
- -c
- cp /config/app.conf /shared/config.conf
volumeMounts:
- name: config-volume
mountPath: /config
- name: shared-volume
mountPath: /shared
containers:
- name: app-container
image: nginx:latest
volumeMounts:
- name: shared-volume
mountPath: /app/config
volumes:
- name: config-volume
configMap:
name: app-config
- name: shared-volume
emptyDir: {}
3. Setting Init Container Order
Example: Defining init containers with dependencies
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
initContainers:
- name: init-db
image: busybox:1.35
command:
- sh
- -c
- 'echo "Initializing database..."'
- name: init-config
image: busybox:1.35
command:
- sh
- -c
- 'echo "Setting up configuration..."'
dependsOn:
- init-db
containers:
- name: app
image: nginx:1.25
| Property | Description | Notes |
|---|---|---|
| initContainers | List of init containers to run before the main containers | Each init container runs sequentially in order defined |
| dependsOn | Specifies dependencies between init containers | NEW in Kubernetes 1.29+ |
Note: The
dependsOn field is a new feature in Kubernetes 1.29+ that allows specifying explicit dependencies between init containers.4. Sharing Volumes with Main Containers
| Field | Description | Example |
|---|---|---|
| volumeMounts.name | Name of the volume to mount | data-volume |
| volumeMounts.mountPath | Path inside the container where volume is mounted | /app/data |
| volumeMounts.readOnly | Whether the mount is read-only | true |
Example: Mounting a Shared Volume
apiVersion: v1
kind: Pod
metadata:
name: init-pod
spec:
initContainers:
- name: init-container
image: alpine
command: ["sh", "-c", "mkdir -p /shared/data"]
volumeMounts:
- name: shared-volume
mountPath: /shared
containers:
- name: main-container
image: nginx
volumeMounts:
- name: shared-volume
mountPath: /app/data
volumes:
- name: shared-volume
emptyDir: {}
Note: The
emptyDir volume is used for sharing data between init containers and main containers. It's deleted when the pod is deleted.
5. Setting Init Container Resources
| Resource Type | Configuration | Description |
|---|---|---|
| requests.cpu | "100m" |
Minimum CPU allocation for the init container |
| requests.memory | "64Mi" |
Minimum memory allocation for the init container |
| limits.cpu | "200m" |
Maximum CPU allocation for the init container |
| limits.memory | "128Mi" |
Maximum memory allocation for the init container |
Example: Setting CPU and Memory Limits in Init Container
apiVersion: v1
kind: Pod
metadata:
name: init-container-pod
spec:
initContainers:
- name: init-container
image: busybox:1.35
resources:
requests:
memory: "64Mi"
cpu: "100m"
limits:
memory: "128Mi"
cpu: "200m"
command:
- sh
- -c
- echo "Init container running with limited resources"
containers:
- name: app-container
image: nginx:1.25
6. Handling Init Container Failures
| Failure Type | Description | Behavior | Recovery Options |
|---|---|---|---|
| Init container exits with non-zero code | Init container completes but fails with an error code | Pod remains in Pending state until resolved |
Fix container logic or image; restart pod |
| Init container hangs or times out | Container does not complete within specified timeout | Pod enters CrashLoopBackOff state |
Adjust initTimeoutSeconds or fix container logic |
| Resource limits exceeded | Init container exceeds CPU or memory limits | Container is terminated and pod restarts | Increase resource limits or optimize container |
Example: Configuring Init Container with Retry Logic
apiVersion: v1
kind: Pod
metadata:
name: init-pod-with-retry
spec:
initContainers:
- name: init-with-retry
image: busybox:1.35
command:
- /bin/sh
- -c
- |
set -e
for i in $(seq 1 5); do
echo "Attempt $i"
if [ "$i" -eq 3 ]; then
echo "Success on attempt $i"
exit 0
fi
sleep 2
done
echo "All attempts failed"
exit 1
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"
containers:
- name: main-app
image: nginx:1.25
Note: Kubernetes does not provide built-in retry logic for init containers. You must implement retry mechanisms inside the container's command or script.
Warning: If an init container fails repeatedly, the pod will remain stuck in
Pending or enter a crash loop. Ensure proper error handling and timeouts.
Key Points for Handling Failures
- Init containers do not support automatic retries; implement logic inside the container
- Use
initTimeoutSecondsto prevent indefinite hanging - Ensure proper resource allocation to avoid termination due to limits
- Monitor pod status for
CrashLoopBackOfforPendingstates
7. Debugging Init Containers
| Command | Description | Notes |
|---|---|---|
| kubectl logs | Retrieve logs from a container | Use -c to specify init container name |
| kubectl describe pod | Get detailed pod information including init container status | Shows events and phase transitions |
Note: Init containers do not support
livenessProbe or readinessProbe, so debugging must rely on logs and status inspection.Debugging Workflow
- Check pod status:
kubectl get pods - Inspect init container state:
kubectl describe pod/<pod-name> - View logs:
kubectl logs pod/<pod-name> -c <init-container-name> - Check for resource limits or errors in logs
8. Using Init Containers for Dependencies
| Property | Description | Example |
|---|---|---|
| initContainers | List of init containers to run before the main container starts | |
| image | Container image to use for the init container | busybox:1.35 |
| command | Command to run inside the init container | ['sh', '-c', 'echo initializing...'] |
Example: Waiting for a Database
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
spec:
initContainers:
- name: wait-for-db
image: busybox:1.35
command:
- sh
- -c
- |
until nslookup mydb; do
echo waiting for database...
sleep 2
done
containers:
- name: app
image: myapp:latest
ports:
- containerPort: 80
Note: Init containers run in sequence and must complete successfully before the main containers start. They are ideal for setting up dependencies like databases or configuration files.
9. Running Database Migrations
Example: Init Container for Database Migration
apiVersion: v1
kind: Pod
metadata:
name: migration-pod
spec:
initContainers:
- name: db-migrator
image: migrate:1.0
command:
- /bin/sh
- -c
- |
echo "Running database migrations..."
migrate -database postgres://user:pass@db:5432/mydb -path /migrations up
env:
- name: DATABASE_URL
value: postgres://user:pass@db:5432/mydb
volumeMounts:
- name: migrations
mountPath: /migrations
containers:
- name: app
image: myapp:latest
ports:
- containerPort: 8080
env:
- name: DATABASE_URL
value: postgres://user:pass@db:5432/mydb
volumes:
- name: migrations
configMap:
name: db-migrations
| Field | Description | Notes |
|---|---|---|
| initContainers[].name | Unique name for the init container | Must be unique within the pod |
| initContainers[].image | Container image to run for migration | Must contain migration tool (e.g., migrate, flyway) |
| initContainers[].command | Command to execute in the init container | Can be array of strings or single string |
| initContainers[].env | Environment variables for migration | Use to pass database credentials or URLs |
| initContainers[].volumeMounts | Mounts volumes into the init container | Required to access migration files or scripts |
Note: Init containers run before the main application containers and must complete successfully before the app containers start.
Warning: If the migration init container fails, the pod will not start. Ensure migrations are idempotent and safe to run multiple times.
10. Downloading Configuration Files
| Property | Description | Example |
|---|---|---|
| configMap | Reference to a ConfigMap containing configuration files | configMap: { name: "app-config" } |
| secret | Reference to a Secret containing sensitive configuration files | secret: { secretName: "app-secrets" } |
| volumeMounts | Defines where to mount the config files inside the container | volumeMounts: [{ name: "config-volume", mountPath: "/etc/config" }] |
Example: Downloading Config Files from a ConfigMap
apiVersion: v1
kind: Pod
metadata:
name: init-container-pod
spec:
initContainers:
- name: download-config
image: busybox
command:
- /bin/sh
- -c
- |
mkdir -p /config
cp /tmp/config/* /config/
volumeMounts:
- name: config-volume
mountPath: /tmp/config
containers:
- name: app-container
image: nginx
volumeMounts:
- name: config-volume
mountPath: /etc/nginx/conf.d
volumes:
- name: config-volume
configMap:
name: nginx-config
Example: Using Secret to Download Sensitive Data
apiVersion: v1
kind: Pod
metadata:
name: secret-init-pod
spec:
initContainers:
- name: copy-secrets
image: alpine
command:
- sh
- -c
- |
mkdir -p /secrets
cp /tmp/secrets/* /secrets/
volumeMounts:
- name: secret-volume
mountPath: /tmp/secrets
containers:
- name: app-container
image: alpine
command:
- sh
- -c
- |
echo "Secrets copied"
volumeMounts:
- name: secret-volume
mountPath: /etc/secrets
volumes:
- name: secret-volume
secret:
secretName: app-secrets