Skip to main content

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 initTimeoutSeconds to prevent indefinite hanging
  • Ensure proper resource allocation to avoid termination due to limits
  • Monitor pod status for CrashLoopBackOff or Pending states

7. Debugging Init Containers

Example: Debugging with Logs

kubectl logs pod/<pod-name> -c <init-container-name>
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

  1. Check pod status: kubectl get pods
  2. Inspect init container state: kubectl describe pod/<pod-name>
  3. View logs: kubectl logs pod/<pod-name> -c <init-container-name>
  4. 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
initContainers:
- name: wait-for-db
  image: busybox
  command: ['sh', '-c', 'until nslookup mydb; do echo waiting for database; sleep 2; done']
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

Was this article helpful?