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--