Home / ConfigMap vs Secret
ConfigMap vs Secret in Kubernetes
The question everybody asks in their first week with Kubernetes.
Structurally, a ConfigMap and a Secret are the same kind of object: a map of key-value pairs a Pod can consume as environment variables or as files mounted in a volume. The difference isn't in the mechanics but in the purpose and the treatment Kubernetes gives them.
ConfigMap: non-sensitive configuration
A ConfigMap is for data that compromises nothing if someone reads it: a log level, the URL of an internal service, the contents of an nginx configuration file. It is stored in plain text inside etcd (the cluster database) and in the output of kubectl get configmap -o yaml.
apiVersion: v1
kind: ConfigMap
metadata:
name: my-config
data:
LOG_LEVEL: info
APP_ENV: production
Secret: sensitive data, base64-encoded
A Secret is for passwords, API tokens, TLS certificates or the credentials of a private Docker registry. The most visible technical difference is that values in the data field are stored base64-encoded:
apiVersion: v1
kind: Secret
metadata:
name: my-secret
type: Opaque
data:
password: Y2hhbmdlbWU=
Y2hhbmdlbWU= is "changeme" in base64 — not encrypted. Anyone with permission to read the Secret (or who copies that string and decodes it with echo Y2hhbmdlbWU= | base64 -d) sees the original value in two seconds. Base64 encoding exists only so the value fits into a YAML text field without special-character problems, not as a security measure.
So how do you actually protect a Secret?
- RBAC: use Role/RoleBinding to limit who can
getorlistSecrets in the namespace. - Encryption at rest: a cluster-level setting so etcd doesn't store Secrets in plain text internally (beyond the base64).
- External managers: for serious workloads, tools like HashiCorp Vault or each cloud's native secret manager inject the secret at runtime without it ever living as a Kubernetes object.
The most common Secret types
Opaque is the generic type (arbitrary key-value pairs). kubernetes.io/tls expects exactly two keys, tls.crt and tls.key, and Ingresses use it to serve HTTPS. kubernetes.io/dockerconfigjson stores private Docker registry credentials in the format a Pod's imagePullSecrets field expects.
Our Kubernetes Secret generator base64-encodes the values directly in your browser — it supports all three types above — without any data leaving your machine.