A Kubernetes ConfigMap is an API object that stores non-sensitive config data as key-value pairs, per the Kubernetes docs. Mount as env vars (envFrom) or files (volumeMounts) in pod specs. The team that uses ConfigMaps for app config (URLs, feature flags, log levels) keeps secrets in Secrets or external managers. The team that conflates ConfigMap with Secrets has plaintext-sensitive data in their config.
Table of contents
- Creating a ConfigMap
- The YAML form
- Mounting as env vars
- Mounting as files
- ConfigMap vs Secret
- Updates and reload
- Immutable ConfigMaps
- FAQ
Creating a ConfigMap
From literal values:
kubectl create configmap app-config \
--from-literal=DATABASE_URL=postgres://db/app \
--from-literal=LOG_LEVEL=info \
--from-literal=FEATURE_FLAG_X=true
From a file:
kubectl create configmap app-config --from-file=app.properties
The team that uses --from-literal for small configs and --from-file for larger has the right ergonomics.
The YAML form
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
DATABASE_URL: postgres://db/app
LOG_LEVEL: info
app.properties: |
key1=value1
key2=value2
The team that uses YAML has version-controlled config (gitops-friendly).
Mounting as env vars
apiVersion: apps/v1
kind: Deployment
spec:
template:
spec:
containers:
- name: app
envFrom:
- configMapKeyRef:
name: app-config
# Or specific keys
env:
- name: LOG_LEVEL
valueFrom:
configMapKeyRef:
name: app-config
key: LOG_LEVEL
The team that uses envFrom gets all keys as env vars. The team that picks specific keys has explicit dependency.
Mounting as files
volumes:
- name: config
configMap:
name: app-config
containers:
- name: app
volumeMounts:
- name: config
mountPath: /etc/config
Files appear at /etc/config/ with each key as a file. The team that uses file mounts has apps that read config from files (e.g., nginx.conf, application.properties).
ConfigMap vs Secret
ConfigMap: non-sensitive, plaintext, no encryption. Secret: sensitive, base64, optionally encrypted-at-rest.
The team that uses ConfigMap for URLs, log levels, feature flags. The team that uses Secret for API keys, passwords, tokens. The team that conflates them has secrets in ConfigMaps (visible to anyone with get configmap permission).
Updates and reload
ConfigMap updates don’t automatically restart pods. The team that needs hot-reload:
- Volume mount: kubelet updates the file (~1 minute), apps must watch and reload.
- Env var: pods need restart to pick up new value.
The team that uses Reloader (or similar) has automatic pod restart on ConfigMap change. The team that uses volume mounts and watches files (via fsnotify, inotify) has sub-second reload.
Immutable ConfigMaps
In K8s 1.20+:
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
immutable: true
data:
LOG_LEVEL: info
Immutable ConfigMaps can’t be changed after creation (must be deleted and recreated). The team that uses immutable ConfigMaps has faster pod startup (no watch overhead) and prevents accidental changes.
FAQ
What’s the size limit on ConfigMaps?
1 MB (etcd limit). The team that has configs larger than 1 MB uses files on a PersistentVolume or external config service.
Can I edit a ConfigMap in place?
Yes with kubectl edit configmap. The team that uses this for quick changes; the team that uses gitops (Argo CD, Flux) updates via git commits.
Are ConfigMap updates atomic?
Yes - the entire ConfigMap is updated at once. The team that updates multiple keys in one operation has atomic updates.
Do pods auto-restart on ConfigMap change?
No - pods need explicit restart or hot-reload. The team that uses Reloader (or annotations like reloader.stakater.com/auto: "true") has automatic restart.
What’s the difference between ConfigMap and Downward API?
ConfigMap: external config, can be updated without pod restart. Downward API: pod metadata (labels, env, etc.) injected directly into the pod. The team that uses both has external config + dynamic pod metadata.
If you are sizing the infrastructure for the kind of project this post covers, the RunxBuild hosting calculator is the right place to model the line items. The compute, the memory, the storage, the bandwidth, the database - each one is a separate number, and the team’s mental model for the platform is the sum of those numbers. The RunxBuild dashboard is where the team sees the actual usage in one place.
Useful related references: