What is a ConfigMap, and how do you use it to inject configuration into a Pod?
Quick Answer
A ConfigMap stores non-sensitive configuration data (key-value pairs or whole config files) as a Kubernetes object, decoupled from the container image itself, so the same image can be deployed with different configuration across environments. It can be consumed by a Pod as environment variables, as command-line arguments, or as files mounted into the container's filesystem via a volume.
Detailed Answer
Why decouple configuration from the image
Baking environment-specific configuration (database hostnames, feature flags, log levels) directly into a container image means building a separate image per environment — defeating the whole point of a container image being an immutable, promotable artifact that's identical from dev through production. A ConfigMap lets the same image run in every environment, with only the ConfigMap's contents differing.
Creating a ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
LOG_LEVEL: "info"
MAX_CONNECTIONS: "100"
app.properties: |
feature.new_checkout=true
cache.ttl_seconds=300
Consuming it as environment variables
spec:
containers:
- name: app
image: myapp:1.0
envFrom:
- configMapRef:
name: app-config # every key becomes an env var: LOG_LEVEL, MAX_CONNECTIONS
env:
- name: LOG_LEVEL # or reference just one specific key
valueFrom:
configMapKeyRef:
name: app-config
key: LOG_LEVEL
Consuming it as mounted files
spec:
containers:
- name: app
image: myapp:1.0
volumeMounts:
- name: config-volume
mountPath: /etc/app-config
volumes:
- name: config-volume
configMap:
name: app-config
Each key in the ConfigMap becomes a separate file inside /etc/app-config (e.g., /etc/app-config/app.properties), which is the natural approach for configuration formats applications expect to read as a whole file, rather than individual environment variables.
A key behavioral difference between the two consumption methods
Environment variables are only read once, at container start — updating the underlying ConfigMap has no effect on an already-running container's environment variables; the Pod must be restarted (e.g., via a rolling update) to pick up the change. Mounted ConfigMap volumes, by contrast, are updated automatically (after a propagation delay, typically up to a minute or so) without restarting the Pod — the kubelet periodically syncs the mounted files to match the ConfigMap's current content. This distinction matters when deciding how a config change should roll out: as environment variables, a change requires an explicit rollout to take effect (which some teams actually prefer, for predictability); as mounted files, the application needs its own file-watching logic to notice and react to the change live.
What ConfigMaps are not for
ConfigMaps are stored as plain, unencrypted data in etcd (readable by anyone with appropriate RBAC access to view the object) — they're explicitly not meant for passwords, API keys, or other sensitive values. That's what Secrets exist for (see that question), even though a Secret's data is only base64-encoded, not strongly encrypted, by default — the distinction between the two objects is more about signaling intent and enabling separate handling than about ConfigMaps being insecure and Secrets being inherently safe.