KubernetesXX · ConfigurationConfiguration
Update behaviour — env vars are frozen, files are eventually consistent
What you'll learn
- Explain the asymmetry between env-var and file consumption
- Design patterns that ensure ConfigMap changes take effect
- Use the hash annotation pattern for automatic rollouts
- Avoid the common production failure: a config change that does nothing
Prerequisites
Verified against Kubernetes 1.34.x · kubeadm 1.34.x · kubectl 1.34.x · etcd 3.6.x · CoreDNS 1.11.x · containerd 1.7.x / 2.x · 2026-08-16
The ConfigMap update semantics depend entirely on the
consumption pattern. Env vars are frozen at container
start; the running process sees the value from /proc/<pid>/ environ until the Pod restarts. Files are updated by the
kubelet within syncPeriod; the running process must
detect the change and reload. This asymmetry is the source
of the most common production ConfigMap mistake: a change
that does nothing.
The asymmetry
flowchart TB
A[ConfigMap changed] --> B{Consumption}
B -->|envFrom / valueFrom| C["Env vars FROZEN<br/>at container start"]
B -->|volumeMount| D["Files UPDATED<br/>within syncPeriod"]
C --> E["Running process sees<br/>old values<br/>until restart"]
D --> F["Running process sees<br/>new values<br/>after reload"]
The Kubelet does not restart the Pod on ConfigMap change. The Deployment controller does not roll the Pod on ConfigMap change (ConfigMaps are not in the Pod template’s hash). The result:
- Env vars: the change has no effect on the running Pod. The Pod must be restarted (typically via a rollout).
- Files: the change takes effect within ~60 seconds, but only if the application reloads.
Patterns that ensure changes take effect
Pattern 1: trigger a manual rollout
kubectl create configmap web-config -n prod \
--from-literal=log_level=debug \
-o yaml --dry-run=client | kubectl apply -f -
kubectl rollout restart deployment/web -n prod
kubectl rollout status deployment/web -n prod
The operator makes the ConfigMap change, then explicitly restarts the Deployment. The Pods are recreated with the new env vars.
Pattern 2: hash annotation
spec:
template:
metadata:
annotations:
config.checksum/web: <sha256 of the ConfigMap>
A controller (Reloader, Argo CD, Flux) computes the checksum and updates the annotation when the ConfigMap changes. The Deployment’s template hash changes; the rollout triggers automatically.
flowchart LR
A[ConfigMap updated] --> B[Reloader controller]
B --> C[Compute new sha256]
C --> D{Annotation<br/>changed?}
D -->|yes| E["Update Deployment<br/>template annotation"]
E --> F["Deployment controller<br/>sees template hash change"]
F --> G[Rollout triggered]
G --> H["Pods recreated with<br/>new ConfigMap"]
Pattern 3: file mount with reload
volumeMounts:
- name: config
mountPath: /etc/web
volumes:
- name: config
configMap:
name: web-config
The kubelet syncs the mount within syncPeriod (default
~60s). A sidecar or the application itself detects the
file change and reloads:
# Sidecar that watches the file and SIGHUPs the process
while true; do
inotifywait -e modify /etc/web/app.conf
kill -HUP $(pidof web-app)
done
No rollout; no restart; the change takes effect within ~60 seconds + the application’s reload time.
When to use which pattern
flowchart TB
A[ConfigMap change] --> B{Application<br/>reads env vars<br/>or files at startup?}
B -->|env vars| C["Use Pattern 1 or 2<br/>Rollout required"]
B -->|files with reload| D["Use Pattern 3<br/>No rollout needed"]
C --> E["Hash annotation or<br/>manual rollout"]
D --> F["Sidecar or<br/>app-level reload"]
| Pattern | Use case | Trade-off |
|---|---|---|
| Manual rollout | Env-var consumers; infrequent config changes | Operator must remember to roll |
| Hash annotation | Auto-roll on any config change | Adds a controller; brief downtime |
| File mount + reload | Hot-reload config; zero-downtime changes | App must support reload |
Failure modes
Failure 1: ConfigMap changed, env var consumer
flowchart LR
A["Operator: change<br/>log_level=debug"] --> B[ConfigMap updated]
B --> C["Operator expects<br/>Pods to log at debug"]
C --> D["Pods continue<br/>at log_level=info"]
D --> E["Operator confused<br/>\"config not applied\""]
E --> F[Ticket opened]
F --> G["Engineer: \"did you<br/>roll the Deployment?\""]
G --> H[Operator rolls]
H --> I[Change takes effect]
This is the most common ConfigMap ticket. The fix is in the runbook: every ConfigMap change is paired with a rollout command. Or the hash annotation pattern eliminates the manual step.
Failure 2: File mount without reload
The kubelet updates the file; the application does not detect it. The application continues with the old config. This is harder to detect because there is no obvious “restart needed” symptom.
The fix: instrument the application to log when it loads its config. A “loaded at” timestamp in the logs surfaces the staleness.
logger.info("config loaded at %s from %s",
time.ctime(), os.stat('/etc/web/app.conf').st_mtime)
Failure 3: File mount with crash on reload
An application that crashes when reloading a malformed
config. A typo in the ConfigMap takes every Pod down. The
fix: validate the config before applying it (a CI step
that kubectl apply --dry-run=server and tests the
application’s startup with the new config).
Sync period tuning
kubelet --config=/etc/kubernetes/kubelet.yaml \
--config-sync-period=10s
The kubelet’s syncPeriod determines how often it checks
for ConfigMap/Secret changes. The default is 60s; tighter
periods (10s, 5s) reduce the staleness window but cost more
API server traffic.
For workloads that need rapid config updates (a rate limit that must change within seconds of an incident), tighten the syncPeriod. For workloads that change config rarely (feature flags toggled weekly), the default is fine.
Quiz
Knowledge check · 4 questions
Q1. When a ConfigMap is updated and consumed via envFrom, what happens to a running Pod?
Q2. Mounted ConfigMap files update automatically without any application-side reload - the kubelet handles the reload.
Q3. Your team deploys a hash annotation controller (Reloader) that updates a Deployment annotation when a ConfigMap changes. The Deployment's template hash changes; the rollout triggers. Diagnose and verify.
ConfigMap web-config updated. Reloader updates Deployment web's annotation config-checksum/web to the new sha. The Deployment rolls.
Q4. Why does a manual rollout after a ConfigMap change require operator discipline, and what is the automated pattern?
Passing score: 75%. Answers are checked in this browser.
Production discipline
- Document the consumption pattern. A ConfigMap manifest without a comment about how it is consumed is half a manifest.
- Pair env-var changes with a rollout. A runbook entry
that says “change the ConfigMap then
kubectl rollout restart” is the minimum. - Use the hash annotation pattern for high-volume config changes. A controller that updates the annotation eliminates the manual step.
- Verify the application’s reload path. A file mount without reload is a config change that does nothing.
- Validate before applying. A ConfigMap that crashes every Pod on reload is an incident waiting to happen.
The ConfigMap update semantics are deterministic. The discipline is in the consumption pattern and the rollout trigger. Operators who understand the asymmetry have ConfigMaps that work.