One of the biggest selling points of containers is the premise that they let you build an app once and run it anywhere. We’re here to tell you that this is wrong – or, at least, it’s an exaggeration of how containers typically work in practice.

The reason why is that, even though containers make application code portable across environments, application configuration settings are often not so portable. Configurations related to databases, APIs, and so on tend to be environment-specific, so you need to customize those settings for each particular deployment scenario – and if the settings are baked into your container images (which is one way to configure them), you can’t take an image built for one environment and run it in another one without breaking stuff.

Fortunately, there’s a solution for this conundrum: Kubernetes ConfigMaps. By separating configuration settings from containers themselves, ConfigMaps make it much easier to port containers across environments without having to rebuild them each time.

What is a Kubernetes ConfigMap?

Diagram illustrating how a Kubernetes ConfigMap mounts configuration data as volumes into multiple pods for shared access.

In Kubernetes, a ConfigMap is an API object that can store data using a key-value pairs approach. Each key is a string with a corresponding value.

The primary purpose of ConfigMaps is to store configuration data that applications need to access at runtime. As we mentioned, this is useful because ConfigMaps are a handy way of separating configuration settings from containers themselves. This eliminates the need to hard-code configurations into containers and update the containers whenever configuration values change. It also reduces the risk that a container won’t run properly in one environment and experience an issue such as exit code 127 due to broken configuration settings.

ConfigMap vs. environment variables

Another way to feed configuration data to containers without embedding it in containers themselves is to use environment variables. In Kubernetes, you can configure environment variables for a container by including a section like the following in a container’s spec:

env:
	- name: SOME_ENVIRONMENT_VALUE
  	value: "This is the value assigned to SOME_ENVIRONMENT_VALUE"

Like ConfigMaps, environment variables allow you to separate environment-specific configuration settings from containers. Unlike ConfigMaps, however, updating environment variables requires redeploying a container – so environment variables are not as convenient and seamless as ConfigMaps.

Note that environment variables are a common way to reference a ConfigMap when deploying a container, as we’ll explain below. But that is different from defining all configuration settings as environment variables instead of storing them in a ConfigMap that is referenced via a single environment variable within a container spec.

ConfigMap vs. Secrets

ConfigMaps are similar to Kubernetes Secrets, which are another way to store configuration data and reference it when a container runs. The major difference between a ConfigMap and a Secret, however, is that Secrets store data in base64-encoded form, whereas ConfigMaps usually store it in plain text

Technically speaking, you can encode values in a ConfigMap as well, but you would typically not do that. If your data is sensitive enough to require encoding, you’d want to store it as a Secret instead. Kubernetes differentiates between ConfigMaps and Secrets primarily as a way of encouraging developers to keep non-sensitive configuration data such as database URLs (which should live in a ConfigMap) separate from sensitive data like passwords and access keys (which should exist in a Secret).

| | Purpose | Advantages | Drawbacks | |---|---|---|---| | **ConfigMaps** | Store non-sensitive configuration data. | Separates configuration data from applications. Supports dynamic updates. | Not ideal for storing sensitive data. | | **Environment variables** | Define environment variables for containers at time of deployment. | Simple to define. | Cumbersome to use when you need to manage many settings. | | **Secrets** | Store sensitive secrets. | Help to separate sensitive data from non-sensitive configuration data. | Not encrypted by default. Need to be managed separately from ConfigMaps to maximize security. |

Where are ConfigMaps stored in Kubernetes?

Like other API objects, ConfigMap objects are stored in Etcd, the distributed key-value pairs store that houses most configuration data for a Kubernetes cluster. Etcd resides on the control plane node or nodes with a cluster.

Note that also like other data stored in Etcd, ConfigMaps are not encrypted by default. This means that anyone who can access Etcd will be able to read all values stored in your ConfigMaps.

What are Kubernetes ConfigMaps used for?

The main use case for ConfigMaps in Kubernetes is storing application configuration settings. Common examples of data you might define in a ConfigMap include:

  • The network address for a database that a container needs to connect to.
  • The URL for an API that a container needs to access.
  • A feature flag that enables or disables an optional feature when a container runs.

Again, you don’t strictly need to use ConfigMaps to store settings like these. You could instead hard-code the settings into your containers, or use environment variables within container specs to define them. But ConfigMaps simplify the process by providing a centralized place to store configuration that is distinct from containers, yet easy for containers to access.

How to create Kubernetes ConfigMaps: Examples

To create a ConfigMap, follow these steps.

1. Define a ConfigMap using YAML

First, write YAML code that defines the settings you want to include in the ConfigMap. For example:

apiVersion: v1
kind: ConfigMap
metadata:
  name: my-first-configmap
data:
  database_addr: “10.20.30.40”

This example creates a ConfigMap object named you-first-configmap (as defined in the ConfigMap metadata section) as well as a key named database_addr whose value is 10.20.30.40. You could use this configuration if you need your container to connect to a database that is available at the IP address 10.20.30.40.

2. Create a ConfigMap

After defining a ConfigMap, you need to save it as a file (such as my-first-configmap.yaml) and create it within your cluster using kubectl:

kubectl apply -f my-first-configmap.yaml

As we show below, it’s also possible to create a ConfigMap from a file using the kubectl create configmap command.

3. Reference the ConfigMap

At this point, the ConfigMap exists as an object in your cluster. But actually using it requires you to reference the ConfigMap object in the container spec section when deploying a pod. A common way to do this is to inject the ConfigMap as an environment variable using code like the following:

apiVersion: v1
kind: Pod
metadata:
  name: configmap-example
spec:
  containers:
	- name: some_app
  	image: some_repo:latest
  	envFrom:
    	   - configMapRef:
        	      name: my-first-configmap

The last three lines of the spec in this example define an environment variable of the type configMapRef whose value is my-first-configmap. This matches the ConfigMap we created in the example above. Note that you can define multiple ConfigMaps for a cluster; you don’t need to create just one ConfigMap for all of your applications.

Managing ConfigMaps

After creating a ConfigMap, there are several actions you might want to perform to manage it.

First, to view a list of all existing ConfigMaps, run:

kubectl get configmaps

For details on a particular ConfigMap, use:

kubectl describe configmaps name_of_configmap

(Replace name_of_configmap with the actual ConfigMap name.)

To delete a ConfigMap, run:

kubectl delete configmap name_of_configmap

Updating ConfigMaps

The easiest way to update a ConfigMap is to use the kubectl edit command, which lets you make changes in real-time to a ConfigMap that you’ve already created. To open a ConfigMap in an editor, run:

kubectl edit configmap name_of_configmap

After editing, save your changes. Kubernetes will then automatically apply the new settings. This is one of the cool features of ConfigMaps – changes are applied automatically, meaning you don’t need to redeploy your containers to update the value of a ConfigMap setting.

You could also update a ConfigMap by deleting it and replacing it with a new one with new values. But this would require restarting any containers that depend on the ConfigMap.

Types of ConfigMaps

ConfigMaps can fall into several different categories based on how they’re created and/or special characteristics.

Literal key-value pairs ConfigMaps

The most common type of ConfigMap is one that includes simple key-value pairs and is defined using the --from-literal flag and corresponding command-line arguments at the time of creation. It’s called a literal ConfigMap because you define key-value pairs as literal command-line arguments.

For example, you could create a ConfigMap that uses literal key-value pairs with command-line arguments such as:

kubectl create configmap my-config --from-literal=some_key=some_value

This is a fast and simple way to create a ConfigMap that requires just one or a handful of key-value pairs.

File-based ConfigMaps

For ConfigMaps that need to include more data, it usually makes sense to define ConfigMaps as configuration files and reference the configuration files when creating a ConfigMap. You can do this with a kubectl create configmap command like:

kubectl create configmap some-config --from-file=some-file.txt

