Maintenance

Site is under maintenance — quizzes are still available.

Go to quizzes

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

Sponsored

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 command or args.

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 data field becomes a file in the mount path. If you want only a subset of keys, use items: under configMap: 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-key to my_key, which can cause unexpected key names.

Variations

  1. You can use kubectl create configmap with --from-literal, --from-file, or --from-env-file to create ConfigMaps from different sources.
  2. Instead of mounting the whole ConfigMap, use items: to select only specific keys to be mounted as files, reducing clutter.
  3. 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.properties or nginx.conf from 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.

Sponsored

Sponsored

Discussion

Questions, corrections, and tips help everyone reading this page.

0 comments

Add a comment

Shown publicly with your comment.

Be constructive · max 4,000 characters

No comments yet — start the thread.

Related tutorials, quizzes, and articles for this topic.