DEV Community

Cover image for 3.Init Containers in Kubernetes
Thu Kha Kyawe
Thu Kha Kyawe

Posted on

3.Init Containers in Kubernetes

Lab Information

There are some applications that need to be deployed on Kubernetes cluster and these apps have some pre-requisites where some configurations need to be changed before deploying the app container. Some of these changes cannot be made inside the images so the DevOps team has come up with a solution to use init containers to perform these tasks during deployment. Below is a sample scenario that the team is going to test first.

Create a Deployment named as ic-deploy-devops.

Configure spec as replicas should be 1, labels app should be ic-devops, template's metadata lables app should be the same ic-devops.

The initContainers should be named as ic-msg-devops, use image fedora with latest tag and use command '/bin/bash', '-c' and 'echo Init Done - Welcome to xFusionCorp Industries > /ic/blog'. The volume mount should be named as ic-volume-devops and mount path should be /ic.

Main container should be named as ic-main-devops, use image fedora with latest tag and use command '/bin/bash', '-c' and 'while true; do cat /ic/blog; sleep 5; done'. The volume mount should be named as ic-volume-devops and mount path should be /ic.

Volume to be named as ic-volume-devops and it should be an emptyDir type.
Enter fullscreen mode Exit fullscreen mode

Note: The kubectl utility on jump_host has been configured to work with the kubernetes cluster.


Lab Solutions

Step 1: Create the Deployment YAML File

Create a file named ic-deploy-devops.yaml with the following content:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: ic-deploy-devops
spec:
  replicas: 1
  selector:
    matchLabels:
      app: ic-devops
  template:
    metadata:
      labels:
        app: ic-devops
    spec:
      initContainers:
      - name: ic-msg-devops
        image: fedora:latest
        command: ['/bin/bash', '-c', 'echo Init Done - Welcome to xFusionCorp Industries > /ic/blog']
        volumeMounts:
        - name: ic-volume-devops
          mountPath: /ic
      containers:
      - name: ic-main-devops
        image: fedora:latest
        command: ['/bin/bash', '-c', 'while true; do cat /ic/blog; sleep 5; done']
        volumeMounts:
        - name: ic-volume-devops
          mountPath: /ic
      volumes:
      - name: ic-volume-devops
        emptyDir: {}
Enter fullscreen mode Exit fullscreen mode

Step 2: Apply the Deployment

Deploy the configuration to your Kubernetes cluster:

kubectl apply -f ic-deploy-devops.yaml
Enter fullscreen mode Exit fullscreen mode

Step 3: Verify the Deployment

Check if the deployment was created successfully:

kubectl get deployment ic-deploy-devops
Enter fullscreen mode Exit fullscreen mode

Step 4: Check the Pod Status

Monitor the pod creation and init container execution:

kubectl get pods -l app=ic-devops
Enter fullscreen mode Exit fullscreen mode

Step 5: Verify Init Container Execution

Check the init container logs to ensure it ran successfully:

# Get the pod name first
POD_NAME=$(kubectl get pods -l app=ic-devops -o jsonpath='{.items[0].metadata.name}')

# Check init container logs
kubectl logs $POD_NAME -c ic-msg-devops
Enter fullscreen mode Exit fullscreen mode

Step 6: Verify Main Container Operation

Check the main container logs to see the continuous output:

kubectl logs $POD_NAME -c ic-main-devops
Enter fullscreen mode Exit fullscreen mode

The main container should be printing the message every 5 seconds.

Step 7: Detailed Verification

Let's verify all components are correctly configured:

# Check the deployment details:
kubectl describe deployment ic-deploy-devops

# Check the pod details:
kubectl describe pod $POD_NAME

# Verify the volume mount:
kubectl exec $POD_NAME -c ic-main-devops -- ls -la /ic/

# Check the file content directly:
kubectl exec $POD_NAME -c ic-main-devops -- cat /ic/blog
Enter fullscreen mode Exit fullscreen mode

Output

