04 - ConfigMaps & Secrets
Why this matters
This is how you separate config from container images — the same image should be deployable to dev/staging/prod with different config, no rebuild.
Read this first — Definitions & Explanations
ConfigMap
Stores non-confidential configuration as key/value data (or files). Inject into Pods as:
- environment variables
- mounted files in a volume
Use ConfigMaps for app config, feature flags, non-secret URLs, templates.
Secret
Stores sensitive data (passwords, tokens, TLS keys). In etcd, Secrets are base64-encoded by default, not strongly encrypted unless you enable encryption at rest. Still treat them as sensitive and restrict RBAC.
How Pods consume them
- env / envFrom — values become environment variables
- volumeMounts — keys become files in a directory
File mounts are often preferred for credentials rotation patterns.
Updates and restarts
Changing a ConfigMap/Secret does not always restart Pods automatically. Env-based injection typically needs a rollout. Some volume mounts can update files in place (with caveats and delays).
Good practice
- Don’t put secrets in ConfigMaps
- Don’t commit Secrets to git in plain form
- Prefer external secret managers in serious production (AWS SM, Vault, etc.)
- Least-privilege RBAC: only the workloads that need a Secret can
getit
Official docs (read for detail)
- ConfigMaps
- Secrets
- Distribute Credentials Securely Using Secrets
- Encrypting Confidential Data at Rest
Key Concepts
- ConfigMap: non-sensitive key-value config
- Secret: base64-encoded (NOT encrypted by default!) sensitive data
- Consuming as env vars vs mounted volumes vs individual keys
- Secret types:
Opaque,kubernetes.io/dockerconfigjson,kubernetes.io/tls - Encryption at rest for Secrets (
EncryptionConfiguration— etcd-level) - Immutable ConfigMaps/Secrets (
immutable: true) for performance + safety - External secret management (mention only here, deep dive later): Sealed Secrets, External Secrets Operator, Vault
YouTube search terms
- "Kubernetes ConfigMaps and Secrets explained"
- "Kubernetes secrets are not encrypted by default"
- "Kubernetes encryption at rest etcd secrets"
Hands-on lab (on prod-sim)
# ConfigMap as env vars
kubectl create configmap app-config --from-literal=LOG_LEVEL=debug --from-literal=FEATURE_X=on
kubectl run cfgtest --image=busybox --restart=Never --env-from=configmap/app-config -- env
kubectl logs cfgtest | grep -E 'LOG_LEVEL|FEATURE_X'
# ConfigMap as mounted volume
kubectl create configmap nginx-conf --from-file=nginx.conf=<(echo "worker_processes 2;")
kubectl run cfgvol --image=nginx --restart=Never --overrides='
{"spec":{"volumes":[{"name":"conf","configMap":{"name":"nginx-conf"}}],
"containers":[{"name":"cfgvol","image":"nginx","volumeMounts":[{"name":"conf","mountPath":"/etc/nginx/conf.d/custom.conf","subPath":"nginx.conf"}]}]}}'
kubectl exec cfgvol -- cat /etc/nginx/conf.d/custom.conf
# Secrets — prove they're only base64, not encrypted
kubectl create secret generic db-creds --from-literal=password=SuperSecret123
kubectl get secret db-creds -o jsonpath='{.data.password}' | base64 -d
kubectl get secret db-creds -o yaml # see it's just base64 in etcd unless encryption-at-rest is on
# Check if this cluster has encryption-at-rest configured (it likely does NOT by default)
minikube ssh -p prod-sim
sudo cat /etc/kubernetes/manifests/kube-apiserver.yaml | grep -i encryption
exit
Notes
(fill in your own words after watching + labbing)