18.3.2.3 Kubernetes ConfigMaps
A focused guide to Kubernetes ConfigMaps, connecting core concepts with practical Docker and container operations.
Kubernetes ConfigMaps serve a role comparable to Compose's env_file and config-mounting patterns, but with their own specific mechanics, two distinct consumption modes, environment variables versus mounted files, a notable gotcha around updates not automatically restarting consuming pods, and an immutability option worth understanding when migrating Docker-based configuration habits to a Kubernetes manifest.
Two consumption modes: environment variables and mounted files
A ConfigMap's data can be injected into a pod either as individual environment variables or as files mounted into the container's filesystem, mirroring the same two general approaches, environment/env_file versus a mounted configuration file, covered for Docker and Compose generally:
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
LOG_LEVEL: info
config.yaml: |
database:
host: db
envFrom:
- configMapRef:
name: app-config
volumeMounts:
- name: config-volume
mountPath: /app/config
volumes:
- name: config-volume
configMap:
name: app-config
Choosing between the two follows the same general guidance covered for Docker configuration generally: simple, scalar values as environment variables, structured, multi-line content as mounted files.
The critical gotcha: updates do not automatically restart pods
Updating a ConfigMap's content does not automatically restart or recreate the pods consuming it; a pod using the ConfigMap as environment variables will not see the new values until it is genuinely restarted, and even pods using it as a mounted volume, which does eventually pick up file content changes, will not necessarily restart the application process to actually reload that updated configuration:
kubectl edit configmap app-config
kubectl get pods
NAME STATUS AGE
my-api-7d9f8b Running 2 hours
The pod continuing to show as Running with the same age after the ConfigMap edit confirms it has not been restarted and is very likely still operating on the old, pre-update configuration values, which is a meaningfully different behavior than might be assumed coming from a Docker-based workflow where recreating a container to pick up a configuration change is a routine, expected step.
Forcing a rollout when configuration changes
Because updates do not trigger an automatic restart, deliberately triggering a rolling restart of the Deployment after a ConfigMap change is necessary to actually apply the new values:
kubectl rollout restart deployment/my-api
A common, more robust pattern uses Kustomize's configMapGenerator, which generates a uniquely named ConfigMap incorporating a content hash into its name, so that any actual change to the ConfigMap's content automatically produces a new, differently named resource, which in turn changes the Deployment's pod template (since it references the ConfigMap by name) and therefore automatically triggers a rollout:
configMapGenerator:
- name: app-config
literals:
- LOG_LEVEL=info
kubectl apply -k .
This hash-suffix pattern converts an otherwise easy-to-forget manual step, remembering to trigger a rollout after every configuration change, into something that happens automatically and correctly every time the underlying configuration content genuinely changes.
Immutable ConfigMaps
Marking a ConfigMap as immutable prevents any further updates to its content entirely, which both protects against an accidental edit and provides a minor performance benefit, since the API server can skip watching an immutable ConfigMap for changes:
apiVersion: v1
kind: ConfigMap
immutable: true
data:
LOG_LEVEL: info
This pairs naturally with the Kustomize hash-suffix generation pattern, since each genuinely new configuration version becomes its own new, immutable ConfigMap object rather than an existing one being mutated in place, which is a meaningfully different and arguably safer model than Docker's typical pattern of updating a single environment file's content directly in place.
ConfigMaps versus Secrets
ConfigMaps are explicitly intended for non-sensitive configuration; genuine secrets belong in the separate Secret resource type, which receives somewhat different handling (base64 encoding, optional encryption at rest depending on cluster configuration) even though its basic usage pattern, environment variables or mounted files, looks superficially similar to a ConfigMap's:
apiVersion: v1
kind: Secret
type: Opaque
data:
db-password: c3VwZXJzZWNyZXQ=
Maintaining this distinction, the same ordinary-configuration-versus-genuine-secret separation covered for Docker generally, applies identically in the Kubernetes context, with Secret as the appropriate resource type for anything genuinely sensitive rather than placing it within an ordinary ConfigMap.
Common mistakes
- Assuming a ConfigMap update automatically restarts or refreshes the configuration of pods already consuming it, when this requires either a deliberate, manual rollout restart or a hash-suffix generation pattern to trigger automatically.
- Storing genuinely sensitive values within a ConfigMap rather than using the dedicated, separately handled Secret resource type.
- Not adopting Kustomize's
configMapGeneratorhash-suffix pattern, relying instead on remembering to manually trigger a rollout restart after every configuration change. - Choosing environment variable injection for genuinely structured, multi-value configuration that would be considerably clearer expressed as a mounted file instead.
- Not marking a ConfigMap immutable when its content is genuinely meant to be fixed once created, missing both the accidental-edit protection and the minor performance benefit this provides.
Kubernetes ConfigMaps map conceptually onto familiar Docker and Compose configuration patterns, but the specific gotcha that updates do not automatically restart consuming pods, addressed either through manual rollout restarts or the hash-suffix generation pattern, is the single most important behavioral difference worth understanding directly when bringing Docker-based configuration habits into a Kubernetes context.