Feedback

Chat Icon

Cloud-Native Microservices With Kubernetes - 2nd Edition

A Comprehensive Guide to Building, Scaling, Deploying, Observing, and Managing Highly-Available Microservices in Kubernetes

From Settings to Startup: Managing Configuration and Initialization in Kubernetes
34%

Init Container: Initializing the Application

Our application serves a static HTML page at the root URL (/), but we haven't created this page yet. We could have baked this page into the Docker image, but that would require rebuilding and pushing the image every time we want to change the content of the page. Also, our static page could be generated based on some configuration or data. It's, after all, an opportunity to use init containers and learn more about them.

Usually, init containers are used to perform initialization tasks that need to be completed before the main application container starts. If the init container fails, the main application container will not start, and the Pod will be in a CrashLoopBackOff state until the init container succeeds.

To create the init container, we will use a simple busybox image that runs a shell command to create the page. We also have to use a volume to share the generated page between the init container and the main application container. All of this requires updating the Deployment manifest.

Here is the updated version:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: hmac-app
  namespace: hmac
spec:
  replicas: 1
  selector:
    matchLabels:
      app: hmac-app
  template:
    metadata:
      labels:
        app: hmac-app
    spec:
      containers:
      - name: hmac-app
        image: $DOCKERHUB_USERNAME/hmac:v0
        ports:
        - containerPort: 5000
        volumeMounts:
        - name: data-volume
          mountPath: /data
      initContainers:
      - name: init-hmac-page
        image: busybox
        command:
          - sh
          - -c
          - |
            echo "HMAC Service

Welcome to the HMAC Service

Use the /sign endpoint to sign your messages.

" > /data/index.html
volumeMounts: - name: data-volume mountPath: /data volumes: - name: data-volume emptyDir: {}

What we added/changed:

  • Added an initContainers section with a single init container called init-hmac-page that uses the busybox image to create the static HTML page.
  • Added a volumeMounts section to both the init container and the main application container; both containers mount the same volume at the /data path.
  • Added a volumes section to define the volume used for sharing data between the init container and the main application container. We used an emptyDir volume, which is a temporary directory that is created when the Pod is assigned to a Node and exists as long as the Pod is running.

emptyDir is one of Kubernetes’ simplest and most useful volume types—a temporary, shared directory that exists only for the lifetime of a Pod. Any container in that Pod that mounts this volume will see the same shared files.

You may ask: why emptyDir? What if the Pod is rescheduled to another Node? Won't we lose the data?

We could have used other types of Volumes as well that require more setup, like PersistentVolumeClaim, that have persistence beyond the Pod's lifetime.

For this use case, there's no need for persistence beyond the Pod's lifetime. When the Pod is deleted (for example, when it’s rescheduled or scaled down), everything inside: the data in the emptyDir is lost. But in our case, the init container will run again when the Pod is recreated, and it will regenerate the HTML. When a Pod starts, Kubernetes creates an empty directory on the node — hence the name emptyDir.

This resource is perfect for our use case and for many use cases where initialization is done by an init container because:

  • It’s simple.
  • It’s reproducible.
  • It’s cheaper than using persistent storage.

If you need persistence beyond the Pod's lifetime, then, of course, consider creating a claim for a PersistentVolume.

Since we are done with the changes, let's update the Deployment file, add the ConfigMap and Secret references, and reapply the manifest:

cat < kubernetes/hmac-resources.yaml
---
# Create a Namespace for our application
apiVersion: v1
kind: Namespace
metadata:
  name: hmac
---
# Create a Deployment for our HMAC application
apiVersion: apps/v1
kind: Deployment
metadata:
  name: hmac-app
  namespace: hmac
spec:
  replicas: 1
  selector:
    matchLabels:
      app: hmac-app
  template:
    metadata:
      labels:
        app: hmac-app
    spec

Cloud-Native Microservices With Kubernetes - 2nd Edition

A Comprehensive Guide to Building, Scaling, Deploying, Observing, and Managing Highly-Available Microservices in Kubernetes

Enroll now to unlock all content and receive all future updates for free.