Using initContainers to create dependencies on Pods

Published on Oct 17

I’ll try to keep this post fairly short as it’s a pretty simple solution to a question I recently got. So, let’s assume you have an application which you need to translate from a Docker Compose file to a Kubernetes manifest. In a Docker Compose file, you have the possibility to add an depends_on entry which allows you to let a container start up once another container has started up. Kubernetes manifests don’t have a feature like that, instead you can use an initContainer which are containers that are started before starting the actual containers in the pod.

The basics

Before we get into adding an initContainer to a Pod deployment, let’s explore two methods to check if a pod is ready to accept traffic. Your choice between these methods will depend on whether you are using readiness probes or not. Let’s take a look our options.

Checking whether a port on the Pod is available

One way to determine if a pod is ready is by checking if a specific port is available. For web applications, this can be easily achieved using tools like cURL or Wget. For other types of applications, such as a database, you can use netcat (nc) to check whether a port is available.

Below, I’ve added a basic example of how you’d check if a pod containing a web application has started up. Using Wget, it sends a request every 5 seconds until the URI returns a 200 status code. You should be able to alter the script to use netcat by changing the until statement to contain a command like the following: nc -z pod.namespace.svc.cluster.local 1234.

until wget --spider -S http://webapp.namespace.svc.cluster.local 2>&1 | grep 'HTTP/1.1 200 OK'; do
  sleep 5;
  echo 'Waiting for the webapp...';
done

Checking if the Pod’s readines probe is ready

If you’re already using readiness probes, consider using them to assess container readiness instead of checking for port availability. Readiness probes are specifically designed to determine when a container within a pod is ready to receive traffic. The kubectl wait command can be used to check if a readiness probe has succeeded.

An example of how you’d check if a Pod’s readiness probe has succeeded can be found below:

until kubectl wait --for=condition=ready pod -l app=webapp --timeout=300s; do
  sleep 5;
  echo 'Waiting for the database pod...';
done

Adding an initContainer to a Pod YAML

Now that we understand how to check if an application has started up, let’s add an initContainer to a Kubernetes pod. In essence, an initContainer in Kubernetes is a special container that runs before the main containers within a pod. It’s often used to perform initialization or preparation tasks necessary for the main containers to function. However, we can also utilize initContainers to verify the status of a different pod.

Adding an initContainer to your pod is straightforward. Simply include an initContainers section in your pod’s YAML definition and define the container. In the example below, we use a port-based check to confirm that another pod is running.

apiVersion: v1
kind: Pod
metadata:
  name: some-webapp
  labels:
    app: some-webapp
spec:
  containers:
    - name: app
      image: app:latest
  initContainers:
    - name: wait-for-pod
      image: busybox
      command:
        - /bin/sh
        - -c
        - |
          until wget --spider -S http://database.default.svc.cluster.local 2>&1 | grep 'HTTP/1.1 200 OK'; do
            sleep 5;
            echo 'Waiting for the database pod...';
          done

Note: In this example, we use the busybox container, which includes the “sh” shell and the wget command. You can choose your preferred container image, as long as it includes these components.

The example can be adapted for a readines probe based check by modifying the script to use the kubectl wait command and changing the container image to one that includes the kubectl command.

initContainers:
  - name: wait-for-pod
    image: kubectl
    command:
      - /bin/sh
      - -c
      - |
        until kubectl wait --for=condition=ready database -l app=database --timeout=300s; do
          sleep 5;
          echo 'Waiting for the database pod...'; 
        done

When you apply your Kubernetes manifest, you’ll observe your pod in the “Init” state until the other pod successfully starts up.

Similar posts

Copyright © Vincent De Borger