Kubernetes ConfigMaps
Overview
Every application needs configuration — database hostnames, log levels, feature flags, connection strings. Hard-coding these values into your container image is a problem because you would need a different image for development, staging, and production. That defeats one of the core benefits of containers: build once, run anywhere.
A ConfigMap is a Kubernetes object that stores non-sensitive configuration data as key-value pairs. You can think of it in two ways:
- As a small filesystem — each key becomes a file name and each value becomes the file content.
- As a set of environment variables — each key-value pair can be injected into a container's environment.
The key idea is that ConfigMaps are combined with a Pod right before it runs. This means the same container image and Pod definition can be reused across many workloads — only the ConfigMap changes. You get a clean separation between your application code and your runtime configuration.
Core Concepts
What Is a ConfigMap?
At its core, a ConfigMap is simply a dictionary of string key-value pairs stored as a Kubernetes object. Unlike Secrets (which are designed for sensitive data), ConfigMaps are intended for non-sensitive configuration — things like log levels, service URLs, feature toggles, and connection strings (without passwords).
A ConfigMap lives inside a Namespace. Pods in the same Namespace can reference it. Pods in a different Namespace cannot.
Why Not Just Use Environment Variables Directly?
You could define environment variables directly in a Pod spec, but that approach has drawbacks:
- Configuration is scattered throughout many Pod or Deployment manifests instead of being in one central place.
- Updating a single value means editing every manifest that uses it.
- There is no way to mount a whole configuration file (like
appsettings.json) as an environment variable.
ConfigMaps solve all three problems. You define configuration once, reference it from as many Pods as you like, and update it in a single place.
Three Ways to Consume a ConfigMap
Kubernetes gives you three methods to pass ConfigMap data into a container:
| Method | How It Works | Best For |
|---|---|---|
| Environment Variables | Each key-value pair becomes an environment variable inside the container. | Simple values: log levels, ports, feature flags. |
| Volume / Filesystem | The ConfigMap is mounted as a directory. Each key becomes a file; its value becomes the file content. | Structured config files: appsettings.json, nginx.conf. |
| Command-Line Arguments | Environment variables sourced from the ConfigMap are referenced in the container's command or args field using $(VAR_NAME) syntax. | CLI applications that accept flags or positional arguments. |
You can mix and match all three methods in the same Pod. We will use all of them in the step-by-step example below.
Hands-On: Kubernetes Commands
Creating a ConfigMap Imperatively (Command Line)
The fastest way to create a ConfigMap is with kubectl create configmap. You can feed it literal values, files, or even entire directories.
From Literal Values
Use --from-literal to pass individual key-value pairs directly on the command line:
This creates a ConfigMap named app-settings with two keys: LOG_LEVEL and MAX_RETRIES.
From a File
Suppose you have a configuration file called my-config.txt on disk:
You can load it into a ConfigMap with --from-file:
The file name (my-config.txt) becomes the key, and the entire file content becomes the value. You can also combine --from-file and --from-literal in one command.
From a Directory
If you have an entire directory of config files, point --from-file at the directory:
Each file in that directory becomes a key in the ConfigMap.
Viewing a ConfigMap
To see the contents of a ConfigMap, use:
This prints the full YAML representation including the data section. Here is an example of what the output looks like for the my-config ConfigMap we created above:
Notice that the file content is stored verbatim under the key my-config.txt. The | symbol in YAML preserves newlines in multi-line values.
Describing a ConfigMap
For a quick summary without the raw YAML:
Listing All ConfigMaps
Add -n <namespace> to list ConfigMaps in a specific Namespace, or --all-namespaces to list them across the entire cluster.
Editing a ConfigMap
To modify an existing ConfigMap in-place:
This opens the ConfigMap in your default text editor. Save and close to apply changes. Note that running Pods do not automatically pick up environment variable changes — you need to restart them. Volume-mounted ConfigMaps, however, are updated automatically by the kubelet (with a short delay).
Deleting a ConfigMap
Be careful: if any Pod references a deleted ConfigMap, that Pod will fail to start until the ConfigMap is recreated.
Step-by-Step Example
In this walkthrough, we will build a realistic scenario: a .NET Notification API that needs runtime configuration for SMTP settings, logging levels, and rate limiting. We will create two ConfigMaps and a Deployment that consumes them using environment variables and volume mounts.
Step 1: Define the Simple Key-Value ConfigMap
First, create a ConfigMap with simple key-value pairs for SMTP settings and logging. Save this file as notification-api-config.yaml:
Apply it to your cluster:
Each key here is a simple string. All values in a ConfigMap must be strings — even numbers like "587" are stored as strings. Your application is responsible for parsing them into the correct type.
Step 2: Define a File-Based ConfigMap
Next, create a ConfigMap that holds an entire appsettings.Production.json file. This is useful when your application expects a structured configuration file at a specific path. Save this as notification-api-appsettings.yaml:
Apply it:
The key appsettings.Production.json will become a file name when we mount this ConfigMap as a volume. The JSON content after the | character will become the content of that file. This means your .NET application can read it just like any other appsettings file.
Step 3: Create the Deployment That Uses Both ConfigMaps
Now create a Deployment that references both ConfigMaps. This manifest demonstrates all the consumption methods in a single resource. Save this as notification-api-deployment.yaml:
Apply it:
Let's break down what this Deployment does with ConfigMaps:
Step 4: Understanding the Environment Variable Methods
There are two different environment-variable approaches used in the Deployment above:
Method A: Individual Keys with valueFrom
This approach picks specific keys from a ConfigMap and maps them to environment variable names you choose:
This is useful when the ConfigMap key names do not match what your application expects. In .NET, double underscores (__) are interpreted as section separators in the configuration hierarchy. So SmtpSettings__Host translates to SmtpSettings:Host in your IConfiguration object.
Method B: All Keys at Once with envFrom
This approach injects every key from the ConfigMap as an environment variable:
Each key in the ConfigMap becomes an environment variable with the same name. In our example, the container will have SMTP_HOST, SMTP_PORT, RETRY_COUNT, LOG_LEVEL, and ALLOWED_ORIGINS all available as environment variables. This is the quickest approach when you control the key naming in the ConfigMap.
Step 5: Understanding the Volume Mount Method
The volume mount projects the ConfigMap as files inside the container's filesystem:
After the Pod starts, the container will see the following file:
The file name comes from the key in the ConfigMap, and the file content comes from its value. If the ConfigMap had three keys, there would be three files in /app/config/.
You can verify this by exec-ing into a running Pod:
And view the file content:
Step 6: Verify Environment Variables
To confirm that environment variables from the ConfigMap were injected correctly, run:
You should see output similar to:
Step 7: Using Command-Line Arguments from ConfigMap Values
The third consumption method injects ConfigMap values into a container's startup command. Kubernetes substitutes $(VAR_NAME) references in the command or args fields with the corresponding environment variable values. Here is a standalone example:
When this Pod starts, Kubernetes replaces $(SMTP_HOST) and $(SMTP_PORT) with their actual values from the ConfigMap. The container's command becomes:
This technique is especially useful for tools that require configuration via command-line flags rather than environment variables.
Step 8: Updating a ConfigMap
To change the log level from Information to Debug, edit the ConfigMap:
Change the value of the LOG_LEVEL key and save. Alternatively, you can replace the entire ConfigMap by re-applying an updated YAML file:
Important behavior differences after an update:
- Volume-mounted files are updated automatically by the kubelet. There is a short delay (typically 30–60 seconds) before the new content appears. Your application will see the updated files without a restart — as long as it re-reads the file.
- Environment variables are not updated automatically. They are set once when the Pod starts. To pick up changes passed as environment variables, you must restart the Pods:
Step 9: Clean Up
When you are finished experimenting, remove all the resources:
Or, if all manifests are in the same directory, you can delete them in one command:
Summary
ConfigMaps let you decouple configuration from container images so you can follow the build once, run anywhere principle. Here is what we covered:
- A ConfigMap stores non-sensitive configuration as string key-value pairs inside a Kubernetes Namespace.
- You can create ConfigMaps imperatively with
kubectl create configmap(from literals, files, or directories) or declaratively from a YAML manifest. - There are three ways to consume a ConfigMap in a Pod:
- Environment variables — using
valueFrom.configMapKeyReffor individual keys orenvFromfor all keys at once. - Volume mounts — mounting the ConfigMap as a directory where each key becomes a file.
- Command-line arguments — referencing ConfigMap-sourced environment variables with
$(VAR_NAME)syntax incommandorargs. - Volume-mounted ConfigMaps are updated automatically (with a short delay). Environment-variable ConfigMaps require a Pod restart to pick up changes.
- ConfigMaps are for non-sensitive data only. For passwords, API keys, and certificates, use Secrets instead.