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
 1---
 2apiVersion: v1
 3kind: Namespace
 4metadata:
 5  name: reloader
 6---
 7apiVersion: source.toolkit.fluxcd.io/v1
 8kind: HelmRepository
 9metadata:
10  name: stakater
11  namespace: reloader
12spec:
13  interval: 30m
14  url: https://stakater.github.io/stakater-charts
15---
16apiVersion: helm.toolkit.fluxcd.io/v2
17kind: HelmRelease
18metadata:
19  name: reloader
20  namespace: reloader
21spec:
22  releaseName: reloader
23  interval: 10m
24  chart:
25    spec:
26      chart: reloader
27      version: "v1.3.0"
28      interval: 10m
29      sourceRef:
30        kind: HelmRepository
31        name: stakater
32        namespace: reloader
33  values:
34    reloader:
35      deployment:
36        replicas: 1
37        resources:
38          requests:
39            cpu: "20m"
40            memory: "128Mi"
41          limits:
42            cpu: "100m"
43            memory: "128Mi"

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

1kubectl -n reloader get pods
2
3NAME                                READY   STATUS    RESTARTS   AGE
4reloader-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:

1apiVersion: v1
2kind: ConfigMap
3metadata:
4  name: message-config
5  namespace: default
6data:
7  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:

 1apiVersion: apps/v1
 2metadata:
 3  name: sample-app
 4  namespace: default
 5+ annotations:
 6+   reloader.stakater.com/auto: "true"
 7kind: Deployment
 8spec:
 9  replicas: 1
10  selector:
11    matchLabels:
12      app: sample-app
13  template:
14    metadata:
15      labels:
16        app: sample-app
17    spec:
18      imagePullSecrets:
19        - name: github-registry-secret
20      containers:
21        - name: sample-app
22+         env:
23+           - name: MESSAGE
24+             valueFrom:
25+               configMapKeyRef:
26+                 key: message
27+                 name: message-config
28          image: ghcr.io/kiriapurv/k8s-sample-app:main-29e96d2a-1740565130 # {"$imagepolicy": "default:sample-app-main-policy"}
29          imagePullPolicy: Always
30          ports:
31            - containerPort: 8080
32          resources:
33            requests:
34              memory: "128Mi"
35              cpu: "50m"
36            limits:
37              memory: "128Mi"
38              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:

1apiVersion: kustomize.config.k8s.io/v1beta1
2kind: Kustomization
3resources:
4  - deployment.yaml
5  - service.yaml
6  - ingress.yaml
7+ - 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:

 1package com.kiriyard;
 2
 3import jakarta.ws.rs.GET;
 4import jakarta.ws.rs.Path;
 5import jakarta.ws.rs.Produces;
 6import jakarta.ws.rs.core.MediaType;
 7import org.eclipse.microprofile.config.inject.ConfigProperty;
 8
 9@Path("/")
10public class K8SampleApplication {
11
12    private static final int VERSION = 2;
13
14+   @ConfigProperty(name = "MESSAGE", defaultValue = "No message found")
15+   private String configMessage;
16+
17    @GET
18    @Produces(MediaType.TEXT_PLAIN)
19    public String index() {
20-       return "Greetings From K8S App : Version %d - Config Message:  %s".formatted(VERSION, configMessage);
21+       return "Greetings From K8S App : Version %d".formatted(VERSION);
22    }
23}

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

1curl https://sample-app.******
2
3Greetings 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

1apiVersion: v1
2kind: ConfigMap
3metadata:
4  name: message-config
5  namespace: default
6data:
7- message: "Message before config change"
8+ 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:

1curl https://sample-app.******
2
3Greetings 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