Kubernetes Series: Explaining ConfigMaps with Practical Examples

Sylia CHIBOUB
7 min readJun 13, 2023

Introduction

This article aims at explaining the Kubernetes ConfigMap objects through a set of practical examples.

ConfigMaps

A ConfigMap is an k8s API object used to store non-confidential data in key-value pairs. It aims at making applications easily portable through decoupling their environment-specific configuration. [1]

Application Portability with ConfigMaps [2]

A ConfigMap has data and binaryData fields. These fields accept key-value pairs as their values. Both the data field and the binaryData are optional.

The data field is designed to contain UTF-8 strings while the binaryData field is designed to contain binary data as base64-encoded strings.

The keys stored in data must not overlap with the keys in the binaryData field.

Configmaps can be created:

  • From literal value
  • From a file
  • From a directory of files

They are used to configure a container inside a Pod in different ways:

  • As environment variables for a container
  • As a file in read-only volume, for the application to read

A ConfigMap is not designed to hold large chunks of data. The data stored in a ConfigMap cannot exceed 1 MiB. [1]

If you need to store settings that are larger than this limit, you may want to consider mounting a volume [1]

Practical Examples: Creating ConfigMaps

  1. Let’s use kubectl command to create a ConfigMap from literal value
# check how to create a ConfigMap
kubectl create configmap -h

# create a new config map named game-demo with the following key-values:
# player_initial_lives="3"
# ui_properties_file_name="user-interface.properties"

kubectl create configmap game-demo \
--from-literal=player_initial_lives="3" \
--from-literal=ui_properties_file_name="user-interface.properties"

# describe the created configmap game-demo
kubectl describe configmap game-demo

# OUTPUT:
Name: game-demo #configmap name
Namespace: default
Labels: <none>
Annotations: <none>

Data #configmap data field
====
player_initial_lives: #configmap data key
----
3 #configmap data value
ui_properties_file_name: #configmap data key
----
user-interface.properties #configmap data value

BinaryData #confgimap binarydata field
====

Events: <none>

2. Let’s use kubectl command to create a ConfigMap from a file

Let’s say we have an alerts.yml file that defines alerts for Prometheus.

# alerts.yml
groups:
- name: Nodes Alerts
rules:

- alert: VM Down
expr: up{job="node_exporter"} == 0
for: 10m
labels:
severity: "critical"
annotations:
description: " The VM {{ $labels.instance }} has been down for more than 10 minutes."

Let create a ConfigMap that will contain the alerts.yml file. alerts.yml is the ConfigMap key and the alerts.yml file content is the ConfigMap value.

# create the configmap from file
kubectl create configmap prometheus-alerts --from-file=alerts.yml

# describe the configmap to see its content
kubectl describe configmap prometheus-alerts

# OUTPUT

Name: prometheus-alerts #configmap name
Namespace: default
Labels: <none>
Annotations: <none>

Data
====
alerts.yml: #configmap key
----
groups: #configmap value
- name: Nodes Alerts
rules:

- alert: VM Down
expr: up{job="node_exporter"} == 0
for: 10m
labels:
severity: "critical"
annotations:
description: " The VM {{ $labels.instance }} has been down for more than 10 minutes."


BinaryData
====

Events: <none>

3. Let’s use kubectl command to create a ConfigMap from a folder

We have a folder named alerts that consists of two files : alert-node.yml and alert-memory.yml :

# alert-memory.yml
groups:
- name: Memory Alerts
rules:

- alert: High Memory Usage
expr: (node_memory_MemAvailable_bytes * 100) / node_memory_MemTotal_bytes < 15
for: 30m
labels:
severity: warning
annotations:
description: ' The memory of the VM: {{ $labels.instance }} is filling up. The available Memory is only {{ $value | printf "%.2f" }} %.'
# alert-node.yml
- name: Nodes Alerts
rules:

- alert: VM Down
expr: up{job="node_exporter"} == 0
for: 10m
labels:
severity: "critical"
annotations:
description: " The VM {{ $labels.instance }} has been down for more than 10 minutes."

Let create a ConfigMap that will contain the alerts folder content (in our case, both files alert-node.yml and alert-memory.yml). Files names represent the ConfigMap keys whereas files content represent the ConfigMap values.

# Create a new config map named prometheus-alerts based on folder alerts
kubectl create configmap prometheus-alerts --from-file=./alerts/

# Let's describe the configmap to see its content
kubectl describe configmap prometheus-alerts

# OUTPUT:

Name: prometheus-alerts #configmap name
Namespace: default
Labels: <none>
Annotations: <none>

Data
====
alert-memory.yml: #configmap key
----
groups: #configmap value
- name: Memory Alerts
rules:

- alert: High Memory Usage
expr: (node_memory_MemAvailable_bytes * 100) / node_memory_MemTotal_bytes < 15
for: 30m
labels:
severity: warning
annotations:
description: ' The memory of the VM: {{ $labels.instance }} is filling up. The available Memory is only {{ $value | printf "%.2f" }} %.'

alert-node.yml: #configmap key
----
groups: #configmap value
- name: Nodes Alerts
rules:

- alert: VM Down
expr: up{job="node_exporter"} == 0
for: 10m
labels:
severity: "critical"
annotations:
description: " The VM {{ $labels.instance }} has been down for more than 10 minutes."


BinaryData
====

Events: <none>

