# Kubernetes Init Containers

## **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
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1740900322258/e95dd1c4-6da9-4656-9b00-038a35e07dee.png align="center")

## 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.

```yaml
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:

```yaml
kubectl apply -f web-app.yaml
```

Check the pod status:

```yaml
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
        

```yaml
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://kubernetes.io/docs/concepts/workloads/pods/init-containers/)

[https://www.loft.sh/blog/kubernetes-init-containers](https://www.loft.sh/blog/kubernetes-init-containers)

[https://www.alibabacloud.com/blog/kubernetes-init-containers\_594725](https://www.alibabacloud.com/blog/kubernetes-init-containers_594725)
