Init containers are the containers that are initialized before the application container in a Pod. Init containers usually contains the setup scripts and utilities which perform a particular task so that the application container can start smoothly.
Each Init Container must complete successfully before the next one is started. If the init container in the Pod fails, the kubelet will repeatedly restart it until it succeeds. A Pod cannot be Ready
until all init containers have succeeded. If the Pod restarts, all init containers must execute again.
An init containers do not support lifecycle, livenessProbe, readinessProbe, or startupProbe because they must run to completion before the application container starts.
Uses of Init Container
- Because init containers run to completion before any application containers, init containers can be used to block or delay application container start-up until a set of preconditions are met. Once preconditions are met, the app containers in a Pod can start. For example init container can be used to check the load balancer has been created or the database service is available for application to consume.
- Init container can contain utilities and scripts which are not required or does not add any benefit to the application.
Adding an Init Container
In this article we will see three different scenarios and understand how status of init container impacts the main application pod.
Case 1: Init container runs to completion.
The below example defines an application pod that has one init container. The init container will simply sleep for ten seconds before completing. Once the init container has run to completion, the application container will be started.
Create a pod manifest file as below and apply it to the Kubernetes cluster.
apiVersion: v1
kind: Pod
metadata:
name: app-pod
labels:
app: app
spec:
containers:
- name: app-container
image: busybox
command: ['sh', '-c', 'echo The application is running! && sleep 3600']
initContainers:
- name: init-container
image: busybox
command: ['sh', '-c', 'echo init-container start; sleep 10;echo init-container complete;']
Create the pod and verify its status.
# kubectl create -f pod.yaml
pod/app-pod created
# kubectl get pods
NAME READY STATUS RESTARTS AGE
app-pod 0/1 Init:0/1 0 10s
NAME READY STATUS RESTARTS AGE
app-pod 0/1 PodInitializing 0 14s
NAME READY STATUS RESTARTS AGE
app-pod 1/1 Running 0 16s
For more details describe the pod. As seen in the below output, the init container was terminated after being run to completion. Only when the init container got terminated successfully, the application pod was started.
# kubectl describe pod app-pod
Name: app-pod
Namespace: default
[ . . . ]
Labels: app=app
Status: Running
Init Containers:
init-container:
[ . . . ]
State: Terminated
Reason: Completed
[ . . . ]
Containers:
app-container:
[ . . . ]
State: Running
[ . . . ]
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 64s default-scheduler Successfully assigned default/app-pod to controlplane
Normal Pulling 64s kubelet Pulling image "busybox"
Normal Created 63s kubelet Created container init-container
Normal Started 62s kubelet Started container init-container
Normal Pulling 52s kubelet Pulling image "busybox"
Normal Created 52s kubelet Created container app-container
Normal Started 51s kubelet Started container app-container
Case 2: Init container fails with Pod’s restartPolicy as always.
In the below example the init container will fail with an exit code 1. When the restartPolicy of a Pod is set to Always
, the init containers use restartPolicy OnFailure
. This means that that the container will only be restarted if it exited with a non-zero exit code (i.e. something went wrong). As a result, kubelet will repeatedly try to restart the init container and go into CrashLoopBackOff
state.
apiVersion: v1
kind: Pod
metadata:
name: app-pod
labels:
app: app
spec:
containers:
- name: app-container
image: busybox
command: ['sh', '-c', 'echo The application is running! && sleep 3600']
initContainers:
- name: init-container
image: busybox
command: ['sh', '-c', 'echo init-container start; exit 1;echo init-container complete;']
Create the pod and verify its status. As seen in the below output, the init container goes into CrashLoopBackOff
state as the Pod’s restartPolicy was set to the default value of Always
and the effective restartPolicy on the init container was OnFailure
.
# kubectl create -f pod.yaml
pod/app-pod created
# kubectl get pods
NAME READY STATUS RESTARTS AGE
app-pod 0/1 Init:CrashLoopBackOff 2 (17s ago) 35s
Case 3: Init container fails with Pod’s restartPolicy as Never.
In the below example the init container fails with an exit code 1. In this scenario the restartPolicy of the Pod is set to Never
. With the restartPolicy as Never
, the container will not be restarted regardless of why it exited. As a result, the Pod will go into Error
state.
apiVersion: v1
kind: Pod
metadata:
name: app-pod
labels:
app: app
spec:
restartPolicy: Never
containers:
- name: app-container
image: busybox
command: ['sh', '-c', 'echo The application is running! && sleep 3600']
initContainers:
- name: init-container
image: busybox
command: ['sh', '-c', 'echo init-container start; exit 1;echo init-container complete;']
Create the pod and verify its status. As in this the case the restartPolicy of the pod was set to Never
, hence the pod will go into Error
state.
# kubectl create -f pod.yaml
pod/app-pod created
# kubectl get pods
NAME READY STATUS RESTARTS AGE
app-pod 0/1 Init:Error 0 58s
For more details describe the pod. In the output it can be seen that the init container got terminated because of the error. As a result, the application container could not be created and is stuck in the Waiting
state.
# kubectl describe pod app-pod
Name: app-pod
Namespace: default
[ . . . ]
Labels: app=app
Status: Running
Init Containers:
init-container:
[ . . . ]
State: Terminated
Reason: Error
[ . . . ]
Containers:
app-container:
[ . . . ]
State: Waiting
Reason: PodInitializing
[ . . . ]
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 64s default-scheduler Successfully assigned default/app-pod to controlplane
Normal Pulling 64s kubelet Pulling image "busybox"
Normal Created 63s kubelet Created container init-container
Normal Started 62s kubelet Started container init-container
Pingback: Kubernetes: What is a sidecar container – Learn and Implement DevOps