ConfigMaps in Kubernetes
Learn how to use ConfigMaps for decoupled configuration in Kubernetes. This lesson covers core concepts, step-by-step walkthrough, and troubleshooting to help you manage application settings independently from your code.
Focus: ConfigMaps for decoupled configuration
When your application needs different settings in development, staging, and production, embedding those values directly into your container image is a fast track to deployment hell. You'd need to rebuild and push a new image for every environment change, break the twelve-factor app principle of strict separation of config from code, and create a maintenance nightmare. ConfigMaps in Kubernetes solve this by letting you decouple configuration artifacts from your container images, keeping your application portable and environment-agnostic.
The problem this lesson solves
Imagine you have a Node.js microservice that connects to a database. The database host, port, username, and password differ between your local machine, a test cluster, and the production cluster. Without a mechanism like ConfigMaps, you might hardcode these values in your code, use environment variables passed via the Dockerfile (which still requires a rebuild for each environment), or rely on a fragile configuration file injected at build time. All these approaches tightly couple your container image to your environment.
Result: Every time a config value changes (for example, a database endpoint after a failover), you must rebuild and redeploy your container image. This slows down iteration, risks version drift between config and code, and violates the principle of immutable infrastructure.
The Kubernetes answer: A ConfigMap is an API object used to store non-confidential data in key-value pairs. Pods can consume ConfigMaps as environment variables, command-line arguments, or configuration files in a volume. ConfigMaps decouple environment-specific configuration from your container images, making your pods portable across environments without any code changes.
Core concept / mental model
Think of ConfigMaps as a separate configuration cabinet for your pods. Your application code is the recipe (the Docker image), and the ConfigMap is the variable set of ingredients (the settings). Just as you can bake the same cake with different flavors by changing the ingredients, you run the same container image in different environments by adjusting the ConfigMap.
Key distinction: ConfigMaps are not for secrets. Use Secrets for sensitive data like passwords and tokens. ConfigMaps are for non-sensitive configuration such as database hostnames, port numbers, feature flags, and external service URLs.
| Concept | Analogy |
|---|---|
| Container image | The recipe book (fixed) |
| ConfigMap | The ingredient list for today (variable) |
| Environment variables | The instructions on how to mix the ingredients |
Pro Tip: Because ConfigMaps are stored in the cluster's etcd, any pod can access them as long as it's in the same namespace (or via cross-namespace references where supported). This makes them ideal for sharing common configuration across multiple deployments.
How it works step by step
Here's the logical flow from creating a ConfigMap to using it in a pod.
1. Create a ConfigMap object
You define a ConfigMap using a YAML manifest or via the kubectl create configmap command. The data is stored as a map of key-value pairs.
# configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
DATABASE_PORT: "5432"
CACHE_ENABLED: "true"
app.properties: |
max.connections=100
timeout.ms=30000
2. Make the ConfigMap available to pods
You have three main methods to expose ConfigMap data to your pod:
- As environment variables – simple and common for small config sets.
- As a volume mount – when your app expects a configuration file (e.g.,
application.properties). - As command-line arguments – through the pod's
commandorargs.
3. Reference the ConfigMap in a Pod or Deployment spec
The pod spec uses envFrom or env to pull values; volumes and volumeMounts to mount config files.
4. Pod reads configuration at runtime
When the pod starts, it picks up the values from the referenced ConfigMap. If you update the ConfigMap, existing pods are not automatically updated unless they are restarted (or you use a controller that watches for changes).
Hands-on walkthrough
Let's build a complete example: a pod that displays environment configuration read from a ConfigMap.
Step 1: Create a ConfigMap
First, create a ConfigMap with several configuration keys.
Command using kubectl:
kubectl create configmap app-config --from-literal=DB_HOST=postgres-svc --from-literal=DB_PORT=5432 --from-literal=LOG_LEVEL=debug
Alternatively, from a file:
kubectl create configmap app-config --from-file=app.properties
Verify the ConfigMap:
kubectl get configmap app-config -o yaml
Expected output (simplified):
apiVersion: v1
data:
DB_HOST: postgres-svc
DB_PORT: "5432"
LOG_LEVEL: debug
kind: ConfigMap
...
Step 2: Deploy a pod that consumes the ConfigMap
Create a pod that uses the ConfigMap as environment variables and prints them.
# config-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: config-demo-pod
spec:
containers:
- name: busybox
image: busybox
command: ["/bin/sh", "-c", "env | grep -E 'DB_HOST|DB_PORT|LOG_LEVEL' ; sleep 3600"]
envFrom:
- configMapRef:
name: app-config
Apply and check logs:
kubectl apply -f config-pod.yaml
kubectl logs config-demo-pod
Expected output:
DB_HOST=postgres-svc
DB_PORT=5432
LOG_LEVEL=debug
Step 3: Mount a ConfigMap as a volume
Suppose your app expects a config file at /etc/config/app.properties. Create the ConfigMap first (as shown earlier with app.properties), then mount it.
# mount-config-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: config-mount-pod
spec:
volumes:
- name: config-volume
configMap:
name: app-config
containers:
- name: busybox
image: busybox
command: ["/bin/sh", "-c", "cat /etc/config/app.properties; sleep 3600"]
volumeMounts:
- name: config-volume
mountPath: /etc/config
Apply and check:
kubectl apply -f mount-config-pod.yaml
kubectl logs config-mount-pod
Expected output:
max.connections=100
timeout.ms=30000
Note: When you mount a ConfigMap as a volume, each key in the
datafield becomes a file in the mount path. If you want only a subset of keys, useitems:underconfigMap:in the volume definition.
Compare options / when to choose what
ConfigMaps offer several ways to inject configuration. Here's a decision guide based on your use case.
| Approach | Best for | Limitations |
|---|---|---|
| envFrom + configMapRef | Injecting many environment variables at once | Names can't be overridden per key; all keys become env vars |
| env (valueFrom) + configMapKeyRef | Injecting specific keys as env vars | Verbose for many values |
| ConfigMap volume mount | Configuration files (e.g., YAML, JSON, properties) | Updates require pod restart; file path is fixed |
Subpath mount (subPath:) |
Injecting a single file into an existing directory | Notion of atomic update behavior: subPath mounts don't receive ConfigMap updates |
When to choose env vars vs. volume:
- Environment variables are ideal for small, simple values that your application reads as environment variables (e.g., database URL). They're easy to consume and don't require a filesystem.
- Volume mounts are necessary when your app reads a structured configuration file from a known path (e.g., a Spring Boot application.yml). Also better for large configs that might exceed environment variable size limits (typically 32KB per variable).
ConfigMap vs. Secrets: - ConfigMap for non-sensitive data (hostnames, ports, feature flags) - Secrets for sensitive data (passwords, API keys, certificates) — Secrets are base64 encoded and can be encrypted at rest.
Troubleshooting & edge cases
1. Pod fails with ConfigMap "name" not found
Cause: The ConfigMap doesn't exist in the pod's namespace, or the name is misspelled.
Fix:
kubectl get configmap -n <namespace> # verify existence and spelling
kubectl describe configmap app-config
2. Environment variable name collisions
Cause: If a configmap key contains characters that are not valid for environment variable names (e.g., my-key), Kubernetes will either skip it or transform it (e.g., my-key becomes my_key). Also, if two ConfigMaps define the same key, the order in envFrom determines which value is used.
Fix: Use configMapKeyRef with explicit name for keys that might conflict, or rename keys in the ConfigMap to valid env format (uppercase, underscores).
3. Mounted ConfigMap file doesn't update after ConfigMap change
Cause: By default, mounted ConfigMaps are not automatically updated in running pods. The pod must be restarted to see new values. This is a feature, not a bug — it ensures consistency during operation.
Fix: Roll out a new pod by updating the Deployment (e.g., change an annotation or tag). For file-based configs, some apps watch the inotify system for file changes, but this is not reliable.
4. Pod fails to start due to invalid configMapKeyRef
Cause: The key referenced in configMapKeyRef.name doesn't exist in the ConfigMap.
Error:
Error: container has runAsNonRoot and image will run as root
But more commonly:
Warning Failed Error: configmap "app-config" not found - container will not be started
Fix: Double-check the key name in kubectl describe configmap app-config.
5. ConfigMap exceeds size limit
Cause: A single ConfigMap is limited to 1 MiB (including all keys).
Solution: Break large configs into multiple ConfigMaps, or use a volume mount pointing to a separate ConfigMap with smaller data.
What you learned & what's next
You now understand the core idea behind ConfigMaps for decoupled configuration: how to store non-sensitive config outside your container image, and how to inject it into pods via environment variables or volume mounts. You've completed a practical exercise that demonstrated both methods and learned to troubleshoot common issues like missing ConfigMaps and naming collisions.
Key objectives met: - ✅ Explain the core idea behind ConfigMaps for decoupled configuration - ✅ Complete a practical exercise for ConfigMaps for decoupled configuration - ✅ Understand when to use env vars versus volume mounts
What's next: In the next lesson, you'll learn about Secrets for managing sensitive data, and then move on to Resource Quotas and LimitRanges to control how pods consume cluster resources. Mastering ConfigMaps is a fundamental step toward building production-ready, environment-agnostic applications on Kubernetes.
Practice recap
Create a ConfigMap with three environment variables: APP_MODE=production, DEBUG=false, and LOG_LEVEL=warn. Then deploy a pod using envFrom to consume all three variables and write them to the pod logs using env. Verify it works by checking kubectl logs <pod-name> | grep -E 'APP_MODE|DEBUG|LOG_LEVEL'.
Common mistakes
- Using ConfigMaps to store secrets like passwords or API keys — ConfigMaps are not encrypted and can be accessed easily. Always use Kubernetes Secrets for sensitive data.
- Assuming that updating a ConfigMap automatically updates all running pods that reference it — pods must be restarted to pick up new values.
- Creating ConfigMaps with keys that use hyphens or dots, then trying to reference them as environment variables — Kubernetes will convert
my-keytomy_key, which can cause unexpected key names.
Variations
- You can use kubectl create configmap with
--from-literal,--from-file, or--from-env-fileto create ConfigMaps from different sources. - Instead of mounting the whole ConfigMap, use
items:to select only specific keys to be mounted as files, reducing clutter. - For dynamic configuration updates without pod restart, consider using Reloader or Stakater Reloader controller that watches ConfigMap changes and triggers a rolling update of Deployments.
Real-world use cases
- Injecting different database connection strings for development, staging, and production environments into the same container image.
- Storing feature flags as key-value pairs in a ConfigMap so you can toggle functionality on/off without redeploying.
- Mounting a configuration file like
application.propertiesornginx.conffrom a ConfigMap into a pod's filesystem at a standard path.
Key takeaways
- ConfigMaps let you decouple non-sensitive configuration from container images, enabling environment-agnostic deployments.
- You can inject ConfigMap data into pods via environment variables (envFrom or configMapKeyRef) or as mounted volume files.
- ConfigMaps are namespace-scoped; a pod can only reference ConfigMaps in its own namespace.
- ConfigMaps are not encrypted — use Secrets for sensitive data like passwords and tokens.
- Changes to a ConfigMap do not automatically update running pods; you must restart pods to apply new values.
- ConfigMap size is limited to 1 MiB; for larger configs, split into multiple ConfigMaps or use alternative storage like PersistentVolume.
Keep learning
Related tutorials, quizzes, and articles for this topic.
Discussion
Questions, corrections, and tips help everyone reading this page.
0 comments
Add a comment
No comments yet — start the thread.