Building ConfigMaps within Kubernetes

ConfigMaps within Kubernetes are a means of separating configuration data from the running container image. This means that all necessary configuration data can exist outside the application code. They are not really suited to storing confidential data as they are stored in plain text (the Secrets object is a better option for this).

There are a number of ways of constructing and using ConfigMaps which can be used to store key-value pairs or even whole configuration files.

This post describes a number of different ways of building a basic ConfigMap to import a couple of key-value pairs. The basic way of doing this is:

  1. Literal Values
  2. Imported from Files Directly
  3. Imported from Directories with a number of Files

We'll leave the actual use of the ConfigMap for another post.

Using Literal Values

The ConfigMap can be easily constucted using literal values where the contents is defined while creating the ConfigMap using the --from-literal option.


kubectl create configmap jason-cm \ 
--from-literal KEY1="This is some data for Key1" \ 
--from-literal KEY2="This is some more data for Key2"

The backslash at the end of the line is just a means of continuing the command over multiple lines.

This will create a configmap called jason-cm that has two key-value pairs, KEY1 and KEY2. It can be seen that the value must be contained in quotes to ensure they are parsed correctly.

The generated configmap looks like this:

cloud_user@salterje2c:~/ConfigMAP$ kubectl describe configmap jason-cm
Name:         jason-cm
Namespace:    production
Labels:       <none>
Annotations:  <none>

Data
====
KEY1:
----
This is some data for Key1
KEY2:
----
This is some more data for Key2
Events:  <none>

This allows a quick and easy way of generating a ConfigMap that has just a couple of values but it does have a problem with scalability as well not having an associated YAML manifest.

The issue with not having an associated manifest obviously can be overcome once the object has been created by sending to the YAML output and piping it to the desired file.

cloud_user@salterje2c:~/ConfigMAP$ kubectl get configmap jason-cm -o YAML > jason-cm.YAML
cloud_user@salterje2c:~/ConfigMAP$ cat jason-cm.YAML 
apiVersion: v1
data:
  KEY1: This is some data for Key1
  KEY2: This is some more data for Key2
kind: ConfigMap
metadata:
  creationTimestamp: "2020-06-14T13:59:09Z"
  name: jason-cm
  namespace: production
  resourceVersion: "668656"
  selfLink: /api/v1/namespaces/production/configmaps/jason-cm
  uid: 1be70c36-0130-4d9b-a98d-cac0e52f6d59
  

Building a ConfigMap From Files

Another way of building a ConfigMap is by reading the values from files that store the data.

In this example a single file, KEYS.properties, has been created with a couple of Key-value pairs inside it and the ConfigMap is created from it.

cloud_user@salterje2c:~/ConfigMAP$ kubectl create configmap jason-cm2 --from-file=KEYS.properties

configmap/jason-cm2 created

cloud_user@salterje2c:~/ConfigMAP$ kubectl describe configmap jason-cm2
Name:         jason-cm2
Namespace:    production
Labels:       <none>
Annotations:  <none>

Data
====
KEYS.properties:
----
KEY1:This is some data for KEY1 that comes from a file called KEYS.properties
KEY2:This is some data for KEY2 that comes from a file called KEYS.properties

cloud_user@salterje2c:~/ConfigMAP$ cat KEYS.properties 
KEY1:This is some data for KEY1 that comes from a file called KEYS.properties
KEY2:This is some data for KEY2 that comes from a file called KEYS.properties

It can be seen that the format is slightly different then when importing from the literal values. The ConfigMap is easier to create as it really is just a case of pointing at the correct file using the --from-file option.

The file that has the key values can be populated with as many values as required.

The YAML manifest can again be created by sending the output to YAML and piping to the file you wish to create.

kubectl get configmap jason-cm2 -o YAML > jason-cm2.YAML

cloud_user@salterje2c:~/ConfigMAP$ cat jason-cm2.YAML
apiVersion: v1
data:
  KEYS.properties: |
    KEY1:This is some data for KEY1 that comes from a file called KEYS.properties
    KEY2:This is some data for KEY2 that comes from a file called KEYS.properties
kind: ConfigMap
metadata:
  creationTimestamp: "2020-06-14T14:20:35Z"
  name: jason-cm2
  namespace: production
  resourceVersion: "670515"
  selfLink: /api/v1/namespaces/production/configmaps/jason-cm2
  uid: 3963ee4a-176f-4dd7-a446-fc24273e1c2c

ConfigMaps from Directories

The final method of building a ConfigMap is similar to taking the data from files but allows importing from all files within a directory.

It can be seen that the syntax is very similar to directly creating from the individual files but is pointed at the directory, which in this case is called configdata. This file has had two files already created within it.

cloud_user@salterje2c:~/ConfigMAP$ kubectl create configmap jason-cm3 \
--from-file=./configdata/

It can be seen that the two files KEY1.properties and KEY2.properties have been used to build the ConfigMap.

cloud_user@salterje2c:~/ConfigMAP$ ls -lhR configdata/
configdata/:
total 8.0K
-rw-rw-r-- 1 cloud_user cloud_user 75 Jun 14 14:12 KEY1.properties
-rw-rw-r-- 1 cloud_user cloud_user 71 Jun 14 14:12 KEY2.properties

cloud_user@salterje2c:~/ConfigMAP$ cat ./configdata/KEY1.properties 
This is some KEY1 Data that is stored within a file called KEY1.properties

cloud_user@salterje2c:~/ConfigMAP$ cat ./configdata/KEY2.properties 
This is some more data for KEY2 that is stored in the KEY2.properties

The resulting ConfigMap will take the values from the files contained in the original command.

cloud_user@salterje2c:~/ConfigMAP$ kubectl describe configmap jason-cm3
Name:         jason-cm3
Namespace:    production
Labels:       <none>
Annotations:  <none>

Data
====
KEY1.properties:
----
This is some KEY1 Data that is stored within a file called KEY1.properties

KEY2.properties:
----
This is some more data for KEY2 that is stored in the KEY2.properties

The created ConfigMap objects can now be used by other objects within the cluster to set configuration settings or even environmental values.