Kubernetes

Kubernetes ConfigMap – What It is, How to Use & Examples

kubernetes configmap

ConfigMaps store config data that can be used by your Pods. A ConfigMap is a Kubernetes API object that contains one or more key-value pairs.

In this article, we’ll provide a complete guide to Kubernetes ConfigMaps. You’ll learn what they are, how to create them, and the ways in which they can be used with Pods.

We will cover:

  1. What are Kubernetes ConfigMaps?
  2. Where are ConfigMaps stored in Kubernetes?
  3. How to use Kubernetes ConfigMaps – Examples
  4. Understanding ConfigMap updates
  5. How to set Sensitive Config values?

What are Kubernetes ConfigMaps?

Kubernetes ConfigMap is a built-in Kubernetes API object that’s designed to store your application’s non-sensitive key-value config data. ConfigMaps allow you to keep config values separate from your code and container images. Values can be strings or Base64-encoded binary data.

Once you’ve created a ConfigMap, its content will be saved to your Kubernetes cluster. Pods can then consume the ConfigMap’s values as environment variables, command line arguments, or filesystem volumes.

ConfigMaps are intended to store relatively small amounts of simple data. The total size of a ConfigMap object must be less than 1 MiB. If you need to store more data, you should split your configuration into multiple ConfigMaps or consider using a separate database or key-value store.

It’s good practice to use a ConfigMap to supply any configurable values that your app needs at runtime. The key-value pairs within the ConfigMap can be injected directly into your Pods in several different formats. Because ConfigMaps are part of the Kubernetes API, it’s possible to alter their values without re-deploying your app’s Pods.

What is a Kubernetes ConfigMap used for?

You should reach for a ConfigMap when your app deployments need access to config values that could change independently of your code. A classic example is a system that uses a database connection—you will need to supply the hostname or IP address of the database server for your app to function correctly.

In general, a ConfigMap is the right place to deposit any user-customizable settings that your application supports. End users can create a ConfigMap before installing your app in their cluster, enabling them to configure their deployment ahead of time.

Developing your app to read config values from its environment or filesystem allows you to decouple configuration from code and easily support multiple deployment methods. When you’re working locally on your laptop, you can set environment variables straight in your shell; for Kubernetes deployments, you can reference values in a ConfigMap.

Where are ConfigMaps stored in Kubernetes?

Kubernetes stores ConfigMaps in its etcd datastore. You shouldn’t directly edit etcd data; instead, use the Kubernetes API server and Kubectl to create and manage your ConfigMaps.

To back up ConfigMap values, follow the guidance to set up backups for etcd. These backups will contain a complete copy of your cluster’s data.

Check out other best practices for Kubernetes security.

How to use Kubernetes ConfigMaps - Examples

Because ConfigMaps are regular Kubernetes API objects, you can create them using YAML Kubernetes manifests files.

They require a top-level data field that defines the key-value config pairs to store. Keys can only contain alphanumeric characters and the ., -, and _ symbols.

The following ConfigMap stores three properties: database_host, debug_mode, and log_level:

apiVersion: v1
kind: ConfigMap
metadata:
  name: demo-config
data:
  database_host: "192.168.0.1"
  debug_mode: "1"
  log_level: "verbose"

Save the manifest to demo-config.yaml, then use Kubectl to apply it to your cluster and create the ConfigMap object:

$ kubectl apply -f demo-config.yaml
configmap/demo-config created

Example 1: Using data and binaryData fields

When you use the data field, your ConfigMap values must be strings. ConfigMaps also support binary data within separate binaryData field.

Binary values need to be Base64-encoded:

apiVersion: v1
kind: ConfigMap
metadata:
  name: demo-config
binaryData:
  file_template: RGVtbwo=

You can use both data and binaryData in a single ConfigMap, but each key can only appear once—either in data or in binaryData.

Example 2: Listing and inspecting ConfigMaps

You can list the ConfigMaps you’ve created by running the kubectl get command:

$ kubectl get configmaps
NAME               DATA   AGE
demo-config        3      83m

To inspect the key-value pairs within a ConfigMap, use kubectl describe:

$ kubectl describe configmap demo-config
Name:         demo-config
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
database_host:
----
192.168.0.1
debug_mode:
----
1
log_level:
----
verbose

