Skip to content

Init Containers

Environment Variables

We are going to use some environment variables in this tutorial. Please make sure you have set them correctly.

# check if the environment variables are set if not set them
export NAMESPACE=<namespace>
echo $NAMESPACE

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 1: Create an init container

We want to create a Pod that runs an init container that creates a file and then runs a container that reads the file.

Create a file called init-container.yaml with the following content:

apiVersion: v1
kind: Pod
metadata:
  name: init-demo
spec:
  containers:
  - name: nginx
    image: nginx
    resources:
      requests:
        cpu: 10m
        memory: 16Mi
      limits:
        cpu: 20m
        memory: 32Mi
    volumeMounts:
    - name: workdir
      mountPath: /usr/share/nginx/html
  initContainers:
  - name: init
    image: busybox
    command:
    - 'sh'
    - '-c'
    - 'echo "<h1>Hello World</h1>" > /work-dir/index.html'
    volumeMounts:
    - name: workdir
      mountPath: /work-dir
  volumes:
  - name: workdir
    emptyDir: {}

Apply the file:

kubectl apply -f init-container.yaml --namespace $NAMESPACE

Check the status of the Pod:

kubectl get pod init-demo --namespace $NAMESPACE

The output should look like this:

NAME        READY   STATUS     RESTARTS   AGE
init-demo   0/1     Init:0/1   0          1m

The Pod is in the Init:0/1 state, which means that the init container is running.

Check the /usr/share/nginx/html/index.html file in the nginx container:

kubectl exec -it init-demo --namespace $NAMESPACE -- cat /usr/share/nginx/html/index.html

The output should look like this:

Defaulted container "nginx" out of: nginx, init (init)
<h1>Hello World</h1>

for fast learners

Try to expose the Pod with a Service and an Ingress.

Task 2: Create a Init Container that checks database connectivity

We want to create a Deployment that runs an init container that checks database connectivity and then starts the main container.

Create a file called init-deployment.yaml with the following content:

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: init-deployment
  name: init-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: init-deployment
  template:
    metadata:
      labels:
        app: init-deployment
    spec:
      initContainers:
      - name: pg-isready
        image: postgres:14.5
        command: 
          - 'sh'
          - '-c'
          - |
            until pg_isready -h <postgresql host> -p 5432; do
              echo "waiting for database to start"
              sleep 2
            done
          - 'echo'
          - 'Database is ready'
      containers:
      - image: ghcr.io/natrongmbh/kubernetes-workshop-golog-test-postgresql-webserver:latest
        name: init-deployment
        resources:
          requests:
            cpu: 10m
            memory: 16Mi
          limits:
            cpu: 20m
            memory: 32Mi
        envFrom:
        - secretRef:
            name: db-secret

Note

Make sure to replace <postgresql host> with the host of your PostgreSQL database.

Apply the file:

kubectl apply -f init-deployment.yaml --namespace $NAMESPACE

Check the status of the Deployment:

kubectl get deployment init-deployment --namespace $NAMESPACE

The output should look like this:

NAME                                        READY   STATUS      RESTARTS   AGE
init-deployment-5567dc778c-ns27h            0/1     Init:0/1    0          3s

The Deployment is in the Init:0/1 state, which means that the init container is running.

Check the logs of the init container:

export POD_NAME=$(kubectl get pods --namespace $NAMESPACE -l "app=init-deployment" -o jsonpath="{.items[0].metadata.name}")
kubectl logs $POD_NAME -c pg-isready --namespace $NAMESPACE