3.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 Init Containers from the Kubernetes documentation for more details.

Task 3.6.1: Add an init container

In Backend you created the example-frontend 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-frontend Deployment by changing your local deployment_example-frontend.yaml. Add the init container into the existing Deployment (same indentation level as containers):

...
    spec:
      initContainers:
        - name: wait-for-db
          securityContext:
            runAsUser: 1000
          image: mirror.gcr.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:

kubectl apply -f deployment_example-frontend.yaml --namespace <namespace>

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

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

kubectl 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 rke2-coredns-rke2-coredns.kube-system.svc.cluster.local

Name:      mariadb.<namespace>.svc.cluster.local
Address 1: 10.43.87.97 mariadb.<namespace>.svc.cluster.local

Check Init Container from the Kubernetes documentation for more details.