thor@jumphost ~$ kubectl describe deployment ic-deploy-devops
Name:                   ic-deploy-devops
Namespace:              default
CreationTimestamp:      Fri, 31 Oct 2025 13:43:39 +0000
Labels:                 <none>
Annotations:            deployment.kubernetes.io/revision: 1
Selector:               app=ic-devops
Replicas:               1 desired | 1 updated | 1 total | 1 available | 0 unavailable
StrategyType:           RollingUpdate
MinReadySeconds:        0
RollingUpdateStrategy:  25% max unavailable, 25% max surge
Pod Template:
  Labels:  app=ic-devops
  Init Containers:
   ic-msg-devops:
    Image:      fedora:latest
    Port:       <none>
    Host Port:  <none>
    Command:
      /bin/bash
      -c
      echo Init Done - Welcome to xFusionCorp Industries > /ic/blog
    Environment:  <none>
    Mounts:
      /ic from ic-volume-devops (rw)
  Containers:
   ic-main-devops:
    Image:      fedora:latest
    Port:       <none>
    Host Port:  <none>
    Command:
      /bin/bash
      -c
      while true; do cat /ic/blog; sleep 5; done
    Environment:  <none>
    Mounts:
      /ic from ic-volume-devops (rw)
  Volumes:
   ic-volume-devops:
    Type:          EmptyDir (a temporary directory that shares a pod's lifetime)
    Medium:        
    SizeLimit:     <unset>
  Node-Selectors:  <none>
  Tolerations:     <none>
Conditions:
  Type           Status  Reason
  ----           ------  ------
  Available      True    MinimumReplicasAvailable
  Progressing    True    NewReplicaSetAvailable
OldReplicaSets:  <none>
NewReplicaSet:   ic-deploy-devops-68789fbb69 (1/1 replicas created)
Events:
  Type    Reason             Age    From                   Message
  ----    ------             ----   ----                   -------
  Normal  ScalingReplicaSet  3m55s  deployment-controller  Scaled up replica set ic-deploy-devops-68789fbb69 to 1
thor@jumphost ~$ kubectl describe pod $POD_NAME
Name:             ic-deploy-devops-68789fbb69-n46fh
Namespace:        default
Priority:         0
Service Account:  default
Node:             kodekloud-control-plane/172.17.0.2
Start Time:       Fri, 31 Oct 2025 13:43:39 +0000
Labels:           app=ic-devops
                  pod-template-hash=68789fbb69
Annotations:      <none>
Status:           Running
IP:               10.244.0.5
IPs:
  IP:           10.244.0.5
Controlled By:  ReplicaSet/ic-deploy-devops-68789fbb69
Init Containers:
  ic-msg-devops:
    Container ID:  containerd://fda2d6a406793fce4784b97fbd48e04fc4562a26b6153f877bedff8460ffa44e
    Image:         fedora:latest
    Image ID:      docker.io/library/fedora@sha256:aa7befe5cfd1f0e062728c16453cd1c479d4134c7b85eac00172f3025ab0d522
    Port:          <none>
    Host Port:     <none>
    Command:
      /bin/bash
      -c
      echo Init Done - Welcome to xFusionCorp Industries > /ic/blog
    State:          Terminated
      Reason:       Completed
      Exit Code:    0
      Started:      Fri, 31 Oct 2025 13:43:46 +0000
      Finished:     Fri, 31 Oct 2025 13:43:46 +0000
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /ic from ic-volume-devops (rw)
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-mqkwp (ro)
Containers:
  ic-main-devops:
    Container ID:  containerd://dbc7396b61602a895278a5ebf5eb61bc231ef702bd607c39237866dd6c5a5b5a
    Image:         fedora:latest
    Image ID:      docker.io/library/fedora@sha256:aa7befe5cfd1f0e062728c16453cd1c479d4134c7b85eac00172f3025ab0d522
    Port:          <none>
    Host Port:     <none>
    Command:
      /bin/bash
      -c
      while true; do cat /ic/blog; sleep 5; done
    State:          Running
      Started:      Fri, 31 Oct 2025 13:43:47 +0000
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /ic from ic-volume-devops (rw)
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-mqkwp (ro)
Conditions:
  Type              Status
  Initialized       True 
  Ready             True 
  ContainersReady   True 
  PodScheduled      True 
Volumes:
  ic-volume-devops:
    Type:       EmptyDir (a temporary directory that shares a pod's lifetime)
    Medium:     
    SizeLimit:  <unset>
  kube-api-access-mqkwp:
    Type:                    Projected (a volume that contains injected data from multiple sources)
    TokenExpirationSeconds:  3607
    ConfigMapName:           kube-root-ca.crt
    ConfigMapOptional:       <nil>
    DownwardAPI:             true
QoS Class:                   BestEffort
Node-Selectors:              <none>
Tolerations:                 node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
                             node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
  Type    Reason     Age    From               Message
  ----    ------     ----   ----               -------
  Normal  Scheduled  4m3s   default-scheduler  Successfully assigned default/ic-deploy-devops-68789fbb69-n46fh to kodekloud-control-plane
  Normal  Pulling    4m2s   kubelet            Pulling image "fedora:latest"
  Normal  Pulled     3m57s  kubelet            Successfully pulled image "fedora:latest" in 5.558670958s (5.558686183s including waiting)
  Normal  Created    3m57s  kubelet            Created container ic-msg-devops
  Normal  Started    3m56s  kubelet            Started container ic-msg-devops
  Normal  Pulling    3m56s  kubelet            Pulling image "fedora:latest"
  Normal  Pulled     3m55s  kubelet            Successfully pulled image "fedora:latest" in 144.822007ms (144.841997ms including waiting)
  Normal  Created    3m55s  kubelet            Created container ic-main-devops
  Normal  Started    3m55s  kubelet            Started container ic-main-devops
thor@jumphost ~$ kubectl exec $POD_NAME -c ic-main-devops -- ls -la /ic/
total 12
drwxrwxrwx 2 root root 4096 Oct 31 13:43 .
drwxr-xr-x 1 root root 4096 Oct 31 13:43 ..
-rw-r--r-- 1 root root   46 Oct 31 13:43 blog
thor@jumphost ~$ kubectl exec $POD_NAME -c ic-main-devops -- cat /ic/blog
Init Done - Welcome to xFusionCorp Industries
Enter fullscreen mode Exit fullscreen mode

Step 8: Continuous Monitoring

To see the real-time output from the main container:

kubectl logs $POD_NAME -c ic-main-devops -f
Enter fullscreen mode Exit fullscreen mode

Press Ctrl+C to exit the continuous log view.

Explanation of the Solution

Init Container (ic-msg-devops):

Runs before the main container starts

Creates a file /ic/blog with the welcome message

Uses the shared volume ic-volume-devops

Main Container (ic-main-devops):

Starts after the init container completes successfully

Reads the file created by the init container every 5 seconds

Shares the same volume mount

Volume (ic-volume-devops):

emptyDir type creates a temporary directory that survives container restarts

Shared between init container and main container

Data persists for the lifetime of the pod

Workflow:

Init container writes message to file → Init container completes → Main container starts → Main container reads file repeatedly
Enter fullscreen mode Exit fullscreen mode

Resources & Next Steps
📦 Full Code Repository: KodeKloud Learning Labs
💬 Join Discussion: DEV Community - Share your thoughts and questions
💼 Let's Connect: LinkedIn - I'd love to connect with you

Credits
• All labs are from: KodeKloud
• I sincerely appreciate your provision of these valuable resources.

Top comments (0)