K8s ConfigMap Hot Reload Without Restart
Reload Kubernetes ConfigMaps without pod restarts. Volume-mounted auto-update, Reloader controller, checksum annotations.
π‘ Quick Answer: ConfigMaps mounted as volumes auto-update in pods (within 30-60 seconds) without restarts. ConfigMaps used as environment variables do NOT update β pods must be restarted. Use Reloader to trigger rolling restarts automatically when ConfigMaps change.
The Problem
You update a ConfigMap but your pods still use the old config. The behavior depends on how you consume the ConfigMap:
flowchart TB
CM["ConfigMap Updated"] --> VOL{"How is it consumed?"}
VOL -->|"Volume mount"| AUTO["Auto-updated<br/>in 30-60 seconds β
"]
VOL -->|"envFrom / env"| STUCK["NOT updated β<br/>Pod restart required"]
VOL -->|"subPath mount"| STUCK2["NOT updated β<br/>subPath never refreshes"]The Solution
Method 1: Volume Mount (Automatic Refresh)
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
config.yaml: |
log_level: info
max_connections: 100
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
template:
spec:
containers:
- name: app
image: myapp:v1.0
volumeMounts:
- name: config
mountPath: /etc/config # β
Auto-updates!
# Do NOT use subPath β it disables auto-update
volumes:
- name: config
configMap:
name: app-config# Update ConfigMap
kubectl edit configmap app-config
# Change log_level: info β log_level: debug
# Wait ~60 seconds, then verify
kubectl exec my-app-xxx -- cat /etc/config/config.yaml
# log_level: debug β Updated automatically!Important: Your application must watch the file for changes (inotify, polling, or SIGHUP).
Method 2: Reloader Controller (Automatic Restart)
Stakater Reloader watches ConfigMaps/Secrets and triggers rolling restarts:
# Install Reloader
helm repo add stakater https://stakater.github.io/stakater-charts
helm install reloader stakater/reloader -n kube-systemapiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
annotations:
reloader.stakater.com/auto: "true" # β Watch ALL referenced ConfigMaps/Secrets
spec:
template:
spec:
containers:
- name: app
envFrom:
- configMapRef:
name: app-config # Reloader restarts on changeOr watch specific ConfigMaps:
metadata:
annotations:
configmap.reloader.stakater.com/reload: "app-config,feature-flags"
secret.reloader.stakater.com/reload: "db-credentials"Method 3: Checksum Annotation (Native Kubernetes)
Force rolling update when ConfigMap changes β no extra controller needed:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
template:
metadata:
annotations:
# Update this hash when ConfigMap changes
checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}In CI/CD without Helm:
# Compute hash and patch deployment
HASH=$(kubectl get configmap app-config -o jsonpath='{.data}' | sha256sum | cut -d' ' -f1)
kubectl patch deployment my-app -p \
"{\"spec\":{\"template\":{\"metadata\":{\"annotations\":{\"checksum/config\":\"$HASH\"}}}}}"Method 4: Application-Level File Watching
Make your app react to config file changes:
# Python with watchdog
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
class ConfigHandler(FileSystemEventHandler):
def on_modified(self, event):
if event.src_path.endswith("config.yaml"):
print("Config changed, reloading...")
reload_config()
observer = Observer()
observer.schedule(ConfigHandler(), "/etc/config", recursive=False)
observer.start()// Go with fsnotify
watcher, _ := fsnotify.NewWatcher()
watcher.Add("/etc/config")
for event := range watcher.Events {
if event.Op&fsnotify.Write == fsnotify.Write {
log.Println("Config modified, reloading...")
reloadConfig()
}
}β οΈ subPath Disables Auto-Update
# β subPath β NEVER auto-updates
volumeMounts:
- name: config
mountPath: /etc/config/config.yaml
subPath: config.yaml # This BREAKS auto-update!
# β
Directory mount β auto-updates
volumeMounts:
- name: config
mountPath: /etc/config # Whole directory, auto-updatesComparison
| Method | Auto? | Restart? | Delay | Complexity |
|---|---|---|---|---|
| Volume mount | β | No | 30-60s | App must watch files |
| Reloader | β | Rolling restart | ~seconds | Install controller |
| Checksum annotation | Manual | Rolling restart | Immediate | CI/CD integration |
| Environment vars | β | Manual restart | N/A | Simplest |
Common Issues
| Issue | Cause | Fix |
|---|---|---|
| Volume not updating | Using `subPath` | Remove subPath, mount whole directory |
| Env vars not updating | Env vars never hot-reload | Use Reloader or restart pods |
| Long update delay | Kubelet sync period | Default 60s β configurable but not recommended to lower |
| App not picking up changes | App doesnβt watch files | Add file watcher or use SIGHUP pattern |
| Symlink confusion | ConfigMap uses symlinks internally | Read the file, not the symlink |
Best Practices
- Prefer volume mounts over env vars when hot-reload is needed
- Never use subPath if you need auto-update
- Install Reloader for env-var-based configs β simple, reliable
- Add file watching in your application β most production apps support SIGHUP
- Test config changes in staging β malformed config can crash apps
Key Takeaways
- Volume-mounted ConfigMaps auto-update in 30-60 seconds β no restart needed
- Environment variables from ConfigMaps NEVER auto-update β restart required
- `subPath` mounts NEVER auto-update β avoid for dynamic configs
- Reloader controller triggers rolling restarts on ConfigMap/Secret changes
- Checksum annotations in Helm force restart on config changes natively
- Your app must actively watch config files to use hot-reload

Recommended
Kubernetes Recipes β The Complete Book100+ production-ready patterns with detailed explanations, best practices, and copy-paste YAML. Everything in one place.
Get the Book βLearn by Doing
CopyPasteLearn β Hands-on Cloud & DevOps CoursesMaster Kubernetes, Ansible, Terraform, and MLOps with interactive, copy-paste-run lessons. Start free.
Browse Courses βπ Deepen Your Skills β Hands-on Courses
Courses by CopyPasteLearn.com β Learn IT by Doing
