Skip to main content

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

◈ DIAGRAM
+-----------------------------+
| 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

Bash
# Create from literal values
kubectl 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 disk
kubectl create configmap nginx-config \
--from-file=nginx.conf \
-n production
# View what was created
kubectl get configmap app-config -n production -o yaml

Using ConfigMap as Environment Variables

YAML
# deployment.yaml — inject ConfigMap values as env vars
spec:
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_HOST

Using ConfigMap as a Mounted File

YAML
# Mount nginx.conf from ConfigMap into the container filesystem
spec:
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 file

Inspecting and Updating ConfigMaps

Bash
# List all ConfigMaps in a namespace
kubectl get configmaps -n production
# View contents of a specific ConfigMap
kubectl describe configmap app-config -n production
# Edit a ConfigMap in place
kubectl edit configmap app-config -n production
# Delete and recreate (common in CI/CD pipelines)
kubectl delete configmap app-config -n production
kubectl create configmap app-config --from-file=config/ -n production
# Force a rolling restart after ConfigMap update
kubectl rollout restart deployment/api-server -n production

Troubleshooting 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
Bash
# Verify env vars are correctly injected inside a running pod
kubectl exec -it <pod-name> -n production -- env | grep APP_ENV
# Check what keys exist in a ConfigMap before referencing them
kubectl get configmap app-config -n production -o jsonpath='{.data}' | jq
Security

Never 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.

Remember

Updating 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 restart or use a controller like Reloader to watch ConfigMap changes and trigger rolling restarts automatically.

Tip

In Razorpay or Hotstar-scale clusters with dozens of services, manage ConfigMaps through Helm values.yaml files instead of manually with kubectl create. This keeps config versioned in Git and makes environment promotion (staging -> production) a controlled, auditable process.

Common Mistake

Using envFrom to inject all ConfigMap keys globally, then not knowing which keys are available inside the pod. This causes hard-to-debug missing variable errors. Prefer explicit env.valueFrom.configMapKeyRef entries 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.