Articles

Kubernetes ConfigMaps vs Secrets: What's the Difference

ConfigMaps store non-sensitive configuration; Secrets store credentials with base64 encoding and tighter access controls. When to use each.

Chisato Chisato · · 4 min read
Server racks with cables in a data center

ConfigMaps and Secrets both inject configuration into Kubernetes pods without baking values into a container image, but they exist for different kinds of data: ConfigMaps hold non-sensitive settings like feature flags and hostnames, while Secrets hold credentials like API keys and database passwords, with access controls and handling that assume the contents are sensitive.

What a ConfigMap holds

A ConfigMap is a key-value store for configuration that’s fine to see in plain text: a log level, a feature toggle, an external service URL, an entire config file mounted as a volume. It’s created from literal values, a file, or a directory, and pods reference it by name.

apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:
  LOG_LEVEL: "info"
  API_TIMEOUT_MS: "5000"

Nothing about a ConfigMap is encrypted or access-restricted beyond ordinary Kubernetes RBAC on the object itself. It’s designed to be readable, and that’s the point — configuration that isn’t sensitive shouldn’t need special handling to change or inspect.

What a Secret holds

A Secret has the same shape as a ConfigMap — key-value pairs, consumable as environment variables or a mounted volume — but it’s stored base64-encoded and Kubernetes treats it with different defaults: it’s excluded from kubectl describe output by default, and cluster operators can layer encryption at rest and tighter RBAC scoping on top of it specifically.

apiVersion: v1
kind: Secret
metadata:
  name: db-credentials
type: Opaque
data:
  username: YWRtaW4=
  password: c3VwZXJzZWNyZXQ=

The critical caveat: base64 is encoding, not encryption. Anyone with access to read the Secret object, or the etcd store behind it, can decode the value trivially — echo c3VwZXJzZWNyZXQ= | base64 -d recovers the plaintext instantly. A Secret’s security comes entirely from restricting who can read the object, not from the encoding itself.

ConfigMaps vs Secrets

ConfigMapSecret
Intended contentsNon-sensitive configCredentials, tokens, keys
Storage encodingPlain textBase64-encoded
Encryption at restNot built inSupported via cluster configuration
Visible in kubectl describeYesNo (values redacted)
RBAC treatmentStandard objectCan be scoped more tightly
Typical consumptionEnv vars, mounted filesEnv vars, mounted files, imagePullSecrets
Update behaviorMounted volumes update live; env vars require restartSame as ConfigMap

Functionally, both objects are consumed the same way by a pod spec. The difference is entirely about how Kubernetes and its ecosystem treat the object once it exists, not the mechanics of injecting it.

How pods consume them

Both ConfigMaps and Secrets can be exposed to a container two ways: as environment variables, or as files in a mounted volume.

env:
  - name: LOG_LEVEL
    valueFrom:
      configMapKeyRef:
        name: app-config
        key: LOG_LEVEL
  - name: DB_PASSWORD
    valueFrom:
      secretKeyRef:
        name: db-credentials
        key: password

Volume-mounted ConfigMaps and Secrets update automatically when the underlying object changes (with a short propagation delay), while values injected as environment variables are fixed at container start and require a pod restart to pick up a change. This matters for anything that needs to rotate a credential without downtime — mounting as a file and having the application watch for changes is the more graceful pattern, though it puts the burden of detecting the update on the application itself.

Secrets aren’t encrypted by default

A common misunderstanding is that a Kubernetes Secret is encrypted the moment it’s created. By default, it isn’t — it’s stored in etcd the same way a ConfigMap is, just base64-encoded on top. Encryption at rest for Secrets is a cluster-level feature (an EncryptionConfiguration with a KMS or AES provider) that has to be explicitly enabled by whoever operates the cluster; it isn’t automatic just because the object type is Secret.

Anyone deploying to a managed Kubernetes service should confirm encryption at rest is actually configured rather than assuming it, and treat cluster RBAC as the real access boundary in the meantime — see what secrets management covers for the broader practice of handling credentials outside of application code entirely, including external secret stores that sync into Kubernetes rather than storing the plaintext there at all.

Best practices

  • Never put credentials in a ConfigMap because it’s convenient — the moment a value needs restricted read access, it belongs in a Secret.
  • Enable encryption at rest for Secrets rather than relying on base64 encoding as a security boundary.
  • Use RBAC to scope which service accounts and users can read Secret objects, not just which namespace they live in.
  • For anything beyond a handful of static credentials, consider an external secrets manager that syncs into Kubernetes, so credentials aren’t duplicated across kubectl history and CI logs.
  • Prefer volume mounts over environment variables for credentials that rotate, since env vars leak more easily into process listings and crash dumps.

Tools like Helm template both object types the same way, so the distinction has to be enforced by convention and review, not by the tooling itself. The same applies to how pods, deployments, and services fit together — Kubernetes gives you the primitives, but which primitive to reach for is a judgment call the platform doesn’t make for you.

The takeaway

ConfigMaps and Secrets share an API shape but serve different purposes: ConfigMaps are for configuration that’s fine to read in plain text, Secrets are for credentials that need restricted access and ideally encryption at rest. Base64 encoding is not encryption — a Secret’s actual protection comes from RBAC and cluster-level encryption at rest, both of which have to be configured deliberately rather than assumed.

Chisato Chisato · · 4 min read

Kubernetes StatefulSets vs Deployments Explained

Deployments manage interchangeable, stateless pods; StatefulSets give each pod a stable identity and storage. When each one actually belongs.

#Kubernetes #DevOps #Cloud
Chisato Chisato · · 5 min read

What Is a Kubernetes Operator?

A Kubernetes operator encodes operational knowledge into software, automating tasks a human admin would otherwise do by hand for a specific application.

#Kubernetes #Cloud #DevOps