skip to content

Config and Secrets

How configuration and credentials reach a running container: ConfigMaps and Secrets projected as environment variables or mounted volumes, immutability, and operators that sync real secrets in from Vault or a cloud store. Reload and leakage traps bite here.

part ofKubernetesoverview, primer and where to startread it →
on this pageshow

questions

24

In Kubernetes, what are the ways a Pod can consume a ConfigMap, and how does injecting values as environment variables differ from mounting the ConfigMap as a volume?

level: juniorimportance: must knowfreq 72%

answer

  1. envFrom = all keys, configMapKeyRef = one key
  2. volume = key becomes a file
  3. env frozen at container start
  4. volume refreshes; subPath does not
  5. missing key → CreateContainerConfigError unless optional

basics

~20 s

Three ways: envFrom to import all keys as env vars, valueFrom.configMapKeyRef to map one key to one env var, or a volume where each key becomes a file. Env values freeze at container start; mounted files are refreshed while the Pod runs.

solid answer

~50 s

A ConfigMap is a namespaced API object holding key/value config data. A Pod consumes it three ways: - **`envFrom.configMapRef`** — every key becomes an environment variable (optionally with a prefix). - **`env[].valueFrom.configMapKeyRef`** — one specific key becomes one named env variable, letting you rename it. - **A `configMap` volume** — each key becomes a file whose contents are the value; `items` lets you project only selected keys to chosen paths. The important difference is lifecycle and shape. Environment variables are resolved once, by the kubelet, when the container starts, so a later edit to the ConfigMap never reaches a running container — you need a Pod restart. Volume-mounted files are kept in sync by the kubelet and change under the running process (unless mounted with `subPath`). Env vars also only carry short scalars; volumes are the way to deliver whole files such as `nginx.conf` or `application.yaml`. Missing key or missing ConfigMap fails container start unless marked `optional: true`.

code

yaml · 41 lines
yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:
  LOG_LEVEL: "debug"
  FEATURE_X: "true"
  application.yaml: |
    server:
      port: 8080
---
apiVersion: v1
kind: Pod
metadata:
  name: demo
spec:
  containers:
    - name: app
      image: example/app:1.0
      envFrom:
        - configMapRef:
            name: app-config
            optional: false
      env:
        - name: APP_LOG_LEVEL
          valueFrom:
            configMapKeyRef:
              name: app-config
              key: LOG_LEVEL
      volumeMounts:
        - name: config
          mountPath: /etc/app
          readOnly: true
  volumes:
    - name: config
      configMap:
        name: app-config
        defaultMode: 0444
        items:
          - key: application.yaml
            path: application.yaml

go deeper

for a junior

Name the three consumption forms and state the core rule: env vars are fixed at container start, volume files can change.

for a middle

Add the mechanics — kubelet resolves env at container creation, keeps volumes in sync via an atomic symlink swap, subPath opts out — plus optional/missing-key failure modes.

for a senior

Discuss which form you standardise on and why, the blast radius of editing a shared ConfigMap, and the fact that live file updates are useless unless the app re-reads or you force a rollout.

for a principal

Frame it as a config-delivery contract: immutable versioned artefacts and forced rollouts versus mutable live config, what that means for rollback and audit, and where per-tenant or per-region configuration should actually live.