BinaryData
====

Events:  <none>

The ConfigMap’s content is visible under the Data and BinaryData headings.

Getting a ConfigMap’s Content as JSON

The following command will produce a JSON object that contains the ConfigMap’s key-value pairs:

$ kubectl get configmap demo-config -o jsonpath='{.data}' | jq
{
  "database_host": "192.168.0.1",
  "debug_mode": "1",
  "log_level": "verbose"
}

This can be a more convenient way to inspect ConfigMaps and export their content into files.

Example 3: Mounting ConfigMaps into Pods as environment variables

Once you’ve created a ConfigMap, you can consume it within your Pods. You can access all or part of a ConfigMap as environment variables, command line arguments, or mounted files.

Environment variables are familiar, easy to consume in code, and open to easy inspection. They’re a good way to supply a small number of simple values to your application.

The following Pod (demo-pod.yaml) makes the content of the demo-config ConfigMap available as environment variables:

apiVersion: v1
kind: Pod
metadata:
  name: demo-pod
spec:
  containers:
    - name: app
      command: ["/bin/sh", "-c", "printenv"]
      image: busybox:latest
      envFrom:
        - configMapRef:
            name: demo-config

The envFrom field instructs Kubernetes to create environment variables from the sources nested within it. The configMapRef refers to a ConfigMap by its name and selects all its key-value pairs.

Add the Pod to your cluster, then retrieve its logs to see the output from the printenv command. This should confirm that the three key-value pairs from the ConfigMap have been set as environment variables:

$ kubectl apply -f demo-pod.yaml
pod/demo-pod created

$ kubectl logs pod/demo-pod
...
database_host=192.168.0.1
debug_mode=1
log_level=verbose
...

Sometimes a Pod won’t require access to all the values contained in a ConfigMap. For example, you could have another Pod which only utilizes the log_level value from our demo ConfigMap.

The env.valueFrom syntax can be used instead of envFrom for this use case. It lets you select individual keys in a ConfigMap. Keys can also be renamed to different environment variables:

apiVersion: v1
kind: Pod
metadata:
  name: demo-pod
spec:
  containers:
    - name: app
      command: ["/bin/sh", "-c", "printenv"]
      image: busybox:latest
      env:
        - name: logging_mode
          valueFrom:
            configMapKeyRef:
              name: demo-config
              key: log_level

If you add this Pod to your cluster, you’ll see that only logging_mode is set as an environment variable. It has the value of the log_level key from the ConfigMap.

$ kubectl logs pod/demo-pod
...
logging_mode=verbose
...

Example 4: Mounting ConfigMaps into Pods as command line arguments

ConfigMap values can be interpolated into a container’s command line arguments by first referencing the relevant ConfigMap key as an environment variable:

apiVersion: v1
kind: Pod
metadata:
  name: demo-pod
spec:
  containers:
    - name: app
      command: ["demo-app", "--database-host", "$(DATABASE_HOST)"]
      image: demo-app:latest
      env:
        - name: DATABASE_HOST
          valueFrom:
            configMapKeyRef:
              name: demo-config
              key: database_host

This technique allows you to change the command that’s run when your containers start, based on the current content of your ConfigMap. It supports scenarios where your app expects configuration to be supplied directly to its process upon startup.

Example 5: Mounting ConfigMaps into Pods as volumes

Environment variables and command line arguments can become unwieldy when you have many different values, or values containing a large amount of data. ConfigMaps can be mounted as volumes instead, allowing your app to read its config values from files within the container’s filesystem.

To set up a volume mount, add an entry to your Pod manifest’s spec.volumes field that uses a configMap entry to reference your ConfigMap by name. Then, use the volumeMounts field to mount the volume to a read-only path in the container. The following manifest mounts the content of the demo-config ConfigMap to /etc/app-config:

apiVersion: v1
kind: Pod
metadata:
  name: demo-pod
spec:
  containers:
    - name: app
      command: ["ls", "/etc/app-config"]
      image: demo-app:latest
      volumeMounts:
        - name: config
          mountPath: "/etc/app-config"
          readOnly: true
  volumes:
    - name: config
      configMap:
        name: demo-config

Apply this Pod to your cluster, then check its log output:

$ kubectl apply -f demo-pod.yaml
pod/demo-pod created

