ConfigMap
A Kubernetes object that stores non-sensitive configuration data as key-value pairs, allowing application configuration to be completely decoupled from container images and injected into pods as environment variables or mounted files at runtime.
ConfigMap — Decoupling Config from Container Images
What is a ConfigMap in Simple Terms?
Without ConfigMaps, every environment change (dev, staging, production) requires building a new Docker image. A ConfigMap lets you store config outside the image and inject it at runtime. Change the config, restart the pod — no new image needed.
How ConfigMap Fits Into a Deployment
+-----------------------------+| Docker Image | <- baked once, never changes per env+-----------------------------+ | v+-----------------------------+| ConfigMap | <- env-specific values injected here| APP_ENV=production || LOG_LEVEL=info || REDIS_HOST=10.0.1.50 |+-----------------------------+ | v+-----------------------------+| Running Pod | <- sees config as env vars or files+-----------------------------+Creating a ConfigMap
# Create from literal valueskubectl create configmap app-config \ --from-literal=APP_ENV=production \ --from-literal=LOG_LEVEL=info \ --from-literal=REDIS_HOST=10.0.1.50 \ -n production # Create from a config file on diskkubectl create configmap nginx-config \ --from-file=nginx.conf \ -n production # View what was createdkubectl get configmap app-config -n production -o yamlUsing ConfigMap as Environment Variables
# deployment.yaml — inject ConfigMap values as env varsspec: containers: - name: api-server image: registry.razorpay.in/api-server:v2.4.1 envFrom: - configMapRef: name: app-config # Injects ALL keys as env vars at once env: - name: DB_HOST # Inject a single key selectively valueFrom: configMapKeyRef: name: app-config key: REDIS_HOSTUsing ConfigMap as a Mounted File
# Mount nginx.conf from ConfigMap into the container filesystemspec: volumes: - name: nginx-config-vol configMap: name: nginx-config # ConfigMap name to mount containers: - name: nginx image: nginx:1.25 volumeMounts: - name: nginx-config-vol mountPath: /etc/nginx/nginx.conf subPath: nginx.conf # Mount only this key as a single fileInspecting and Updating ConfigMaps
# List all ConfigMaps in a namespacekubectl get configmaps -n production # View contents of a specific ConfigMapkubectl describe configmap app-config -n production # Edit a ConfigMap in placekubectl edit configmap app-config -n production # Delete and recreate (common in CI/CD pipelines)kubectl delete configmap app-config -n productionkubectl create configmap app-config --from-file=config/ -n production # Force a rolling restart after ConfigMap updatekubectl rollout restart deployment/api-server -n productionTroubleshooting ConfigMap Issues
| Symptom | Likely Cause | Fix |
|---|---|---|
| Env var missing in pod | Wrong key name in configMapKeyRef |
kubectl describe configmap to verify exact key names |
| Old config still in pod | ConfigMap updated but pod not restarted | kubectl rollout restart deployment/<name> |
| Mounted file not updating | Volume mount caches aggressively | Restart pod or use Reloader controller |
| ConfigMap not found | Wrong namespace | Confirm ConfigMap and pod are in same namespace |
# Verify env vars are correctly injected inside a running podkubectl exec -it <pod-name> -n production -- env | grep APP_ENV # Check what keys exist in a ConfigMap before referencing themkubectl get configmap app-config -n production -o jsonpath='{.data}' | jqSecurityNever store passwords, API keys, or tokens in a ConfigMap. ConfigMaps are stored as plain text in etcd and visible to anyone with cluster read access. Use Kubernetes Secrets or an external vault like HashiCorp Vault for sensitive values.
RememberUpdating a ConfigMap does NOT automatically restart pods. Running pods continue using the old values in memory. You must either restart the deployment manually with
kubectl rollout restartor use a controller like Reloader to watch ConfigMap changes and trigger rolling restarts automatically.
TipIn Razorpay or Hotstar-scale clusters with dozens of services, manage ConfigMaps through Helm
values.yamlfiles instead of manually withkubectl create. This keeps config versioned in Git and makes environment promotion (staging -> production) a controlled, auditable process.
Common MistakeUsing
envFromto inject all ConfigMap keys globally, then not knowing which keys are available inside the pod. This causes hard-to-debug missing variable errors. Prefer explicitenv.valueFrom.configMapKeyRefentries for critical config values — it makes dependencies visible in the deployment spec.
Frequently Asked Questions
Why not just bake configuration into the container image instead of using a ConfigMap?
Baking config into the image means every environment (dev, staging, prod) needs its own image build just to change a value like a log level or feature flag — slow and wasteful. A ConfigMap decouples that: the same image runs everywhere, and the ConfigMap injected as environment variables or a mounted file supplies the environment-specific values. This also means config changes don't require a rebuild, only a redeploy or, with mounted files, sometimes not even that.
What's a common ConfigMap gotcha in production?
Updating a ConfigMap doesn't automatically restart pods using it as environment variables — env vars are only read at container start, so a pod keeps running with stale values until it's manually restarted or rolled. Mounted ConfigMap volumes do eventually sync updated file contents into the pod (with a delay), which is why teams designing for live-reload use volume mounts with a watcher, not environment variables, for values that need to change without a redeploy.