Here, we reference the ConfigMap file using command-line arguments, but we don’t define literal key-value pairs on the command line; instead, we store the values in separate configuration files.

Taking this approach a step further, you can also populate a storage volume with data from the ConfigMap file. To do this, you reference the appropriate ConfigMap name in the volumeMounts section of your container spec, along with a desired mount point for the file inside the container. For example:

spec:
  containers:
name: some-container
  	image: some-image

  	volumeMounts:
  	   - name: volume-configmap
    	      mountPath: /etc/configmap-mount
   volumes:
	- name: volume-configmap
  	configMap:
                    name: container-files

Immutable ConfigMaps

Immutable ConfigMaps are a special type of ConfigMap whose values are – as you might guess – immutable. This means you can’t make changes to an immutable ConfigMap once you create a ConfigMap of this type. You can only delete it.

To create a ConfigMap that is immutable, include the line immutable: true in the ConfigMap metadata when defining the ConfigMap. For example:

metadata:
  name: some-configmap
  immutable: true

You don’t need to include the immutable: setting in ConfigMap metadata; if you don’t, Kubernetes will make your ConfigMap non-immutable by default.

Benefits and challenges of Kubernetes ConfigMaps

ConfigMaps offer a range of advantages as well as challenges. Here’s a look at their main pros and cons.

ConfigMap benefits

The main benefits of ConfigMaps include:

  • Decoupling configuration data from applications: As we explained above, ConfigMaps make it possible to separate configuration settings from applications, which in turn means you can modify configurations without having to rebuild container images.
  • Dynamic updates: ConfigMaps offer the advantage of allowing you to modify configuration settings dynamically, without having to redeploy your applications.
  • Centralized configuration settings: A ConfigMap provides a central, persistent location to store all of the configuration data that an application needs to reference. This is simpler than trying to define settings using a scattered approach where some are environment variables, some are hard-coded into containers, and so on.

ConfigMap challenges and limitations

On the other hand, ConfigMaps present a few challenges:

  • Not designed for sensitive information: Although you technically can store encoded data in a ConfigMap, this is not a best practice because it is likely to mean that your sensitive data will end up mixed in with less sensitive information, increasing the risk of accidentally leaking sensitive data.
  • No encryption: As we mentioned, ConfigMaps are not encrypted by default, and anyone who is able to access Etcd (or the control plane node that hosts it) can view ConfigMap settings. This is another reason why you shouldn’t store sensitive data in ConfigMaps.

Lack of built-in version control: Kubernetes makes it easy to edit ConfigMaps, but it doesn’t track changes over time or provide features for automatically rolling back to an earlier ConfigMap version in the event that changes cause a problem. To implement ConfigMap version control, you’d need to store copies of your ConfigMaps in an external system like Git.

| Pros | Cons | |---|---| | Decouple configuration data from applications. | Not ideal for storing sensitive settings. | | Enable dynamic configuration updates. | Not encrypted by default. | | Centralize configuration settings. | No built-in version control. |

Advanced ConfigMap use cases

So far, we’ve looked at relatively simple ConfigMap use cases, like storing database settings. To illustrate further why ConfigMaps can be so useful, let’s look at some more advanced use cases.

Moving applications from dev/test to production

It’s common for developers to test an application in a dev/test namespace prior to deploying it to production. During testing, the application is likely to require different settings than in production because it may interact with different databases, APIs, and so on.

Diagram showing how different environment-specific ConfigMaps (DEV, TEST, PROD) are created and used in a Kubernetes cluster.

ConfigMaps make it easy to modify these settings when the app moves from testing to production. The simplest approach would be to create multiple ConfigMaps – one for dev/test and one for production – and reference the appropriate one when deploying an application to each environment. That way, your containers can remain unchanged even as your configuration settings evolve.

Copying settings between clusters

Because ConfigMaps can be simple files, they offer an easy way of porting configuration settings between clusters. If you need to migrate an application to a different cluster, you can move its configuration settings by simply copying the relevant ConfigMap into the new cluster and applying it with kubectl. In this way, ConfigMaps help streamline cross-cluster migrations.

