Kubernetes Secret Env Var Snapshot Causes Connection Storm
Secret env vars are snapshots — all pods restarted at once after update, causing DB connection storms and 500s.
- ConfigMap: Stores non-sensitive key-value pairs (feature flags, URLs, config files).
- Secret: Stores sensitive data (passwords, tokens, TLS certs). Values are base64-encoded, NOT encrypted by default.
- Both can be injected as environment variables OR mounted as files into a pod.
- Storage: Both are stored in etcd. Secrets have an additional encryption-at-rest layer (envelope encryption) that must be explicitly enabled.
- Env vars: Simple, but require pod restart for updates. Visible in pod spec and process environment.
- Volume mounts: Support live rotation without restart. File permissions can be restricted.
- Assuming base64 encoding equals encryption. It does not. Anyone with API access can decode a Secret. Envelope encryption must be configured separately via EncryptionConfiguration.
Imagine your app is a coffee machine. The machine itself is the same every time — but the recipe card telling it how strong to brew, and the locked safe holding the Wi-Fi password, those change depending on the kitchen it's in. ConfigMaps are the recipe card: non-sensitive settings anyone can read. Secrets are the locked safe: passwords and keys that only authorized hands should touch. Kubernetes separates these two so you never accidentally display your database password in plain sight on a Post-it note.
Every production Kubernetes cluster eventually hits the same wall: the app image is beautifully immutable, but the configuration it needs — database URLs, feature flags, TLS certificates, API keys — changes constantly across environments. Baking config into the image means rebuilding for a one-line change. Passing it ad-hoc at runtime means no audit trail and no consistency across hundreds of pods.
Kubernetes solves this with two first-class API objects: ConfigMaps for ordinary configuration data and Secrets for sensitive credentials. Both decouple config from the container image, but they have fundamentally different storage mechanisms, access controls, and risk profiles. Understanding that difference — not just syntactically, but at the etcd and kubelet level — is what separates engineers who use these safely from engineers who accidentally expose credentials in pod specs.
This is not a syntax reference. It is for engineers who need to understand how ConfigMaps and Secrets are persisted, why base64 is NOT encryption, when to mount as a file versus inject as an environment variable and why it matters for rotation, how to enable envelope encryption at rest, and the RBAC patterns that keep least-privilege real in a multi-team cluster.
What is Kubernetes ConfigMaps and Secrets?
Kubernetes ConfigMaps and Secrets are core API objects that externalize configuration from container images. ConfigMaps hold non-sensitive data: environment-specific URLs, feature flags, configuration files. Secrets hold sensitive data: passwords, API tokens, TLS private keys. Both are namespaced resources, stored in etcd, and can be consumed by pods as environment variables or mounted volumes.
- base64 is reversible with a single command:
echo <value> | base64 -d. - Security relies on RBAC: who can
getorlistSecrets. - Encryption at rest (envelope encryption) protects against etcd data theft, not API access.
- For real encryption, use external secret stores (Vault, AWS Secrets Manager) with the Secrets Store CSI Driver.
get permission on the secrets resource in that namespace. In practice, this means: cluster admins can see all secrets, CI/CD service accounts often have broad secret access, and compromised pods with mounted service account tokens can potentially read other secrets. Mitigate with: dedicated service accounts per workload, minimal RBAC roles, and disabling automounting of service account tokens (automountServiceAccountToken: false).Storage Internals: How etcd Handles ConfigMaps and Secrets
Both ConfigMaps and Secrets are stored as key-value pairs in etcd through the API Server. The API Server is the only component that talks to etcd directly. When you create a ConfigMap or Secret, the API Server validates it, serializes it, and writes it to etcd. When a kubelet needs to mount a Secret into a pod, it fetches the data from the API Server (which reads from etcd).
- Default: Secrets are stored in plain text in etcd.
- Envelope encryption is opt-in via
--encryption-provider-configflag on the API Server. - Key rotation: Add a new key to the config, restart API Server, then run
kubectl get secrets -A -o json | kubectl replace -f -to re-encrypt. - Cloud KMS integration (e.g., AWS KMS) means you never handle the KEK directly.
etcd_debugging_mvcc_db_total_size_in_bytes metric; large Secrets (e.g., multi-megabyte TLS certs) inflate etcd and degrade performance.Env Var vs Volume Mount: The Rotation Trade-off
ConfigMaps and Secrets can be consumed by pods in two ways: as environment variables or as mounted files. This choice has significant implications for secret rotation, visibility, and application architecture.
- Env vars: Simple, but require pod restart for updates. Values visible in
kubectl describe pod. - Volume mounts: Support live rotation (~60s kubelet sync). Values NOT visible in pod spec.
- subPath mounts: Do NOT auto-update. Avoid for rotating secrets.
- Application must watch or periodically re-read mounted files to detect changes.
--sync-frequency (default 1 minute). This means there is up to a 60-second window where a pod has stale credentials after a Secret update. For security-critical rotations (e.g., revoking a compromised key), this delay is unacceptable. In those cases, perform a rolling pod restart immediately after updating the Secret, rather than relying on the kubelet sync.RBAC and Least Privilege for Secrets
Secret access must be tightly controlled via RBAC. In a multi-team cluster, the default behavior — where any pod's service account can potentially read any Secret in its namespace — is a security anti-pattern.
- Default service account has broad permissions in many clusters.
- Compromised pod + mounted token = potential Secret enumeration.
- Set
automountServiceAccountToken: falseon all pods that do not need API access. - Use
resourceNamesin RBAC to restrict which specific Secrets a service account can read. - Avoid
listverb on Secrets — it allows enumeration of all Secret names.
automountServiceAccountToken: false as a cluster-wide default. Audit RBAC regularly: kubectl auth can-i --list --as=system:serviceaccount:<ns>:<sa> shows exactly what a service account can do.list on Secrets unless absolutely necessary. Treat every service account token as a potential attack vector.External Secret Stores: Beyond Native Kubernetes Secrets
For organizations with mature secret management practices, native Kubernetes Secrets are often insufficient. External secret stores like HashiCorp Vault, AWS Secrets Manager, GCP Secret Manager, and Azure Key Vault provide centralized management, automatic rotation, audit logging, and fine-grained access policies that Kubernetes RBAC alone cannot match.
- Native Secrets: Simple, no external dependencies, but limited rotation and audit capabilities.
- External stores: Centralized lifecycle, audit logs, automatic rotation, cross-cluster sharing.
- Secrets Store CSI Driver: The bridge. Mounts external secrets as files without storing them in etcd.
- External Secrets Operator: Alternative approach. Syncs external secrets INTO native Kubernetes Secrets.
--set syncSecret.enabled=true), and fallback logic in your application.Secret Rotation Failure Causes Database Connection Storm
kubectl rollout restart deployment with maxUnavailable: 1 to avoid simultaneous restarts.
4. Configured the application's connection pool to retry authentication with exponential backoff.- Env vars are a snapshot at pod start time. They do NOT update when the source Secret changes.
- Volume-mounted Secrets support live rotation, but the application must be designed to re-read the file.
- Never restart all pods simultaneously during credential rotation. Use rolling restarts.
- Test your rotation runbook in staging before executing in production.
kubectl describe pod output.defaultMode field in the volume mount. Verify the pod's securityContext.runAsUser can read the file. Default mode is 0644 but can be overridden.kubectl get secret <name> -o json | wc -c to measure size. Consider external secret stores for large payloads.Key takeaways
list on Secrets unless absolutely required.Interview Questions on This Topic
Frequently Asked Questions
That's Kubernetes. Mark it forged?
3 min read · try the examples if you haven't