Kubernetes ConfigMap vs Secret: Configuration, Sensitive Data, and Safe Usage
Understand when to use ConfigMap or Secret in Kubernetes, how they reach Pods, and which practices reduce config drift and secret exposure.
ConfigMap and Secret solve a basic but important problem: how do you keep images immutable while still changing configuration and credentials across environments?
The short answer is simple: regular configuration goes in ConfigMaps, sensitive data goes in Secrets. The operational details are where most teams get into trouble.
What each one is for
- ConfigMap: non-sensitive configuration such as feature flags, log levels, and app settings.
- Secret: sensitive data such as passwords, API tokens, and certificates.
Both are namespace-scoped and both are consumed by workloads, but they should not be treated with the same risk model.
Why this matters
If you bake environment-specific values into images, every configuration change becomes an image rebuild. That slows release flow and makes secret rotation awkward.
ConfigMaps and Secrets let you separate deployment artifacts from runtime configuration.
Minimal examples
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
LOG_LEVEL: "info"
---
apiVersion: v1
kind: Secret
metadata:
name: db-secret
type: Opaque
stringData:
DB_PASSWORD: "changeme"
How workloads consume them
There are two main patterns.
Environment variables
Good for:
- small configuration values
- app frameworks that read env directly
- simple deployment patterns
But remember: environment variables are usually only read at process start, so updates often require restart.
File mounts
Good for:
- config files
- certificates and keys
- applications that can reload file-based config
Mounted files can update on disk, but your app still has to notice and reload them.
Environment variable example
envFrom:
- configMapRef:
name: app-config
- secretRef:
name: db-secret
Or specific keys:
env:
- name: LOG_LEVEL
valueFrom:
configMapKeyRef:
name: app-config
key: LOG_LEVEL
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-secret
key: DB_PASSWORD
File mount example
volumes:
- name: config
configMap:
name: app-config
- name: secret
secret:
secretName: db-secret
volumeMounts:
- name: config
mountPath: /etc/app/config
readOnly: true
- name: secret
mountPath: /etc/app/secret
readOnly: true
Config changes and rollout behavior
This is where many teams get surprised.
- mounted files can update without recreating the Pod
- env vars usually require Pod restart
- applications may still need reload support even if files update underneath
That is why many teams use checksum annotations on Deployments to trigger controlled rollouts when config changes.
ConfigMap vs Secret: what not to do
Do not treat Secret as encrypted by default
Secrets are base64-encoded, not meaningfully protected by that encoding alone. Encryption at rest and access control still matter.
Do not dump large blobs into ConfigMaps
ConfigMaps are not object storage. Large artifacts belong somewhere else.
Do not make every workload read every Secret
That turns compromise of one Pod into access to far more sensitive data than necessary.
Namespace and scoping behavior
ConfigMaps and Secrets are namespace-scoped. The Pod and the referenced object need to be in the same namespace unless you build a higher-level sync mechanism yourself.
This sounds obvious, but cross-namespace assumptions cause a lot of quiet failures.
Security habits worth adopting early
- enable encryption at rest for Secrets
- restrict access with RBAC
- keep Secret scope narrow
- avoid committing Secrets to git
- prefer external secret managers for mature production setups
Secret hygiene is not just about secrecy. It is also about reducing blast radius.
Debugging sequence
Start here:
kubectl describe pod <pod-name>
kubectl get configmap app-config -o yaml
kubectl get secret db-secret -o yaml
kubectl exec -it <pod-name> -- ls -l /etc/app/config
kubectl exec -it <pod-name> -- ls -l /etc/app/secret
Then ask:
- Is the object in the right namespace?
- Are the key names correct?
- Is the Pod consuming env vars or mounted files?
- Does the app reload config automatically or require restart?
When to choose external secret management
Move beyond native Secrets when:
- you need stronger auditability
- you rotate secrets frequently
- you want central policy and lease control
- multiple clusters need a shared secret workflow
Native Kubernetes Secrets are a good starting point, not always the final answer.
FAQ
Q: Should every secret live in Kubernetes? A: Not necessarily. Kubernetes Secrets are convenient, but external secret systems may be a better fit for higher-security or multi-cluster environments.
Q: Why did my ConfigMap change not affect the app? A: Because the app may only read config at startup, or it may not watch the mounted files for reload.
Q: When should I prefer file mounts over env vars? A: Prefer file mounts for certificates, richer config files, and applications that support file-based reload behavior.
Next reading
- Continue with
kubernetes-quickstart-probes.mdfor rollout-safe behavior. - Read
kubernetes-quickstart-declarative-config.mdfor safer config workflows. - For RBAC and production safety, continue into the tips series.
Wrap-up
ConfigMap and Secret are simple on paper, but operationally they touch rollout behavior, security boundaries, and debugging flow. Treat them as part of the workload contract, not as an afterthought.