## What a ConfigMap is A ConfigMap is a namespaced Kubernetes API object that stores non-confidential configuration as key/value pairs. Text values live under `data`; base64-encoded binary values live under `binaryData`. It exists so that container images stay generic and environment-specific settings (URLs, feature flags, tuning parameters, whole config files) are supplied at run time. A ConfigMap is inert on its own: it does nothing until a Pod in the *same namespace* references it. There is no cross-namespace reference. ## The three consumption forms **1. `envFrom` — bulk import.** Under `envFrom` you list `configMapRef: {name: my-config}` and every key in the ConfigMap becomes an environment variable of the same name. An optional `prefix` is prepended to each name. This is the least typing and the least control: you cannot rename individual keys, and keys that are not valid environment-variable identifiers (for example `app.properties`) are skipped, with the kubelet recording an event — a silent-looking failure that surprises people. **2. `valueFrom.configMapKeyRef` — one key, one variable.** Inside the container's `env` list you name the variable and point at `{name: my-config, key: log_level}`. This decouples the ConfigMap key from the variable name the application expects, and it makes the dependency explicit and greppable. It is the form to prefer in reviewed manifests. **3. `configMap` volume — keys as files.** You declare a volume of type `configMap` and mount it at a path. Each key becomes a file in that directory whose content is the value. With `items` you project only certain keys, rename their paths, and set per-file `mode` bits. `defaultMode` sets permissions for all files (it is an octal number in YAML, so write `0644`). Mounting a ConfigMap volume over a directory that already exists in the image *replaces* the directory's visible contents — a classic way to accidentally wipe `/etc/nginx/conf.d`. ## What actually differs **Update behaviour.** Environment variables are materialised once: the kubelet reads the ConfigMap when it creates the container and passes the values into the process environment. A process's environment cannot be rewritten from outside, so editing the ConfigMap afterwards changes nothing for running containers until they are recreated. Volume-mounted files are different: the kubelet keeps watching the ConfigMap and refreshes the file contents in place (typically within about a minute, bounded by the kubelet sync period plus its cache TTL). The refresh is atomic — the kubelet writes a new timestamped directory and flips a `..data` symlink — so readers never see a half-written file. Two exceptions: a volume mounted with `subPath` is a one-time copy and never updates, and a ConfigMap marked immutable never changes at all. **Shape of the data.** Environment variables suit short scalars. They are visible to anything that can read `/proc/<pid>/environ`, are inherited by child processes, and show up in crash dumps and `kubectl describe pod`. Whole configuration files belong in volumes: a 40-line YAML file as an env var is unreadable and hits practical size limits. **Failure mode.** If the referenced ConfigMap or key does not exist, the container will not start; the Pod sits in `CreateContainerConfigError` and the kubelet retries. Mark the reference `optional: true` when absence should be tolerated. For volumes, a missing ConfigMap keeps the Pod in `ContainerCreating` with a `FailedMount` event. **Who has to cooperate.** A volume update only helps if the application re-reads the file, or a sidecar/`SIGHUP` handler tells it to. Most applications read config once at startup, so in practice teams deliberately force a restart on change (a checksum annotation on the Pod template, or a hashed ConfigMap name) rather than relying on live propagation. ## Choosing Use `configMapKeyRef` env vars for a handful of scalars that twelve-factor-style apps expect. Use a volume for real config files, for anything larger than a line or two, and when you want the option of live reload. Use `envFrom` sparingly — for a ConfigMap that exists solely to feed one workload's environment — and be aware that it makes the container's environment depend on data you cannot see in the Pod spec. ## Practical notes Keys must consist of alphanumerics, `-`, `_` and `.`. The whole object is capped at roughly 1 MiB. Changing a ConfigMap is a live change to shared state: several Deployments may reference the same object, so an edit can affect workloads you were not thinking about.

  • What happens to the Pod if the ConfigMap key referenced by configMapKeyRef does not exist?
    The kubelet cannot build the container's environment, so the container never starts and the Pod reports `CreateContainerConfigError` with an event naming the missing key. The kubelet keeps retrying, so the Pod recovers on its own once the key appears. Setting `optional: true` on the reference makes the variable simply be omitted instead.
  • You mount a ConfigMap volume at /etc/nginx and nginx stops finding its default files. Why?
    A volume mount shadows whatever was at that path in the image, so the directory now shows only the ConfigMap's keys. Mount at a dedicated path such as `/etc/nginx/conf.d/`, or project a single file with `subPath` — accepting that `subPath` mounts never receive updates.
  • Can a Pod reference a ConfigMap in another namespace?
    No. ConfigMap references resolve within the Pod's own namespace only. To share configuration across namespaces you duplicate the object (via your GitOps/templating tooling) or use a controller that replicates it.

Environment variables are like ingredients read off the recipe card the moment you start cooking — rewriting the card later changes nothing. A volume mount is a card taped to the wall that someone can swap while you cook, but only helps if you look up again.

saying these in an interview costs you the question

  • Claiming an environment variable updates when the ConfigMap is edited
  • Thinking a ConfigMap change automatically restarts the Pods that use it
  • Assuming a Pod can reference a ConfigMap in another namespace
  • Believing keys with dots (app.properties) become valid environment variables under envFrom
  • Mounting a ConfigMap over an image directory without realising the original files are hidden

context

open as a page

How can a container in Kubernetes learn its own Pod name, namespace, node name and Pod IP without calling the Kubernetes API server?

level: juniorimportance: must knowfreq 52%

basics

~20 s

Use the downward API: in the Pod spec, set env[].valueFrom.fieldRef with fieldPath metadata.name, metadata.namespace, spec.nodeName or status.podIP. The kubelet fills the values in when it creates the container — no API credentials or network call needed.

open as a page

A teammate says Kubernetes Secrets are safe because "the values are base64-encrypted". What is actually stored, and which protections do and do not apply?

level: juniorimportance: must knowfreq 72%

basics

~20 s

Base64 is encoding, not encryption — anyone can decode it. A Secret's value is stored as-is in etcd, plaintext by default, and readable by anyone with API read access to it. Real protection comes from RBAC, encryption at rest, and limiting who and what can read it.

open as a page

