ConfigMaps and Secrets
ConfigMaps hold non-confidential configuration and Secrets hold sensitive values, both decoupled from the container image. The same image runs in dev, staging, and prod; only the ConfigMap and Secret change. This is the twelve-factor principle of config-in-the-environment made concrete.
The dangerous misconception to clear up immediately: a Secret is not encrypted. It is base64-encoded, which is encoding, not security. Treating Secrets as genuinely secret requires extra work, covered here and in depth in the security chapter.
ConfigMaps
A ConfigMap is a set of key-value pairs — individual values or whole config files. You consume it two ways: as environment variables injected into a container, or as files mounted into a volume. The choice matters for updates, as the next section explains.
apiVersion: v1 kind: ConfigMap metadata: name: app-config data: LOG_LEVEL: info config.yaml: | server: timeout: 30s
Env Vars vs Volume Mounts
How you consume config changes its update behavior. Values injected as environment variables are read once at container start and never change — updating the ConfigMap does nothing until the Pod restarts. Values mounted as files in a volume are updated in place when the ConfigMap changes (after a short delay), so an app that re-reads the file can pick up changes live. Neither restarts your process for you; the app must either be restarted or watch the file.
This trips people up constantly: they edit a ConfigMap, see the env-var-based app keep using the old value, and assume something is broken. Choose volume mounts when you want live reload, and accept that env vars are effectively immutable for the Pod's lifetime.
Secrets and Why They Aren't Secret
A Secret looks like a ConfigMap but is meant for sensitive data, and Kubernetes treats it slightly differently — it is not written to a Pod's environment in logs, and is held in memory on nodes rather than on disk. But the values are merely base64-encoded, which anyone can decode. By default a Secret sits in etcd in plaintext, and anyone with read access to Secrets in a namespace can read it.
Making Secrets actually secure takes three things, covered fully in the security chapter: enable encryption at rest so etcd does not store plaintext, lock down RBAC so few identities can read Secrets, and consider an external secret store (Vault or a cloud secrets manager) so the sensitive value never lives in etcd at all.
Immutability and Good Hygiene
Marking a ConfigMap or Secret immutable: true prevents accidental edits and lets the kubelet stop watching it, which improves performance at scale. The common pattern is to create a new, versioned ConfigMap per change and update the Deployment to reference it — which also makes the config change a tracked, rollback-able part of the deploy rather than an invisible live edit.
ConfigMap — non-confidential configuration — flags, URLs, whole config files. Plain text by design.
Secret — sensitive values — passwords, tokens, keys. Base64-encoded, not encrypted; needs encryption at rest and tight RBAC to be genuinely safe.
- Treating a Secret as encrypted — it is base64; without encryption at rest, etcd holds it in plaintext.
- Editing a ConfigMap and expecting an env-var-based app to pick it up without a restart.
- Committing Secrets to Git in plain manifests.
- Putting secrets in environment variables, where they leak into logs, crash dumps, and child processes.
- Leaving broad
get secretsRBAC so any workload in a namespace can read every credential.
- Keep all environment-specific config in ConfigMaps and Secrets, never baked into the image.
- Use volume mounts when you want live config reload; know that env vars are fixed for the Pod's life.
- Enable encryption at rest for Secrets and restrict
get secretsto the identities that truly need it. - Prefer an external secret store (Vault, cloud secrets manager) for high-value credentials.
- Version ConfigMaps/Secrets and reference the new one in the Deployment so config changes roll and roll back with the app.
Knowledge Check
In what sense is a Kubernetes Secret NOT secure by default?
- Its values are only base64-encoded and, without encryption at rest, stored in etcd as plaintext
- It is AES-encrypted, but the single decryption key is shared with every Pod
- It can only ever be read by the control-plane components, never by Pods
- It is replicated in plaintext onto the local disk of every single worker node across the whole cluster
You update a ConfigMap consumed as environment variables, but the app keeps using old values. Why?
- Env vars are read once at container start; the Pod must restart to pick up changes
- ConfigMaps are sealed after creation and cannot be edited at all
- The app needs elevated cluster-admin RBAC rights before it can read the freshly updated value
- Environment variables are encrypted and cached by the kubelet for safety
Which approach lets a running app pick up ConfigMap changes without a restart?
- Mounting the ConfigMap as files in a volume and re-reading the file
- Injecting the values as plain environment variables at container start
- Marking the ConfigMap immutable so the kubelet auto-refreshes it
- Storing the values in a Secret object instead of a ConfigMap
You got correct