Graphic showing the Kubernetes logo

Init containers are a Kubernetes mechanism for initializing new Pods. Init containers start and exit before their Pod’s main application containers, providing a chance to run bootstrap scripts in sequential order.

In this article we’ll show how to add init containers to a Pod and consider some common use cases. Although init containers are configured similarly to regular containers, they do have some differences because of their specialized purpose.

The Role of Init Containers

Init containers solve challenges associated with first-run initialization of applications. It’s common for services to depend on the successful completion of a setup script before they can fully start up.

In smaller systems, you could add the script to your existing application container image. However this isn’t ideal as it adds another responsibility to the image. You may even have several distinct stages to complete, each with their own dependencies and relationships. Adding all these single-use operations to your main container image can quickly create bloated complexity that’s hard to maintain.

Init containers address this by letting you run specialized containers before a Pod’s application containers start. Each Pod can have multiple init containers; they’re guaranteed to run sequentially, only after the previous one has completed by exiting successfully.

Kubernetes starts the Pod’s regular containers once all the init containers have completed. If an init container fails, it will be restarted until it completes. When the Pod’s restartPolicy is set to Never, the Pod is marked as failed instead.

Adding Init Containers to a Pod

Init containers are defined in the spec.initContainers field of a Pod’s manifest. This is very similar to a regular spec.containers definition.

Here’s a example of a Pod with two init containers attached:

apiVersion: v1
kind: Pod
metadata:
  name: init-containers-pod
spec:
  containers:
    - name: app-container
      image: busybox:latest
      command: ["echo", "Started app"]
  initContainers:
    - name: first-init-container
      image: busybox:latest
      command: ["echo", "This is the first init container"]
    - name: second-init-container
      image: busybox:latest
      command: ["echo", "This is the second init container"]

Use Kubectl to add the Pod to your cluster:

$ kubectl apply -f pod.yaml
pod/init-containers-pod created

Now retrieve the logs associated with each of the init containers to confirm they’ve been run:

$ kubectl logs init-containers-pod -c first-init-container
This is the first init container

$ kubectl logs init-containers-pod -c second-init-container
This is the second init container

You can use most properties available to Kubernetes container manifests within an initContainers field. These include volumes, ports, environment variables, and security contexts.

Init containers support resource limits too but these are handled differently to regular containers. The highest value of the resource limits declared by all the init containers is selected as the Pod’s effective limit, unless it’s lower than the sum of the limits on the Pod’s application containers. This computed value will be used for scheduling purposes.

One limitation of init containers is their lack of support for probes. You can’t assign livenessProbe, readinessProbe, or startupProbe fields to container objects in the initContainers field. Init containers are a separate mechanism which you can use instead of or alongside probes attached to your main application containers.

Common Gotchas

There are a few common pitfalls when using init containers. Here are some details to remember:

  • Init containers run each time their Pod restarts. This means your init container operations should be idempotent so they’re resilient to running twice in the same Pod. If the Pod is restarted, all its init containers will be executed again.
  • Changes to a Pod’s initContainers field aren’t supported, with one exception. You can modify the image field. This will cause the Pod to restart and run your new init containers.
  • Init container names need to be unique across all the containers in the Pod. This includes other init containers and your application containers. You’ll see a YAML validation error in your console if you try to apply a manifest that breaks this rule.
  • Pods have an Initialized: False condition when init containers are running. This is visible under the Conditions heading when you run kubectl describe my-pod.

You can also check whether a Pod’s init containers have completed using the kubectl get command:

$ kubectl get init-containers-pod
NAME                   READY     STATUS    RESTARTS    AGE
init-containers-pod    0/1       Init:1/2  0           1m

In this case, the STATUS column shows the Pod has two init containers, one of which has successfully completed. Once all the init containers finish, Kubernetes will start the application containers and the Pod’s status will change to Running.

When to Use Init Containers

Init containers are ideal whenever new deployments of your application need to be initialized in some way. They cater for dedicated pre-run tasks that depend on tooling outside your main container image.

Here are a few situations where you might use init containers:

  • Generating configuration files from environment variables.
  • Pre-populating caches used by your application.
  • Migrating and seeding a database instance.
  • Downloading and installing application plugins into a volume.
  • Blocking application start-up until dependencies are available (such as databases or external APIs).

Another way to achieve some of these tasks is with a readiness or startup probe. However there is a difference in intent: probes are primarily designed to communicate a container’s state to Kubernetes whereas init containers are designated as a way to perform actions during Pod initialization.

Summary

Init containers are a way to perform first run initialization routines within a Kubernetes Pod. They can be used to block or delay application container startup while you wait for dependencies to become available or bootstrap scripts to complete.

The functionality of init containers sometimes overlaps startup and readiness probes. You can use a probe when the activity you want to perform mostly concerns blocking application startup until a condition is met. They rely on your script already existing in your application’s container image. An init container is a better choice when you want to perform specialist actions without bloating your main image with single-use utilities.

Profile Photo for James Walker James Walker
James Walker is a contributor to How-To Geek DevOps. He is the founder of Heron Web, a UK-based digital agency providing bespoke software development services to SMEs. He has experience managing complete end-to-end web development workflows, using technologies including Linux, GitLab, Docker, and Kubernetes.
Read Full Bio »