Kubernetes: Using ConfigMaps to Manage Application Configuration

Most applications contain settings which differ from environment to environment, or just need to be able to have behavior changed without making changes to the code. Configuration allows applications to do this.

Thankfully, Kubernetes provides a simple way to store configuration values in a cluster and reference them in a Pod specification. In this blog post, I'll show some simple examples of using ConfigMaps in Kubernetes.

What Are ConfigMaps

ConfigMaps are resources in Kubernetes. So, to use a configmap, it needs to be created through its API. As I have shown in previous examples with Kubernetes there are two primary ways to create resources and both work here with ConfigMaps.

First is imperatively through the CLI with the kubectl create configmap command, and the second is declarative through a YAML resource definition.

In this post I'll be using the imperative commands, and showing the corresponding resources which could be used to create the same resources.

ConfigMaps from the CommandLine

There are a few different ways to create ConfigMaps. I will highlight three of these.

  • From a raw file or directory
  • From a literal value
  • From an env file

When I create the ConfigMap from the Command Line, I will also show the corresponding resource created using kubectl get. This will show what the resource should look like if I were adding it directly through a kubectl apply -f or kubectl create -f command.

Create a Config Map from a Literal Value

First I'll create a configmap that has two literal values in it.

kubectl create configmap literal-cfg --from-literal=name=Jeremy --from-literal=hello=universe```

Let's output the ConfigMap as a resource to see what it contains. The corresponding resource for the ConfigMap looks like this:

apiVersion: v1
data:
  hello: universe
  name: Jeremy
kind: ConfigMap

A ConfigMap can be created from a file or directory using the --from-file options. For example, the following command will create a ConfigMap from the config.txt file:

Create a Config Map from a File

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

Each file provided maps to a key in the resource. The resource for the created config map looks like this:

> kubectl get configmap/file-cfg -o yaml
apiVersion: v1
data:
  data.txt: "config-map-data\r\nwith multiple lines"
kind: ConfigMap

The --from-file parameter also works on directories. For directories, each file name becomes a key, and the contents of the file become the value under the data section of the resource.

Create a Config Map from a .env File

Many applications use environment variables as a way to easily set configuration at runtime. So having an easy way to go from a .env file to a config map can help those types of applications.

kubectl create configmap env-cfg --from-env-file=sample.env

The file sample.env has these contents like this:

hello=world
name=jeremy

Looking at the resource, each key in the .env file translated to a corresponding key under the ConfigMap data.

The resulting resource looks like this:

apiVersion: v1
data:
  hello: world
  name: jeremy
kind: ConfigMap

Using the Config Values

So, I've been able to create a set of config values in Kubernetes, the next step is using those values. In pod specifications, there are multiple options to specify the configuration values.

I'm going to show two examples. First is using a value from a ConfigMap as an environment variable, the second mounting it as a file.

Using a Config Map Value as an Environment Variable

In this example, I'm going to create a single YAML file which sets up a config map and also a Pod. The Pod will reference the config map and output the environment variable value.

The key section is the envFrom: section in the Pod specification. It specifies a configMapRef which is referenced to get the values for the environment. The Pod will run a bash command which will output the current values of the environment variables.

apiVersion: v1
kind: ConfigMap
metadata:
  namespace: config-map-example-ns
  name: config-map-example
data:
  env_var1: VALUE1
  env_var2: VALUE2
---
apiVersion: v1
kind: Pod
metadata:
  namespace: config-map-example-ns
  labels:
    run: busybox-env-list
  name: busybox-env-list
spec:
  containers:
  - image: busybox
    command: ["/bin/sh"]
    args:
      - -c
      - "echo \"env_var1: $env_var1\"  env_var2: \"$env_var2\""
    name: env-list
    envFrom:
    - configMapRef:
      name: config-map-example
  restartPolicy: Never

Here is the output of the Pod. Both the environment values were output as expected.

> k logs pod/busybox-env-list --namespace=config-map-example-ns
env_var1: VALUE1 env_var2: VALUE2

Mounting a ConfigMap as a File in a Pod

The final example will be mounting a ConfigMap as files inside the Pod. Note the volumes section with a configMap defining a ConfigMap as a volume. The volumeMounts section then refers to that volume by name.

apiVersion: v1
kind: ConfigMap
metadata:
  namespace: config-map-example-ns
  name: config-map-example
data:
  env_var1: VALUE1
  env_var2: VALUE2
---
apiVersion: v1
kind: Pod
metadata:
  namespace: config-map-example-ns
  name: config-map-vol-pod
spec:
  containers:
  - image: busybox
    command: ["/bin/sh"]
    args:
      - -c
      - "ls -l /app/config; cat /app/config/env_var1; cat /app/config/env_var2;"
    name: env-list
    volumeMounts:
      - name: config-map-vol
        mountPath: /app/config
        readOnly: true
  volumes:
    - name: config-map-vol
      configMap:
        name: config-map-example
  restartPolicy: Never

After running a kubectl apply, and grabbing the logs, this was the output.

> k logs pod/config-map-vol-pod --namespace=config-map-example-ns
total 0
lrwxrwxrwx    1 root     root            15 Jan  7 22:52 env_var1 -> ..data/env_var1
lrwxrwxrwx    1 root     root            15 Jan  7 22:52 env_var2 -> ..data/env_var2
VALUE1VALUE2

It shows the file listing for the directory containing the config map. It has a file for each key in the original ConfigMap. The contents of the files contains the values from the ConfigMap.

Wrapping Up

I've shown a few examples of using a ConfigMap in Kubernetes to inject configuration within a Pod. By using ConfigMaps, the configuration can live alongside the Pod or Deployment definition which is extremely useful maintaining differences between environments. By having this construct built in it makes it much easier to manage configuration especially across different instances of an application being run.

Share this post:
© 2024 - Built and designed by Jeremy Honl with Gatsby. Images are from Unsplash