9.6. Init containers

A Pod can have multiple containers running apps within it, but it can also have one or more init containers, which are run before the app container is started.

Init containers are exactly like regular containers, except:

  • Init containers always run to completion.
  • Each init container must complete successfully before the next one starts.

Check out the Init Containers documentation for more details.

Task 9.6.1: Add an init container

In 7. Attaching a database you created the example-web-app application. In this task, you are going to add an init container which checks if the MariaDB database is ready to be used before actually starting your example application.

Edit your existing example-web-app Deployment by changing your local deployment_example-web-app.yaml. Add the init container into the existing Deployment (same indentation level as containers):

...
    spec:
      initContainers:
        - name: wait-for-db
          image: docker.io/busybox:1.28
          command:
            [
              "sh",
              "-c",
              "until nslookup mariadb.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for mydb; sleep 2; done",
            ]
...

And then apply again with:

oc apply -f deployment_example-web-app.yaml --namespace <namespace>

Let’s see what has changed by analyzing your newly created example-web-app Pod with the following command (use oc get pod or auto-completion to get the Pod name):

oc describe pod <pod> --namespace <namespace>

You see the new init container with the name wait-for-db:

...
Init Containers:
  wait-for-db:
    Container ID:  docker://77e6e309c88cfe62d03ed97e8fae20704bbf547a1e717a8f699ba79d9879cca2
    Image:         busybox
    Image ID:      docker-pullable://busybox@sha256:141c253bc4c3fd0a201d32dc1f493bcf3fff003b6df416dea4f41046e0f37d47
    Port:          <none>
    Host Port:     <none>
    Command:
      sh
      -c
      until nslookup mariadb.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for mydb; sleep 2; done
    State:          Terminated
      Reason:       Completed
      Exit Code:    0
      Started:      Tue, 10 Nov 2020 21:00:24 +0100
      Finished:     Tue, 10 Nov 2020 21:02:52 +0100
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-xz2b7 (ro)
...

The init container has the State: Terminated and an Exit Code: 0 which means it was successful. That’s what we wanted, the init container was successfully executed before our main application.

You can also check the logs of the init container with:

oc logs -c wait-for-db <pod> --namespace <namespace>

Which should give you something similar to:

Server:    10.43.0.10
Address 1: 10.43.0.10 kube-dns.kube-system.svc.cluster.local

Name:      mariadb.acend-test.svc.cluster.local
Address 1: 10.43.243.105 mariadb.acend-test.svc.cluster.local

Deployment hooks on OpenShift

A similar concept are the so-called pre and post deployment hooks. Those hooks basically give the possibility to execute Pods before and after a deployment is in progress.

Check out the official documentation for further information.