Kubernetes - Automating ConfigMap and Secret Reloads with Reloader

Table of Contents

This post is part of our ongoing series of posts for Kubernetes. In this post, we will explore how to automate the reloading of ConfigMaps and Secrets in your Kubernetes clusters using Reloader, a powerful tool designed to streamline application configuration updates without manual intervention.

When working with applications that rely on configuration data or sensitive information stored in ConfigMaps and Secrets, manually restarting pods to apply changes can be tedious, error-prone, and disruptive to service availability. Reloader elegantly solves this problem by automatically detecting configuration changes and triggering rolling updates for the associated deployments, ensuring your applications always run with the latest configurations while maintaining high availability.

1. Setup Reloader

Let’s configure Reloader by creating cluster/default/reloader.yaml. This declarative configuration establishes:

  • A dedicated Reloader namespace
  • The Stakater Helm Repository reference
  • The Reloader Helm Release with appropriate configuration
---
apiVersion: v1
kind: Namespace
metadata:
  name: reloader
---
apiVersion: source.toolkit.fluxcd.io/v1
kind: HelmRepository
metadata:
  name: stakater
  namespace: reloader
spec:
  interval: 30m
  url: https://stakater.github.io/stakater-charts
---
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
  name: reloader
  namespace: reloader
spec:
  releaseName: reloader
  interval: 10m
  chart:
    spec:
      chart: reloader
      version: "v1.3.0"
      interval: 10m
      sourceRef:
        kind: HelmRepository
        name: stakater
        namespace: reloader
  values:
    reloader:
      deployment:
        replicas: 1
        resources:
          requests:
            cpu: "20m"
            memory: "128Mi"
          limits:
            cpu: "100m"
            memory: "128Mi"

After applying this configuration, verify that the Reloader pod is up and running:

kubectl -n reloader get pods

NAME                                READY   STATUS    RESTARTS   AGE
reloader-reloader-666577c76-76gph   1/1     Running   0          56s

The output confirms that Reloader has been successfully deployed and is operational in your cluster.

2. Validate Setup with a Practical Example

To demonstrate Reloader’s capabilities in action, we’ll update the sample application we created in Kubernetes GitOps with FluxCD - Part 3 - Automated Image Updates to consume a ConfigMap value injected through an environment variable.

2.1 Define a ConfigMap

First, let’s define a ConfigMap by creating apps/sample-app/message-config.yaml:

apiVersion: v1
kind: ConfigMap
metadata:
  name: message-config
  namespace: default
data:
  message: "Message before config change"

2.2 Update Deployment Configuration

Next, we’ll modify our deployment manifest in apps/sample-app/deployment.yaml to add the Reloader annotation and inject our configuration as an environment variable:

apiVersion: apps/v1
metadata:
  name: sample-app
  namespace: default
+ annotations:
+   reloader.stakater.com/auto: "true"
kind: Deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: sample-app
  template:
    metadata:
      labels:
        app: sample-app
    spec:
      imagePullSecrets:
        - name: github-registry-secret
      containers:
        - name: sample-app
+         env:
+           - name: MESSAGE
+             valueFrom:
+               configMapKeyRef:
+                 key: message
+                 name: message-config
          image: ghcr.io/kiriapurv/k8s-sample-app:main-29e96d2a-1740565130 # {"$imagepolicy": "default:sample-app-main-policy"}
          imagePullPolicy: Always
          ports:
            - containerPort: 8080
          resources:
            requests:
              memory: "128Mi"
              cpu: "50m"
            limits:
              memory: "128Mi"
              cpu: "150m"

The critical addition here is the reloader.stakater.com/auto: "true" annotation, which instructs Reloader to monitor this deployment for configuration changes.

2.3 Update Kustomization File

We need to update the apps/sample-app/kustomization.yaml to include our new ConfigMap:

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
  - deployment.yaml
  - service.yaml
  - ingress.yaml
+ - message-config.yaml

Now we can commit and push these changes to our GitOps repository, allowing FluxCD to synchronize them to our cluster. This will inject the environment variable into our application pods.

2.4 Modify Application Code

To make our application respond with the configured message, let’s update our Controller code:

package com.kiriyard;

import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
import org.eclipse.microprofile.config.inject.ConfigProperty;

@Path("/")
public class K8SampleApplication {

    private static final int VERSION = 2;

+   @ConfigProperty(name = "MESSAGE", defaultValue = "No message found")
+   private String configMessage;
+
    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String index() {
-       return "Greetings From K8S App : Version %d - Config Message:  %s".formatted(VERSION, configMessage);
+       return "Greetings From K8S App : Version %d".formatted(VERSION);
    }
}

After building and deploying this code update, let’s verify the application’s response:

curl https://sample-app.******

Greetings From K8S App : Version 2 - Config Message:  Message before config change

Perfect! Our application is now successfully reading and displaying the message from our ConfigMap.

2.5 Test Reloader’s Automation

Now for the real test of Reloader’s functionality: let’s modify our ConfigMap and observe if the deployment automatically updates without manual intervention.

Update apps/sample-app/message-config.yaml

apiVersion: v1
kind: ConfigMap
metadata:
  name: message-config
  namespace: default
data:
- message: "Message before config change"
+ message: "Message after config change"

After committing and pushing this change to your GitOps repository, wait a moment for the synchronization to occur, then check the application’s response:

curl https://sample-app.******

Greetings From K8S App : Version 2 - Config Message:  Message after config change

Success! Our deployment has been automatically updated with the new configuration value, and the application is now displaying the updated message. Reloader detected the ConfigMap change and triggered a rolling update of our deployment without any manual intervention.

3. Advanced Reloader Features

While our example demonstrated the basic functionality, Reloader offers several advanced features:

  • Selective monitoring: Use annotations like reloader.stakater.com/search: "true" to monitor specific ConfigMaps or Secrets or specify secret.reloader.stakater.com/reload to reload on certain selected ConfigMap or Secret only.
  • Namespace monitoring: Configure Reloader: to watch specific namespaces with reloader.namespaceSelector helm value
  • Rolling update strategy customization: Control how pods are replaced during updates ( e.g. env-vars vs annotations)

For more detailed information on these advanced features, refer to the Reloader documentation.

References