Kubernetes Init Containers

Sushil TiwariSushil Tiwari
4 min read

What is an Init Container?

As Kubernetes pods can have more than one container.
Init containers are specialized containers that run before app containers in a Kubernetes Pod. Unlike regular containers, init containers must complete successfully before the main application containers can start. This sequential execution pattern makes them perfect for setup tasks.

Why Use Init Containers?

  1. Separating initialization logic from application code

  2. Delaying application startup until dependencies are ready

  3. Running setup operations with different security contexts

  4. Pre-populating volumes with configuration or data

How Init Containers Work?

Before jumping into the example, let’s see how it works step by step.

  1. When a Pod is created, the kubelet initializes all volumes and networks

  2. Kubelet starts init containers sequentially in the order defined in Pod spec

  3. Each init container must terminate completely before the next one starts

  4. The kubelet waits for each init container to have exit code 0 before proceeding

  5. If an init container fails, kubelet restarts it according to the Pod's restartPolicy

  6. Once all init containers complete successfully, kubelet initializes and starts all app containers simultaneously

  7. Status of init containers is exposed in the Pod's .status.initContainerStatuses field

  8. Init containers rerun completely during Pod restarts (unlike regular containers)

  9. Kubelet retains init container logs until the Pod is deleted, even after container termination

Let’s see a example: Django with PostgreSQL

In this example, Let’s start with the scenario where PostgreSQL database is ready before starting your Django application.

apiVersion: v1
kind: Pod
metadata:
  name: django
spec:
  initContainers:
  - name: wait-for-postgres
    image: postgres:13
    command: [
        'sh',
        '-c',
        'until pg_isready -h postgres-service -p 5432; do echo waiting for postgres; sleep 2; done;'
    ]

  containers:
  - name: django
    image: <Image-name>:<Tag>
    env:
    - name: DATABASE_URL
      value: "postgres://user:password@postgres-service:5432/app_db"
    ports:
    - containerPort: 8000
  - name: nginx
    image: nginx:1.21
    ports:
    - containerPort: 80
    volumeMounts:
    - name: nginx-config
      mountPath: /etc/nginx/conf.d/
  volumes:
  - name: nginx-config
    configMap:
      name: nginx-config

In this example, the init container uses pg_isready from the official PostgreSQL image to check if the database is accepting connections. The Django application and Nginx containers only start after this verification succeeds.

Let’s deploy this pod.

Save the YAML as web-app.yaml and apply it:

kubectl apply -f web-app.yaml

Check the pod status:

kubectl get pods

You’ll see the init container running first. Once it’s done, your app starts.

Resources and Volumes for Init Containers

Init containers can define resources and access volumes just like regular containers, with some important considerations:

  • Resource Requests and Limits

    • The highest resource request/limit for each resource across all init containers is used

    • The Pod's effective request/limit is the higher of the sum of app containers and the highest init container

    • This ensures init containers have enough resources without permanently reserving them

  • Volume Usage

    • Init containers can mount and modify volumes that app containers will later use

    • Volumes created by init containers are available to app containers

    • Changes made to shared volumes by init containers persist for app containers

    • Empty directories and persistent volumes can be shared across container

apiVersion: v1
kind: Pod
metadata:
  name: django
spec:
  initContainers:
  - name: wait-for-postgres
    image: postgres:13
    command: ['sh', '-c', 'pg_isready -h postgres-service && echo "DB schema initialized" > /data/status.txt']
    resources:
      limits:
        memory: "256Mi"
        cpu: "500m"
      requests:
        memory: "128Mi"
        cpu: "250m"
    volumeMounts:
    - name: shared-data
      mountPath: /data

  containers:
  - name: django
    image: <Image>:<Tag>
    resources:
      limits:
        memory: "512Mi"
        cpu: "500m"
      requests:
        memory: "256Mi"
        cpu: "250m"
    volumeMounts:
    - name: shared-data
      mountPath: /app/data

  volumes:
  - name: shared-data
    emptyDir: {}

Init container vs Sidecar container

  1. Init Container performs tasks that need to be completed before the main container can start, while Sidecar Container provides supplementary functionality to the main container.

  2. Init Container runs to completion and must succeed before the main container starts, while Sidecar Container runs continuously alongside the main container.

  3. Init Container is used for setup tasks like waiting for dependencies, fetching configs, or running migrations, while Sidecar Container is used for tasks like logging, monitoring, or proxying.

  4. Init Container always runs first in the pod lifecycle, while Sidecar Container runs concurrently with the main container.

  5. If an Init Container fails, the pod restarts it until it succeeds, while a failing Sidecar Container may or may not impact the main container depending on its role.

  6. Init Container does not run simultaneously with the main container, while Sidecar Container shares resources and runs in parallel with the main container.

So, Init containers always run to completion and each init container must complete successfully before the next one begins. If any init container fails, Kubernetes restarts the Pod repeatedly until initialization succeeds and Init containers can access secrets, while preventing app containers from having these privileges. Thank you.

References:

https://kubernetes.io/docs/concepts/workloads/pods/init-containers/

https://www.loft.sh/blog/kubernetes-init-containers

https://www.alibabacloud.com/blog/kubernetes-init-containers_594725

0
Subscribe to my newsletter

Read articles from Sushil Tiwari directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Sushil Tiwari
Sushil Tiwari