Files
kodekloud-engineer/kubernetes/level 3/task-3.md

5.4 KiB

Assignment

There are some applications that need to be deployed on Kubernetes cluster and these apps have some pre-requisites where some configurations need to be changed before deploying the app container. Some of these changes cannot be made inside the images so the DevOps team has come up with a solution to use init containers to perform these tasks during deployment. Below is a sample scenario that the team is going to test first.

Create a Deployment named as ic-deploy-devops.

Configure spec as replicas should be 1, labels app should be ic-devops, template's metadata lables app should be the same ic-devops.

The initContainers should be named as ic-msg-devops, use image fedora with latest tag and use command '/bin/bash', '-c' and 'echo Init Done - Welcome to xFusionCorp Industries > /ic/media'. The volume mount should be named as ic-volume-devops and mount path should be /ic.

Main container should be named as ic-main-devops, use image fedora with latest tag and use command '/bin/bash', '-c' and 'while true; do cat /ic/media; sleep 5; done'. The volume mount should be named as ic-volume-devops and mount path should be /ic.

Volume to be named as ic-volume-devops and it should be an emptyDir type.

Note: The kubectl utility on the jump-host has been configured to work with the Kubernetes cluster.

Solution

Deployment with Init Container — ic-deploy-devops

An init container writes a message to a shared emptyDir volume; the main container then reads it in a loop. This is the canonical init-container pattern. Applied inline via a heredoc — no manifest file on disk.

Apply (heredoc → kubectl)

kubectl apply -f - <<'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
  name: ic-deploy-devops
  labels:
    app: ic-devops
spec:
  replicas: 1
  selector:
    matchLabels:
      app: ic-devops
  template:
    metadata:
      labels:
        app: ic-devops
    spec:
      initContainers:
        - name: ic-msg-devops
          image: fedora:latest
          command:
            - /bin/bash
            - -c
            - "echo Init Done - Welcome to xFusionCorp Industries > /ic/media"
          volumeMounts:
            - name: ic-volume-devops
              mountPath: /ic
      containers:
        - name: ic-main-devops
          image: fedora:latest
          command:
            - /bin/bash
            - -c
            - "while true; do cat /ic/media; sleep 5; done"
          volumeMounts:
            - name: ic-volume-devops
              mountPath: /ic
      volumes:
        - name: ic-volume-devops
          emptyDir: {}
EOF

kubectl rollout status deployment/ic-deploy-devops

How it works

The heredoc apply pattern

  • kubectl apply -f - reads from stdin; nothing written to disk.
  • <<'EOF' (delimiter quoted) keeps the manifest literal — the right default for k8s YAML.

Init container vs. main container — the ordering guarantee

This is a classic init container (under initContainers, no restartPolicy override), which behaves very differently from the main container:

  • ic-msg-devops (init) runs first, to completion, before any main container starts. It echos the message into /ic/media and exits 0. Because it's a one-shot task that finishes, a classic init container is exactly right here — it does setup work, then gets out of the way.
  • ic-main-devops (main) starts only after the init container succeeds. It then loops, cat-ing /ic/media every 5 seconds. The while true keeps it running so the pod stays up.

The sequencing is guaranteed by Kubernetes: init containers complete before app containers begin. That's what makes the pattern work — the file is written before the main container ever tries to read it.

The shared emptyDir volume

  • ic-volume-devops (emptyDir: {}) is declared once and mounted at /ic in both containers. emptyDir is created empty when the pod starts and shared by all its containers, so the init container's write to /ic/media is visible to the main container at the same path. This is the hand-off mechanism: init writes, main reads, through shared storage.

Both volumeMounts reference the same volume name (ic-volume-devops) at the same path — that's what ties them to one storage location.

Why the commands need /bin/bash -c

Each command is a shell one-liner (a redirect for the init, a loop for the main), so both run via /bin/bash -c. The main container's while true loop is what keeps it in Running state — without a long-running process, the fedora container would exit immediately and the pod would crash-loop.

Verify

# Deployment ready
kubectl get deployment ic-deploy-devops
kubectl get pods -l app=ic-devops

# Init container completed (check pod init status)
kubectl get pod -l app=ic-devops \
  -o jsonpath='{.items[0].status.initContainerStatuses[0].state}{"\n"}'

# Main container is printing the message from the shared volume
kubectl logs -l app=ic-devops -c ic-main-devops --tail=3

Expected — deployment READY 1/1, the init container state showing terminated/reason: Completed, and the main container's logs repeatedly printing Init Done - Welcome to xFusionCorp Industries.

If the pod is stuck in Init:0/1, the init container hasn't completed — check kubectl logs -l app=ic-devops -c ic-msg-devops. Unlike a native sidecar, a classic init container here is meant to finish, and it does (the echo exits immediately).