What are ConfigMaps and Secrets in Kubernetes and how are they different?
Quick Answer
ConfigMaps store non-sensitive configuration data (feature flags, database hostnames, config files) as key-value pairs. Secrets store sensitive data (passwords, API keys, TLS certificates) with base64 encoding. Both inject configuration into Pods without baking it into container images.
Detailed Answer
Think of this like moving into a new apartment. The landlord gives you two things: a welcome packet (ConfigMap) with the WiFi name, trash pickup schedule, and building rules — information that's useful but not sensitive, and you'd stick it on the fridge for anyone to read. They also give you a sealed envelope (Secret) with the front door keypad code, mailbox key number, and garage PIN — information you'd keep in a locked drawer because if someone else got it, they could access your stuff.
ConfigMaps hold non-sensitive configuration that your application needs: database hostnames, feature flag values, logging levels, or even entire configuration files like nginx.conf. They're stored in etcd as plain text, visible to anyone with RBAC read access, and show up in full when you run kubectl describe configmap. You inject them into Pods either as environment variables (good for simple key-value pairs) or as mounted files in a volume (good for entire config files that your application reads from disk).
Secrets are structurally almost identical to ConfigMaps — they're also key-value pairs stored in etcd. The critical differences: Secret values are base64 encoded (NOT encrypted — base64 is just encoding, anyone can decode it with echo <value> | base64 -d), they're excluded from kubectl get output by default to prevent accidental exposure in terminal logs, and Kubernetes can be configured to encrypt them at rest in etcd using an EncryptionConfiguration. When mounted into a Pod, Secrets are stored in a tmpfs (in-memory filesystem) so they're never written to the node's physical disk.
Both ConfigMaps and Secrets can be updated without restarting Pods — but only when mounted as volumes. Kubernetes automatically propagates changes to mounted volumes within about 60 seconds (the kubelet sync period). However, environment variables from ConfigMaps or Secrets are set at Pod startup and NEVER updated — you must restart the Pod to pick up changes. This is a common source of confusion in production.
The biggest security gotcha with Secrets: by default, they are NOT encrypted in etcd — they're only base64 encoded, which provides zero security. Anyone with etcd access can read all your Secrets in plain text. For production clusters, you must either enable etcd encryption at rest (using an EncryptionConfiguration), or better yet, use an external secrets manager (AWS Secrets Manager, HashiCorp Vault, or the External Secrets Operator) that stores the actual secret values outside the cluster and injects them at runtime.