Note that this article doesn’t concern Prometheus, thus the way we’re creating alerts using ConfigMaps is not the right way to use for Prometheus, These are just examples.

4. Let’s use kubectl command to create a ConfigMap from an environment File.

Let’s say we have the following .env file

#.env
DATABASEHOST=localhost

Let create a ConfigMap that will contain the .env environment file content. DATABASEHOST is the ConfigMap key and the localhost is the ConfigMap value.

# create the configmap 
kubectl create configmap database --from-env-file=.env

# describe the created configmap
kubectl describe configmap database

# OUTPUT
Name: database #configmap name
Namespace: default
Labels: <none>
Annotations: <none>

Data
====
DATABASEHOST: #configmap key
----
localhost #configmap value

BinaryData
====

Events: <none>

Practical Examples: Mount ConfigMaps to Containers

  1. Mounting the configmap as a file (or a set of files) in read-only volume

Let’s create a pod named nginx to which the configmapnamed prometheus-alerts created previously from a folder will be mounted

# generate the nginx pod yaml file
kubectl run nginx - image=nginx - dry-run=client -o yaml > nginx.yaml

Let’s edit the nginx.yamlfile to mount the prometheus-alerts configmap as a file (or a set of files, depending on the configmap available keys) in read-only volume.

# nginx.yaml
# data defined in the configmap prometheus-alerts will be mounted as files
# to the alerts volume mounted under the /alerts path within
# the nginx container

apiVersion: v1
kind: Pod
metadata:
labels:
run: nginx
name: nginx
spec:
containers:
- image: nginx
name: nginx
# ------ add this lines------
volumeMounts:
- name: alerts
mountPath: /alerts
readOnly: true
# ---------------------------
volumes:
- name: alerts
configMap:
name: prometheus-alerts
# ---------------------------
restartPolicy: Always
# create the nginx pod 
kubectl apply -f nginx.yaml

# checkout the mounted files
kubectl exec -it nginx -- sh -c "ls /alerts/"

# OUTPUT
alert-memory.yml alert-node.yml

Instead of mounting all of configmap data, we can mount only specific data based on keys as files within a container as follows:

# nginx.yaml
# the value of alert-node.yml key defined in the configmap prometheus-alerts
# will be mounted as a file named alert-node.yml
# to the alerts volume mounted under the /alerts path within
# the nginx container

apiVersion: v1
kind: Pod
metadata:
labels:
run: nginx
name: nginx
spec:
containers:
- image: nginx
name: nginx
# ------ add this lines------
volumeMounts:
- name: alerts
mountPath: /alerts
readOnly: true
# ---------------------------
volumes:
- name: alerts
configMap:
name: prometheus-alerts
items:
# configmap selected key
- key: alert-node.yml
# how the file will be named
# (the file contains the value of the selected key)
path: alert-node.yml
# ---------------------------
restartPolicy: Always
# create the nginx pod 
kubectl apply -f nginx.yaml

# checkout the mounted files
kubectl exec -it nginx -- sh -c "ls /alerts/"

# OUTPUT
alert-node.yml

2. Mounting the configmap as environment variables for a container

Let’s create a pod named nginx to which the configmapnamed database created previously from an environment file will be mounted.

# generate the nginx pod yaml file
kubectl run nginx - image=nginx - dry-run=client -o yaml > nginx.yaml
# nginx.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
run: nginx
name: nginx
spec:
containers:
- image: nginx
name: nginx
# add these lines ---------
env:
- name: databaseName
valueFrom:
configMapKeyRef:
name: database
key: DATABASEHOST
# --------------------------
# create the pod 
kubectl apply -f nginx.yml

# verify if the env variable has been set for the container nginx
kubectl exec -it nginx --sh -c "printenv"

#OUTPUT
..
databaseName=localhost

Mounted ConfigMaps are updated automatically

When a ConfigMap currently consumed in a volume is updated, projected keys are eventually updated as well. The kubelet checks whether the mounted ConfigMap is fresh on every periodic sync.[1]

ConfigMaps consumed as environment variables are not updated automatically and require a pod restart [1]

A container using a ConfigMap as a subPath volume mount will not receive ConfigMap updates. [1]

Immutable ConfigMaps

The Kubernetes feature Immutable ConfigMaps provides an option to set individual ConfigMaps as immutable, preventing changes to their data. This option has the following advantages: [1]

  • Protection against unwanted updates that could cause applications outages [1]
  • Cluster performance improvement through significantly reducing load on kube-apiserver, by closing watches for ConfigMaps marked as immutable. [1]

An immutable ConfigMap can be created by setting the immutable field to true. For example: [1]

apiVersion: v1
kind: ConfigMap
metadata:
...
data:
...
immutable: true

Conclusion

The primary goal of this article was to provide a good understanding of ConfigMaps k8s objects . This has been accomplished through a brief explanation and a bunch of practical examples.

References

[1] Configmaps (2023) Kubernetes. Available at: https://kubernetes.io/docs/concepts/configuration/configmap/#configmap-immutable (Accessed: 13 June 2023).

[2] AK, S. (2023) Kubernetes configmap examples — how to guide: Devops junction, Middleware Inventory. Available at: https://www.middlewareinventory.com/blog/kubernetes-configmap-examples/ (Accessed: 13 June 2023).

--

--

Sylia CHIBOUB

Supporting Open Source and Cloud Native as a DevOps Engineer