Kubernetes > Pods > initContainers
A Pod can contain more than ore container, likewise it can also contain more than one initContainer which starts when the Pod is initialized. By default, initContainers will be launched first before the normal app containers. The initContainers are used for supporting the normal containers such as performing certain tasks and keeping the environment ready before the app container starts
Let’s see our objectives and few descriptions for this exercise
- We are going to create a Pod volume of type emptyDir, we name the volume vol10
- We would share this volume with both the initContainer(busybox) and the app container(nginx)
- The busy box is a tiny image that combines common unix utilities, in our case we are going to use the ‘wget’ utility from the busybox
- As we know containers would only contain minimal software that reflects the purpose of that container, for example the nginx container would mainly have the nginx package and it wouldn’t have utilities such as curl or wget
- Hence we are running the initContainer first which would have the utilities we need and makes the job easier for the app container
- If we had to use a utility such as wget directly on the nginx container, then we should update the repo and install wget. This isn’t the right way of doing things in the world of containers, and the whole essence of using containers is lost. The containers serve the purpose of combining utilities in an image relevant to the need. So instead of installing wget on nginx, it would be a good choice to have another container such as busybox which already as it installed
- We are going to run “wget -O /work-dir/index.html networkandcode.wordpress.com” on the initContainer(busybox), some explanation on what this command does - it captures the html content from the website networkandcode.wordpress.com and stores the code in the file index.html which is inside the /work-dir directory of the busybox initContainer, we have given this initContainer the name ctr10-init
- We would attach the volume vol10 with the initContainer and mount the volume in the path /work-dir, note that we have a file ‘index.html’ inside this directory that has the content from the website we mentioned earlier
- Once the initContainer has finished its task, a.k.a executed the command, it would be terminated, and the file index.html is now in the volume vol10
- Note that the app container would only start after the initContainer has finished its job.
- We no more need the initContainer, and the app container (nginx) is now going to start
- We would attach the same volume vol10 to the app container in the path /usr/share/nginx/html
- As the volume is attached to the nginx container, the index.html file inside the volume vol10 should now be inside the directory /usr/share/nginx/html of the nginx container
- Some information on nginx - By default the index.html file inside the /usr/share/nginx/html directory would contain certain default information as configured by the nginx team, and we could customize that webpage to display any other information that we may need, for example a website that we may build using nginx is going to contain information relevant to our content
- The html code that the nginx web server would display as a website is by default stored in /usr/share/nginx/html/index.html, so whatever html content this index.html has is going to be rendered as a web page on the browser(Chrome, Firefox, Edge, etc.). Note that when we use a utility like curl or wget instead of a web browser, this page would return the html code as is, in text
- Hence when we wget / curl the nginx container it should display the content inside index.html a.k.a the content that we sourced from the website networkandcode.wordpress.com
Let's see this in action
Let’s define a Pod configuration/manifest as follows
---
apiVersion: v1
kind: Pod
metadata:
name: po10-init
spec:
volumes:
- name: vol10
emptyDir: {}
initContainers:
- name: ctr10-init
image: busybox
command:
- wget
- "-O"
- "/work-dir/index.html"
- networkandcode.wordpress.com
volumeMounts:
- name: vol10
mountPath: "/work-dir"
containers:
- name: ctr10
image: nginx
volumeMounts:
- name: vol10
mountPath: /usr/share/nginx/html
...
Please note that the command section inside the initContainer has a list of commands, actually it’s a single command, however its given in multiple lines, to specify sections of the command that are separated by spaces
Let’s create the Pod
networkandcode:~ kubectl create -f ex10-po-init.yaml
pod/po10-init created
The Pod is now running, please make a note of the Pod’s IP - here its 10.8.1.13, we would need this when we want to curl
networkandcode:~ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE
po10-init 1/1 Running 0 58m 10.8.1.13 gke-standard-cluster-1-default-pool-a798a8f8-601m
Let’s curl the Pod from one of the worker nodes
To check the list of nodes, note that I am using google cloud here
networkandcode:~ kubectl get nodes
NAME STATUS ROLES AGE VERSION
gke-standard-cluster-1-default-pool-a798a8f8-2w5s Ready 4m44s v1.12.8-gke.10
gke-standard-cluster-1-default-pool-a798a8f8-601m Ready 4m44s v1.12.8-gke.10
gke-standard-cluster-1-default-pool-a798a8f8-p27f Ready 4m44s v1.12.8-gke.10
Since this scenario is setup on google cloud, I am using the gcloud way of logging into the node, however if you are running a cluster that is not in cloud, you could directly ssh into the nodes, or you could even directly curl from the master if it has connectivity to the pods, In the case of gcloud I wasn’t able to curl the Pod from the gcloud shell, hence I had to login to one of the nodes to execute curl
To login to the node (in gcloud)
Check the cluster zone first - its us-central1-a here
Set the zone on gcloud shell appropriately
networkandcode:~ gcloud config set compute/zone us-central1-a
Updated property [compute/zone].
Login to one of the nodes now
For instance, gke-standard-cluster-1-default-pool-a798a8f8-2w5s, this name could change in your case, this was checked in the get nodes section few steps back in this post
networkandcode:~ gcloud compute ssh gke-standard-cluster-1-default-pool-a798a8f8-2w5s
Warning: Permanently added 'compute.6743270824986417587' (ED25519) to the list of known hosts.
Welcome to Kubernetes v1.12.8-gke.10!
You can find documentation for Kubernetes at:
http://docs.kubernetes.io/
The source for this release can be found at:
/home/kubernetes/kubernetes-src.tar.gz
Or you can download it at:
https://storage.googleapis.com/kubernetes-release-gke/release/v1.12.8-gke.10/kubernetes-src.tar.gz
It is based on the Kubernetes source at:
https://github.com/kubernetes/kubernetes/tree/v1.12.8-gke.10
For Kubernetes copyright and licensing information, see:
/home/kubernetes/LICENSES
Let’s curl the Pod’s IP, It would display a whole lot of content that was sourced from the website and then placed in index.html
networkandcode@gke-standard-cluster-1-default-pool-a798a8f8-2w5s ~ $ curl 10.8.1.13
network blog | blog > practice > share | [ network coding cloud… ]
--TRUNCATED--
<path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608
,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771
,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-
1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"/>
Another way to verify, the same content could be found in /usr/share/nginx/html/index.html
We can issue this from the master or the gcloud shell, the command is executed on the container inside the pod directly from the master without getting into bash of the container
networkandcode:~ kubectl exec -it po10-init cat /usr/share/nginx/html/index.html
--TRUNCATED--
<path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608
,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771
,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-
1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"/>
In this scenario, we have used wget on the initContainer, however we could use many other utilities depending on the need
--end-of-post--