# 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) ```bash 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 `echo`s 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 ```bash # 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).