ConfigMaps and Secrets

Kubernetes · Essentials · 10 min

The same image should run in every environment; only its configuration should differ.

A ConfigMap holds non-secret key-value configuration; a Secret holds sensitive data such as passwords, tokens and TLS keys. Both are namespaced and consumed by pods in two ways:

  • as environment variables: one key with valueFrom.configMapKeyRef/secretKeyRef, or all keys with envFrom,
  • as files: mount the object as a volume and each key becomes a file.

Mounted files are updated automatically (after a short delay) when the object changes; environment variables are fixed at container start, so a change needs a rollout (kubectl rollout restart deploy/web). Mounts using subPath don't update either.

About Secrets: values are base64-encoded, not encrypted. Anyone who can read the Secret object can read the password. Protection comes from RBAC (restrict get/list on secrets), encryption at rest in etcd (configured by the cluster admin; managed services often provide it), and keeping secrets out of git (External Secrets Operator, Sealed Secrets, or a cloud secret manager with the CSI driver).

Create them from literals or files: kubectl create configmap app-config --from-file=app.conf or kubectl create secret generic db --from-literal=password=.... In manifests, stringData lets you write plain text that the API stores base64-encoded.

Mark a ConfigMap or Secret immutable: true when it should never change.

Example

apiVersion: v1
kind: ConfigMap
metadata: {name: app-config}
data: {LOG_LEVEL: info, app.conf: "workers = 4"}
---
apiVersion: v1
kind: Secret
metadata: {name: db}
stringData: {password: s3cr3t}      # stored base64-encoded
---
apiVersion: v1
kind: Pod
metadata: {name: app}
spec:
  containers:
    - name: app
      image: busybox:1.37
      command: ["sh", "-c", "env; cat /etc/app/app.conf; sleep 3600"]
      env:
        - {name: LOG_LEVEL, valueFrom: {configMapKeyRef: {name: app-config, key: LOG_LEVEL}}}
        - {name: DB_PASSWORD, valueFrom: {secretKeyRef: {name: db, key: password}}}
      volumeMounts: [{name: conf, mountPath: /etc/app}]
  volumes:
    - {name: conf, configMap: {name: app-config}}

Remember

  • Inject config as env vars or mounted files
  • Env vars need a restart to change; mounted files update
  • Secrets are base64, not encrypted: protect them with RBAC and encryption at rest

Watch out for

  • Committing Secret manifests with real passwords to git because they look encoded.

Check yourself

  1. You update a ConfigMap used via envFrom. When do running pods see the new values?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: kubernetes.io/docs/concepts/configuration/configmap/