$ kubectl logs pod/demo-pod
database_host
debug_mode
log_level

The logs show the output from the ls /etc/app-config command that the container is configured to run. The command confirms there are three files within the directory, corresponding to the keys in the ConfigMap. You should configure your app to read these files when it needs to access a config value.

Example 6: Using Immutable ConfigMaps

The ConfigMaps we’ve created so far have been mutable—you can modify them at any time by adding, changing, and removing keys. In practice, many apps are configured once, then expected to stay in the same configuration throughout their lifetime.

ConfigMaps can be marked as immutable to facilitate this use case. An immutable ConfigMap cannot be edited and you’ll see an error if you try to apply changes. This enhances safety by preventing accidental modification or deletion of ConfigMap keys that your app depends on.

To create an immutable ConfigMap, set its immutable manifest property to true:

apiVersion: v1
kind: ConfigMap
metadata:
  name: demo-config-immutable
data:
  foo: bar
immutable: true

Save the example manifest to demo-config-immutable.yaml, then add it to your cluster:

$ kubectl apply -f demo-config-immutable.yaml
configmap/demo-config-immutable created

Now try changing the ConfigMap, such as by changing foo from bar to baz:

data:
  foo: baz

When you re-apply the manifest, you’ll see a Forbidden error because the immutable ConfigMap doesn’t permit modifications:

$ kubectl apply -f demo-config-immutable.yaml
The ConfigMap "demo-config-immutable" is invalid: data: Forbidden: field is immutable when `immutable` is set

Understanding ConfigMap Updates

You can use Kubectl or the Kubernetes API to change mutable ConfigMaps. However, modifications won’t necessarily affect existing Pods, depending on how you’ve consumed the ConfigMap:

  • ConfigMaps consumed as environment variables or command line arguments will not update. Containers must restart to receive new environment variables and command line arguments. Consequently, containers consuming ConfigMaps using these methods won’t receive new values until they’re restarted.
  • ConfigMaps consumed as volumes will automatically apply updates. Pods that mount a ConfigMap as a volume will receive the new ConfigMap’s values, but the change won’t be instantaneous. The Kubelet worker process running on your cluster’s Nodes periodically checks for ConfigMap changes and updates the content of the files mounted into your Pods.

Immutable ConfigMaps are never updated–it’s impossible for them to change. As a result, immutable ConfigMaps provide a performance advantage because worker Nodes can skip calling the API server to check for updates.

How to Set Sensitive Config Values

ConfigMaps are only suitable for values that aren’t sensitive or confidential. Data isn’t encrypted so it could be retrieved by anyone who gains access to your cluster’s etcd datastore.

ConfigMap vs Secrets

Kubernetes Secrets are an alternative to ConfigMaps that can be used to save confidential values with encryption support. Most real-world applications will therefore use a combination of ConfigMaps and Secrets when deploying to Kubernetes.

Values such as passwords, API keys, tokens, and certificates should be stored in a Kubernetes Secret instead. Secrets function similarly to ConfigMaps but are encrypted at rest, ensuring that your sensitive values are protected.

In summary, non-sensitive values such as DATABASE_HOST should be added to ConfigMaps; valuable ones like DATABASE_PASSWORD belong in a Secret.

Key points

Kubernetes ConfigMaps are Kubernetes resources that store arbitrary key-value data required by your application. Once you’ve created a ConfigMap, you can mount its values into your Pods as environment variables or volumes.

ConfigMaps are stored in plain-text so you should not use them for sensitive values including passwords and API keys. Kubernetes Secrets are an alternative to ConfigMaps that can be used to save confidential values with encryption support. Most real-world applications will therefore use a combination of ConfigMaps and Secrets when deploying to Kubernetes.

If you need any assistance with managing your Kubernetes projects, take a look at Spacelift. It brings with it a GitOps flow, so your Kubernetes Deployments are synced with your Kubernetes Stacks, and pull requests show you a preview of what they’re planning to change. It also has an extensive selection of policies, which lets you automate compliance checks and build complex multi-stack workflows. You can check it for free by creating a trial account.

Manage Kubernetes Easier and Faster

Spacelift allows you to automate, audit, secure, and continuously deliver your infrastructure. It helps overcome common state management issues and adds several must-have features for infrastructure management.

Start free trial