Kubernetes ConfigMap best practices

Consider the following best practices to get the most value from ConfigMaps.

Test ConfigMaps before deployment

Errors in a ConfigMap, such as typos or broken indentation, could cause Kubernetes to fail to read the ConfigMap data properly. To mitigate this risk, consider testing ConfigMaps prior to deployment.

Kubernetes doesn’t offer a native way of testing ConfigMaps (other than applying them and checking whether they cause problems), but you can use external YAML linters, such as YAML Lint, to validate syntax.

Version-control ConfigMaps

As we noted, Kubernetes doesn’t provide version-control features for your ConfigMaps. But you may want to be able to track how a ConfigMap changes over time and roll back to an earlier version if you make a change that causes a problem. For this reason, consider storing copies of your ConfigMaps in a version-control system, like Git.

Avoid secrets in ConfigMaps

We said it before, and we’ll say it again: Although you technically can store passwords, access keys, and other types of secrets in ConfigMaps, this is a risky practice. You should use Secrets to store sensitive data instead, which makes it easier to keep that data separate from non-sensitive configuration settings.

Update ConfigMaps using live edits

While you could update a configuration by deleting a ConfigMap and replacing it with a new one, a better practice is to use the kubectl edit feature to modify an existing ConfigMap in a live editor. Not only is this faster and simpler, but it allows you to apply changes dynamically without having to redeploy your applications.

It also reduces the risk that you’ll accidentally make a mistake, such as referencing the wrong ConfigMap name. If you do that, you could experience errors like CreateContainerConfigError or a failed Kubernetes liveness probe, which may occur when Kubernetes can’t find a designated ConfigMap or when the settings defined by ConfigMap data cause a container to crash.

Document ConfigMaps

Because ConfigMaps often contain critical configuration data, and because a cluster may include multiple ConfigMaps, it’s important to keep track of which ConfigMaps you have created and what they do. And while you could use kubectl get configmaps to view existing ConfigMaps, that approach provides limited context on what the purpose of each ConfigMap is, who created it, why they created it, and so on.

A better practice is to document your ConfigMap data and ConfigMap metadata in a central place, making it easy for developers to determine which ConfigMaps exist throughout the cluster and what they are intended to do.

Don’t use ConfigMaps when they’re not necessary

Not every application requires a ConfigMap. If an app’s configuration is so simple that it doesn’t vary between environments or requires just one or two settings, it may be easier not to create a ConfigMap and instead use an alternative approach, such as environment variables, to define whichever simple configuration data the app needs.

How groundcover helps with Kubernetes ConfigMaps

When something’s wrong with your ConfigMaps, it often means something will be wrong with your applications as well. An app that can’t reference a ConfigMap may be unable to connect to other applications, databases, and so on. And Kubernetes won’t automatically alert you to the problem because Kubernetes includes no built-in monitoring or notification features.

groundcover dashboard showing Kubernetes observability metrics, including logs by workload and namespace, CPU usage, and dropped HTTP traces.

This is where groundcover comes in. By continuously monitoring and observing your cluster, groundcover clues you in fast to issues like broken service connections, pods that fail to start because of a missing ConfigMap, or poor performance triggered by bad settings inside a ConfigMap. We can’t fix your ConfigMaps for you, but we can tell you when something’s wrong with a ConfigMap and you need to make a change to keep your apps running smoothly.

Fulfilling the “build once, run anywhere” promise

On its own, a container in most cases can’t actually run anywhere, due to the need for varying configuration settings between environments. But with a little help from Kubernetes ConfigMaps, developers can live the “build once, run anywhere” dream. They can create a container image once, and then deploy it across diverse environments using different ConfigMap settings. They can also update configurations whenever they want, without having to redeploy.

When it comes to configuration management for cloud-native apps, you can’t really ask for more than that.

Sign up for Updates

Keep up with all things cloud-native observability.

We care about data. Check out our privacy policy.