A standard Kubernetes Pod is designed to host one or more application containers running concurrently for the life of the Pod. However, applications often require initialization steps—such as configuring environment files, running database migrations, or waiting for helper services to be online—before the main application container starts.
Kubernetes addresses this pre-requisite requirement using Init Containers. An Init Container is a specialized container that runs to completion before any app containers start.
sequenceDiagram
autonumber
participant K8s as Kubernetes API
participant Init as Init Container: ic-msg-xfusion
participant Shared as Shared Volume: ic-volume-xfusion
participant Main as App Container: ic-main-xfusion
K8s->>Init: Starts container
Init->>Shared: Writes 'Init Done...' to /ic/beta
Init->>K8s: Exits successfully (code 0)
Note over Init: Container terminates
K8s->>Main: Starts container
Main->>Shared: Reads /ic/beta in infinite loop
Main->>Main: Output contents to stdout
Init Containers are defined inside the Pod specification under the initContainers array, parallel to the containers array.
Unlike application containers that start in parallel, if a Pod has multiple Init Containers, they run sequentially, one by one. Each Init Container must exit successfully (with exit code 0) before the next one starts.
If an Init Container fails, Kubernetes restarts the entire Pod repeatedly until the Init Container succeeds. However, if the Pod’s restartPolicy is set to Never and an Init Container fails, the Pod status immediately transitions to Failed and execution stops.
Init Containers do not support liveness, readiness, or startup probes. Because they are designed to run to completion and terminate, they do not remain active to be probed.
A Pod cannot transition into the Ready status (and therefore cannot receive traffic from a Service) until all Init Containers have successfully terminated and the main application containers are running and report ready.
Kubernetes schedules Pods based on their resource requirements. For a Pod with Init Containers, the resource requests and limits are calculated using the following formulas:
\[\text{Pod Request} = \max\left(\max(\text{Init Container Requests}), \sum(\text{App Container Requests})\right)\] \[\text{Pod Limit} = \max\left(\max(\text{Init Container Limits}), \sum(\text{App Container Limits})\right)\]Why? Since Init Containers run sequentially and terminate before the application containers start, they never consume resources at the same time as the application containers. Therefore, the scheduler only needs to allocate enough resources for the heaviest initialization phase, or the sum of all concurrently running application containers (whichever is larger).
thordefaultic-deploy-xfusion1ic-volume-xfusionemptyDir/icic-msg-xfusionubuntu:latest["/bin/bash", "-c", "echo Init Done - Welcome to xFusionCorp Industries > /ic/beta"]ic-main-xfusionubuntu:latest["/bin/bash", "-c", "while true; do cat /ic/beta; sleep 5; done"]SSH from your administrator terminal:
ssh thor@jump_host_ip
Create a file named ic-deploy.yaml declaring the Deployment, the shared volume, the initContainers block, and the containers block:
apiVersion: apps/v1
kind: Deployment
metadata:
name: ic-deploy-xfusion
labels:
app: ic-app
spec:
replicas: 1
selector:
matchLabels:
app: ic-app
template:
metadata:
labels:
app: ic-app
spec:
volumes:
- name: ic-volume-xfusion
emptyDir: {}
initContainers:
- name: ic-msg-xfusion
image: ubuntu:latest
command: ["/bin/bash", "-c", "echo Init Done - Welcome to xFusionCorp Industries > /ic/beta"]
volumeMounts:
- name: ic-volume-xfusion
mountPath: /ic
containers:
- name: ic-main-xfusion
image: ubuntu:latest
command: ["/bin/bash", "-c", "while true; do cat /ic/beta; sleep 5; done"]
volumeMounts:
- name: ic-volume-xfusion
mountPath: /ic
Apply the configuration:
kubectl apply -f ic-deploy.yaml
Expected Output:
deployment.apps/ic-deploy-xfusion created
Observe the Pod startup states in real-time. You will watch it transition through initialization phases:
kubectl get pods -w -l app=ic-app
Expected Output Transition:
NAME READY STATUS RESTARTS AGE
ic-deploy-xfusion-7f8a9b0c-abcde 0/1 Pending 0 0s
ic-deploy-xfusion-7f8a9b0c-abcde 0/1 Init:0/1 0 2s
ic-deploy-xfusion-7f8a9b0c-abcde 0/1 PodInitializing 0 5s
ic-deploy-xfusion-7f8a9b0c-abcde 1/1 Running 0 7s
Note:
Init:0/1 means 0 out of 1 Init Containers have completed successfully.PodInitializing indicates that the Init Container completed successfully with exit code 0, and the main container is now starting up.Query the logs of the ic-main-xfusion container to verify that the file written by the Init Container is successfully read:
# Get the generated Pod name
POD_NAME=$(kubectl get pods -l app=ic-app -o jsonpath='{.items[0].metadata.name}')
# View logs from the app container
kubectl logs $POD_NAME -c ic-main-xfusion
Expected Output repeating every 5 seconds:
Init Done - Welcome to xFusionCorp Industries
Init Done - Welcome to xFusionCorp Industries
Exec directly into the running application container and inspect the /ic/beta file:
kubectl exec -it $POD_NAME -c ic-main-xfusion -- cat /ic/beta
Expected Output:
Init Done - Welcome to xFusionCorp Industries
This confirms the Init Container successfully terminated and passed the setup details to the application container via the shared volume!