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.