You edit a Kubernetes ConfigMap that a running Deployment already consumes. Which of its consumers pick up the new values without a Pod restart, which never do, and roughly how long does propagation take?

level: middleimportance: must knowfreq 64%

basics

~20 s

Files from a configMap volume are refreshed by the kubelet, typically within about a minute. Environment variables never update, and a volume mounted with subPath never updates. Even a refreshed file only helps if the application re-reads it.

open as a page

How does the External Secrets Operator turn a value in an external secret manager into a Kubernetes Secret, and what does an ExternalSecret's refreshInterval control?

level: middleimportance: must knowfreq 68%

basics

~20 s

A SecretStore or ClusterSecretStore defines provider access. An ExternalSecret names remote keys and a target Secret. The operator fetches the values, writes the Secret, and re-reads the provider every refreshInterval, which defaults to one hour.

open as a page

When giving a container a Kubernetes Secret, what are the trade-offs between injecting it as environment variables (`envFrom` / `valueFrom.secretKeyRef`) and mounting it as a volume?

level: middleimportance: must knowfreq 58%

basics

~20 s

Environment variables are captured once at process start, so rotation needs a Pod restart, and they leak easily via /proc, crash dumps and child processes. Volume files are memory-backed and refreshed by the kubelet within about a minute, so apps that re-read the file pick up rotation — but subPath mounts never update.

open as a page

The shipment-tracking API reads its database password from a Kubernetes Secret synced by the External Secrets Operator: after the password rotates upstream, how do running Pods get the new value without a redeploy?

level: seniorimportance: must knowfreq 58%

basics

~20 s

The operator updates the Secret within one refreshInterval, but only volume-mounted files change in running Pods, never env vars. Mount files the app re-reads, or trigger a rolling restart, and keep both passwords valid until every Pod has switched.

open as a page

How do you create a Kubernetes ConfigMap from the command line using literal values, a file, a directory, and a dotenv-style file — and how do the resulting keys differ in each case?

level: juniorimportance: should knowfreq 48%

basics

~20 s

