What Is a ConfigMap?
A ConfigMap is a Kubernetes API object used to store non-sensitive configuration as key-value pairs.
Typical examples include:
- application environment variables
- log levels
- feature flags
- hostnames and ports
- small configuration files
- command-line arguments
A ConfigMap is designed for configuration that should live outside your container image. That makes your workloads more portable and easier to promote between environments.
If the data is confidential, use a Secret instead. ConfigMaps are not meant for passwords, API tokens, certificates, or anything that requires secrecy.
Why ConfigMaps Matter
Decoupling configuration from images gives you a few important advantages:
- You can reuse the same image in multiple environments.
- You can change configuration without rebuilding the application image.
- Multiple Pods can share the same configuration source.
- Configuration can be managed declaratively alongside other Kubernetes manifests.
This follows the same general idea as the Twelve-Factor App principle of separating config from code, but implemented using a native Kubernetes object.
What Can a ConfigMap Store?
A ConfigMap mainly stores data in two fields:
data: for UTF-8 string valuesbinaryData: for binary content encoded as base64
A few important limits and rules apply:
- A ConfigMap is not intended for large payloads.
- The total size cannot exceed 1 MiB.
- Keys may contain alphanumeric characters,
-,_, and.. dataandbinaryDatakeys must not overlap.
Here is a simple example:
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
APP_ENV: production
LOG_LEVEL: info
DATABASE_HOST: postgres.default.svc.cluster.local
And here is an example with file-like content:
apiVersion: v1
kind: ConfigMap
metadata:
name: app-settings
data:
application.properties: |
app.name=demo
app.mode=production
app.featureX=true
This is an important point: ConfigMaps do not care whether the value is a single line or a multiline file. What matters is how the Pod consumes it.
Four Ways to Use a ConfigMap in a Pod
Kubernetes supports four main ways to consume a ConfigMap:
- As environment variables
- As command-line arguments
- As files mounted through a volume
- By reading the Kubernetes API directly from the application
1. Inject all keys as environment variables
This is useful when your application already reads from environment variables.
apiVersion: v1
kind: Pod
metadata:
name: env-configmap-demo
spec:
containers:
- name: app
image: busybox:1.36
command: ["/bin/sh", "-c", "env && sleep 3600"]
envFrom:
- configMapRef:
name: app-config
With this approach, each key in the ConfigMap becomes an environment variable inside the container.
2. Inject a single key as one environment variable
Use this when you want tighter control over what gets exposed.
apiVersion: v1
kind: Pod
metadata:
name: single-key-demo
spec:
containers:
- name: app
image: nginx:stable
env:
- name: APP_DATABASE_HOST
valueFrom:
configMapKeyRef:
name: app-config
key: DATABASE_HOST
3. Mount the ConfigMap as files
This works well for .properties, .ini, .yaml, .json, or other small config files.
apiVersion: v1
kind: Pod
metadata:
name: configmap-volume-demo
spec:
containers:
- name: app
image: busybox:1.36
command: ["/bin/sh", "-c", "ls -R /etc/config && sleep 3600"]
volumeMounts:
- name: config-volume
mountPath: /etc/config
readOnly: true
volumes:
- name: config-volume
configMap:
name: app-settings
Each key becomes a file. In this example, the container will see:
/etc/config/application.properties
And the file content will be the value stored under that key.
4. Read the ConfigMap through the Kubernetes API
This is the most flexible option, but also the most advanced. Your application can call the Kubernetes API, read a ConfigMap directly, and even react to changes.
This approach is less common, but it can be useful when:
- you want dynamic reload behavior managed by application logic
- you need more advanced control than static env vars or mounted files provide
- you need to read a ConfigMap from another namespace through the API
ConfigMaps and Namespaces
A Pod and the ConfigMap it references must normally live in the same namespace.
That means this works:
- Pod in
production - ConfigMap in
production
But this does not work through a normal configMapRef or volume reference:
- Pod in
production - ConfigMap in
shared-config
The main exception is when your application talks to the Kubernetes API directly and fetches the ConfigMap itself.
ConfigMaps and Static Pods
There is one limitation that is easy to miss: static Pods cannot reference ConfigMaps.
That is because static Pods are managed directly by the kubelet and their spec cannot refer to other Kubernetes API objects such as ConfigMaps or Secrets.
If you are working with regular Deployments, StatefulSets, or DaemonSets, this is usually not a concern. But it is worth remembering when troubleshooting node-level or bootstrap workloads.
How Updates Actually Behave
This is where many teams get surprised.
ConfigMap updates do not behave the same way for every consumption method.
Mounted as a volume
When a ConfigMap is mounted as a volume, Kubernetes eventually updates the projected files after the ConfigMap changes.
In practice, this means:
- the update is not always instant
- kubelet sync timing and cache propagation affect how quickly the change appears
- the application still needs to reload the file if it only reads configuration at startup
Injected as environment variables
If a ConfigMap is exposed through env or envFrom, the values are not updated automatically inside already-running containers.
You need to restart or roll out the Pod again.
Mounted with subPath
If you mount a ConfigMap using subPath, that mount does not receive updates.
That is a very common pitfall.
If you expect live updates from mounted files, avoid subPath.
Immutable ConfigMaps
Kubernetes supports immutable ConfigMaps.
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config-immutable
data:
APP_ENV: production
LOG_LEVEL: info
immutable: true
When immutable: true is set:
- the ConfigMap data cannot be changed
- the object cannot be made mutable again later
- you must delete and recreate it to change the values
Why would you do this?
Because immutable ConfigMaps can help:
- prevent accidental runtime edits
- reduce load on the API server in clusters with many ConfigMap mounts
- encourage versioned, deliberate configuration rollouts
For production systems, this is often a very good pattern.
ConfigMap vs Secret
This is the simplest rule:
- Use a ConfigMap for non-sensitive configuration.
- Use a Secret for sensitive data.
Examples for ConfigMaps:
LOG_LEVEL=debugFEATURE_X_ENABLED=trueSPRING_PROFILES_ACTIVE=prodappsettings.json
Examples for Secrets:
- database passwords
- API tokens
- private keys
- OAuth client secrets
If losing or exposing the value would be a security problem, it should not be in a ConfigMap.
A Practical Example for a FastAPI App
Suppose you have a small FastAPI service that reads settings from environment variables.
FastAPI code
import os
from fastapi import FastAPI
app = FastAPI()
APP_ENV = os.getenv("APP_ENV", "development")
LOG_LEVEL = os.getenv("LOG_LEVEL", "info")
@app.get("/health")
def health() -> dict[str, str]:
return {
"status": "ok",
"environment": APP_ENV,
"log_level": LOG_LEVEL,
}
ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
name: fastapi-config
data:
APP_ENV: production
LOG_LEVEL: warning
Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: fastapi-app
spec:
replicas: 2
selector:
matchLabels:
app: fastapi-app
template:
metadata:
labels:
app: fastapi-app
spec:
containers:
- name: api
image: myregistry/fastapi-app:latest
ports:
- containerPort: 8000
envFrom:
- configMapRef:
name: fastapi-config
This is a clean and practical setup:
- the image stays the same
- environment-specific values live in Kubernetes
- changing configuration does not require rebuilding the image
Just remember that for envFrom, existing Pods will need a restart or rollout to pick up updated values.
Creating ConfigMaps from the CLI
Kubernetes also lets you create ConfigMaps directly with kubectl.
From literal values
kubectl create configmap app-config \
--from-literal=APP_ENV=production \
--from-literal=LOG_LEVEL=info
From a file
kubectl create configmap app-settings \
--from-file=application.properties
From an env file
kubectl create configmap app-config \
--from-env-file=.env
This is useful for experiments and quick setups, although for production systems you will usually want to keep ConfigMaps under version control as YAML or generate them through Kustomize.
Managing ConfigMaps with Kustomize
Kustomize is especially useful for environment-specific configuration.
configMapGenerator:
- name: app-config
envs:
- .env
Or from literals:
configMapGenerator:
- name: app-config
literals:
- APP_ENV=production
- LOG_LEVEL=info
One useful detail is that generated ConfigMaps receive a content hash suffix in their names by default.
That means a generated name may look like this:
app-config-42cfbf598f
This is helpful because when the content changes, Kustomize generates a new ConfigMap name and updates references automatically. That makes configuration changes more explicit and safer to roll out.
Common Mistakes
1. Putting secrets into a ConfigMap
This is the most obvious mistake, but it still happens. ConfigMaps are not a secure storage mechanism.
2. Expecting environment variables to refresh automatically
They do not. If your Pod uses env or envFrom, a restart or rollout is required.
3. Using subPath and expecting file updates
A ConfigMap mounted with subPath does not get refreshed.
4. Storing too much data
ConfigMaps are limited to 1 MiB and are not meant to replace object storage, persistent volumes, or a database.
5. Mixing too many unrelated settings into one ConfigMap
A ConfigMap should usually have a clear purpose. For example:
api-confignginx-configfeature-flags
That makes maintenance, ownership, and rollouts much easier.
Best Practices
Here are a few practical recommendations that hold up well in real clusters:
- Keep ConfigMaps focused and small.
- Use file mounts for structured config files.
- Use environment variables for small scalar values.
- Prefer immutable ConfigMaps for stable production configuration.
- Version or regenerate ConfigMaps instead of editing them manually in production.
- Avoid
subPathwhen you need mounted config updates. - Keep Secrets and ConfigMaps clearly separated.
- Store your manifests or generators in version control.
When Should You Use a ConfigMap?
Use a ConfigMap when all of the following are true:
- the data is configuration
- the data is not sensitive
- the size is relatively small
- the application benefits from keeping config outside the image
That covers a large percentage of everyday Kubernetes configuration work.
Final Thoughts
ConfigMaps are simple, but they are foundational.
They help you keep container images generic, move environment-specific values out of application code, and manage configuration in a more Kubernetes-native way. Once you understand the difference between environment-variable injection, mounted files, direct API access, and immutable configuration, ConfigMaps become much more predictable and much more useful.
If you are just getting started, the safest mental model is this:
Use ConfigMaps for non-sensitive configuration, use Secrets for sensitive values, and always be explicit about how your application reloads configuration.
That one rule will already help you avoid most real-world mistakes.
Sources
- Kubernetes Docs: ConfigMaps - kubernetes.io/docs/concepts/configuration/configmap/)
- Kubernetes Docs: Configure a Pod to Use a ConfigMap - kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/
- Kubernetes Docs: Updating Configuration via a ConfigMap - kubernetes.io/docs/tutorials/configuration/updating-configuration-via-a-configmap/
- Kubernetes Docs: Create static Pods - kubernetes.io/docs/tasks/configure-pod-container/static-pod/
- Kubernetes Docs: kubectl create configmap - kubernetes-io/docs/reference/kubectl/generated/kubectl_create/kubectl_create_configmap/
- Kubernetes Docs: Declarative Management of Kubernetes Objects Using Kustomize - kubernetes.io/docs/tasks/manage-kubernetes-objects/kustomization/