Exploring the Role of Init Containers in Kubernetes Applications
Table of contents
- Use cases of init containers:
- Use-case 1: Deploy the file index.html & then start the nginx pod.
- Use-case 2: Check the databases service & then start the main pod.
- Using the init container as a sidecar container
- Use-case 3: Use a sidecar container to append the memory info to the index.html file every 10 sec.
A pod can have multiple containers, this init container is run before the main app containers.
Init containers are run before the main app containers.
Init containers always run to completion before the pod can be ready and it not continuously running alongside the main containers.
Init containers run to completion sequentially & the main container does not start until all the init containers have been completed.
Each init container must be completed successfully before the next one starts.
Use cases of init containers:
Some configurations need to be performed before starting the main application container.
Check for some X services or database services before starting the application containers.
Understanding with the help of the following examples:
Use-case 1: Deploy the file index.html & then start the nginx pod.
Here, we will use a common volume mount for both the init container & app container.
The application(Nginx) container only starts if the init container is executed successfully.
spec:
volumes:
- name: shared-data
emptyDir: {}
initContainers:
- name: first-init-container
image: busybox
command: ['sh', '-c', 'wget -O /usr/share/data/index.html https://minex.hashnode.dev']
volumeMounts:
- name: shared-data
mountPath: /usr/share/data
containers:
- name: nginx-container
image: nginx
volumeMounts:
- name: shared-data
mountPath: /usr/share/nginx/html
Explanation:
1. First, we have created the empty volume called shared-data.
2. Then, use the initContainer block, specify the command to update the index.html file, and mount it to the /usr/share/data directory (This is the container directory.)
3. Then, have the main container block, where we used the same volume that was created earlier (This volume has the updated index.html file), and mount it to the main container, to reflect the changes.
Use-case 2: Check the databases service & then start the main pod.
Here, we have two init containers, first to check the database service & second to check the application service.
Once the successful completion of both the init containers are sequentially completed, then only the main container gets started.
spec:
initContainers:
- name: check-db-service
image: busybox
command: ['sh', '-c', 'until nslookup db.default.svc.cluster.local; do echo waiting for db service; sleep 2; done;']
- name: check-myservice
image: busybox
command: ['sh', '-c', 'until nslookup myservice.default.svc.cluster.local; do echo waiting for myservice; sleep 2; done;']
containers:
- name: main-container
image: busybox
command: ['sleep', '3600']
This service file is for the above pod manifest.
---
apiVersion: v1
kind: Service
metadata:
name: db
spec:
selector:
app: demo1
ports:
- protocol: TCP
port: 3306
targetPort: 3306
---
apiVersion: v1
kind: Service
metadata:
name: myservice
spec:
selector:
app: demo2
ports:
- protocol: TCP
port: 80
targetPort: 80
Explanation:
1. Here, we have created the kubernetes service kind for the database and myservice services and used the Kubernetes DNS name for a service within a Kubernetes cluster to check the status.
2. Then, it starts the main container.
Using the init container as a sidecar container
About sidecar containers:
The init container runs to completion before starting the main container, whereas the side-car container starts first & continuously runs along with the main container as the supporting container.
Use case of sidecar container:
- Service mesh (proxy server)
- Logging purpose
- Metrics collection
- To make the normal init container as the sidecar container, we have to use “restartPolicy: Always” in the initContainers block.
Use-case 3: Use a sidecar container to append the memory info to the index.html file every 10 sec.
Here, we will use a common volume mount for both the init container & app container.
spec:
volumes:
- name: shared-data
emptyDir: {}
initContainers:
- name: meminfo-container
image: alpine
restartPolicy: Always
command: ['sh', '-c', 'sleep 5; while true; do cat /proc/meminfo > /usr/share/data/index.html; sleep 10; done;']
volumeMounts:
- name: shared-data
mountPath: /usr/share/data
containers:
- name: nginx-container
image: nginx
volumeMounts:
- name: shared-data
mountPath: /usr/share/nginx/html
Explanation:
1. First, we have created the empty volume called shared-data.
2. Then, use the initContainer block, specify the “restartPolicy: Always” to act as a sidecar container and command to update the index.html file with memory info at every 10 sec of interval and mount it to the /usr/share/data directory (This is the container directory.)
3. Then, have the main container block, where we used the same volume that was created earlier (This volume has the updated index.html file), and mount it to the main container, to reflect the changes.
Note: The sidecar container will remain running during the entire life of the pod.
Refer to the GitHub repository for all the manifest files used in this blog.
Subscribe to my newsletter
Read articles from Neeraj Gupta directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by