Use kubectl create configmap NAME with --from-literal=K=V (key is K), --from-file=path (key is the file's basename, value is its content), --from-file=key=path to rename, --from-file=dir/ (one key per file), or --from-env-file=.env (one key per line in the file).

open as a page

Your team deploys to Kubernetes with GitOps: how can Secret values live in Git safely, and how do Sealed Secrets and SOPS differ?

level: juniorimportance: should knowfreq 52%

basics

~20 s

Never commit a plain Secret manifest, because base64 is readable. Sealed Secrets commits a SealedSecret that only an in-cluster controller can decrypt. SOPS commits values encrypted with an external key and decrypts them at deploy time.

open as a page

A Kubernetes ConfigMap is rejected because its data exceeds roughly 1 MiB. Where does that limit come from, and what are your options for delivering configuration larger than that to a container?

level: middleimportance: should knowfreq 36%

basics

~20 s

The API server caps a ConfigMap's data at about 1 MiB because these objects are stored whole in etcd, which has a default per-value size limit. Options: split the data, bake it into the image, mount a PersistentVolume, or fetch it at startup from object storage or a config service.

open as a page

Why can't a Kubernetes Pod expose its entire label set as one environment variable, and what does a downwardAPI volume do differently for labels and annotations?

level: middleimportance: should knowfreq 38%

basics

~20 s

An environment variable is a single string, so fieldRef in the env form only supports single-valued paths — you can select one label by key with metadata.labels['app'], but not the whole map. A downwardAPI volume writes all labels or annotations into a file, and the kubelet refreshes that file when they change.

open as a page

How do you expose a container's own CPU and memory requests and limits to the process running inside it in Kubernetes, and what value is injected when a limit is not set?

level: middleimportance: should knowfreq 40%

basics

~20 s

Use resourceFieldRef in env or in a downwardAPI volume, selecting limits.cpu, limits.memory, requests.cpu or requests.memory, with a divisor to choose units. If the limit is unset, the injected value falls back to the node's allocatable capacity for that resource — which can badly oversize a runtime.

open as a page

How does the Secrets Store CSI Driver deliver external secrets into a Kubernetes Pod, and what does a SecretProviderClass's secretObjects field add?

level: middleimportance: should knowfreq 40%

basics

~20 s

A Pod mounts an inline CSI volume naming a SecretProviderClass. At mount time the driver asks a provider plugin for the values and writes them as files. secretObjects also mirrors them into a Kubernetes Secret, for example for env vars.

open as a page

An application's configuration lives in a Kubernetes ConfigMap that is marked `immutable: true`. Walk through how you ship a configuration change to the running Pods.

level: middleimportance: should knowfreq 30%

basics

~20 s

Create a new ConfigMap under a new name (usually a content-hash or version suffix), update the Pod template to reference that name, and apply. The template change triggers a rolling update by itself, so Pods pick up the new config. Then prune superseded ConfigMaps.

open as a page

In Kubernetes, what does setting `immutable: true` on a ConfigMap or Secret actually do, and why would a team turn it on?

level: middleimportance: should knowfreq 34%

basics

~20 s

The API server then rejects any change to that object's data (and to the flag itself); only metadata like labels can change, and the only way to alter values is to delete and recreate the object. You get accident protection plus much lower kubelet/API-server watch load.

open as a page

Pods in a namespace fail with `ErrImagePull` from a private registry. Explain how Kubernetes authenticates image pulls and how you wire credentials with `imagePullSecrets`.

level: middleimportance: should knowfreq 46%

basics

~20 s

The kubelet pulls images, so it needs credentials: a kubernetes.io/dockerconfigjson Secret in the same namespace as the Pod, referenced either from spec.imagePullSecrets or from the Pod's ServiceAccount. The registry host in the Secret must match the host in the image reference exactly.

open as a page

Kubernetes Secrets carry a `type` field with values such as `Opaque`, `kubernetes.io/tls` and `kubernetes.io/dockerconfigjson`. What does the type actually change, and can you change it later?

level: middleimportance: should knowfreq 42%

basics

~20 s

The type is a contract: the API server validates that the required keys exist for built-in types, and consumers select Secrets by type. Opaque means no validation. It changes nothing about storage or encryption, and the type is fixed once the Secret is created.

open as a page

Your service reads its configuration file only at process startup. How do you make a Kubernetes Deployment actually roll out when its ConfigMap changes, and how do you keep that change revertible?

level: seniorimportance: should knowfreq 50%

basics

~20 s

Make the config change alter the Pod template: put a hash of the ConfigMap content in a Pod-template annotation, or give the ConfigMap a content-hash suffix in its name so the reference changes. Either turns the edit into a normal rolling update you can roll back.

open as a page

How do you ensure Kubernetes Secret values are not written to etcd in plaintext, and what happens to Secrets that already exist when you enable that?

level: seniorimportance: should knowfreq 36%

basics

~20 s

Start kube-apiserver with --encryption-provider-config pointing at an EncryptionConfiguration that lists secrets with a real provider (KMS preferred) ahead of identity. Existing Secrets stay in their old form until rewritten, so you must re-write them all, e.g. kubectl get secrets -A -o json | kubectl replace -f -.

open as a page

Which pieces of information can the Kubernetes downward API surface to a container, and which common needs does it not cover — forcing you to call the API server or use a different mechanism?

level: seniorimportance: nice to knowfreq 30%

basics

~20 s

It surfaces only the Pod's own object: name, namespace, UID, labels, annotations, service account, node name, Pod and host IPs, and the container's resource requests and limits. Node labels, Services, other Pods, cluster info and object contents are out of scope and need an API client with RBAC.

open as a page

Marking Kubernetes ConfigMaps and Secrets immutable is described as a scalability improvement. Describe the mechanism — what work disappears, and where?

level: seniorimportance: nice to knowfreq 22%

basics

~20 s

By default each kubelet keeps mounted ConfigMaps/Secrets fresh by holding an API watch on every object its Pods reference. Immutable objects can never change, so the kubelet fetches once and opens no watch — removing large numbers of long-lived watches and their memory and CPU cost on the API server.

open as a page

A platform team runs 612 External Secrets Operator ExternalSecrets for many teams on one 48-node Kubernetes cluster: how would you design store scoping, refresh cadence and outage behaviour?

level: principalimportance: nice to knowfreq 26%

basics

~20 s

Give each team a namespaced SecretStore with its own provider identity, and keep ClusterSecretStores few and condition-limited. Tier refreshInterval by credential class within the provider call budget. Alert on failed syncs, because an outage keeps values but stops rotation.

open as a page

Would you require every ConfigMap and Secret in a large shared Kubernetes cluster to be created with `immutable: true`? Argue both sides and say where you would land.

level: principalimportance: nice to knowfreq 14%

basics

~20 s

Usually yes for application config, enforced by generation tooling rather than by policy alone — but with carve-outs for objects written by controllers (TLS renewal, external-secret sync), a retention policy so rollback still works, and an agreed break-glass procedure for incidents.

open as a page

For a production platform, would you keep application credentials in native Kubernetes Secret objects or source them from an external secret manager? Make the design argument.

level: principalimportance: nice to knowfreq 28%

basics

~20 s

Native Secrets are a distribution mechanism with no versioning, rotation or cross-cluster source of truth. Keep them as the delivery layer, but make an external manager the source of truth for anything long-lived — and prefer short-lived workload identity so there is no static credential to manage at all.

open as a page