How to Create and Use ConfigMaps in Kubernetes

Alibaba Cloud
12 min readApr 29, 2019

--

By Alwyn Botha, Alibaba Cloud Tech Share Author. Tech Share is Alibaba Cloud’s incentive program to encourage the sharing of technical knowledge and best practices within the cloud community.

This tutorial gives you practical experience in creating and using ConfigMaps in Kubernetes Pods. Note the name: ConfigMaps. Let’s look at what that means.

  • Config: keeps configuration information.
  • Maps: In computer science, an associative array, map, symbol table, or dictionary is an abstract data type composed of a collection of (key, value) pairs, such that each possible key appears at most once in the collection. Learn more on this Wiki page.

Simply put ConfigMaps store configuration maps/dictionaries of key=value data.

ConfigMaps store plain text values unencrypted — do not use if for secrets. Kubernetes has functionality that deals specifically with secrets, which is covered in the article How to Create and Use Secrets in Kubernetes.

ConfigMap values are frequently referenced using Linux environment variables.

Prerequisites

This tutorial is written using Windows 10, kubectl, and minikube. If you have a similar setup you are good to go.

Important Note for Windows Users

All files you create must have Unix (LF) line endings, not Windows ( CR LF ) endings. Read your editor documentation on how to change it to default to LF line endings. There should also be some EOL conversion menu option somewhere to convert to LF.

If you are using a server then you need a running Kubernetes cluster, and your kubectl command-line tool must be able to access your cluster. If you run kubectl get nodes and it shows a list of nodes — even just one — you are good to go.

You need about 2 weeks of basic beginner exposure to Kubernetes to follow these tutorials.

If you have zero Kubernetes experience I suggest you spend a few days reading at https://kubernetes.io/docs/concepts/ Unfortunately these are not step by step how-to tutorials, mostly in-depth theory with snippets assuming you know how to apply it. The https://kubernetes.io/docs/tasks/ are step by step tutorials, but you need to be quite familiar with the theory and concepts.

You need not be a theory expert to follow this tutorial, we will walk you thorough some practical experience of applying Kubernetes.

Basic Example: Create ConfigMaps from a file

You should speed-read rush through the first few basic examples. Its very easy to do and understand.

Create file that will be the input to our ConfigMap.

nano config-map-data.txtkey1=value1
key2=23

Create the ConfigMap using our file just created.

kubectl create configmap configmap-example-1 --from-file=./config-map-data.txtconfigmap/configmap-example-1 created

Find out what Kubernetes knows about our newly created ConfigMap via kubectl describe .

kubectl describe configmap/configmap-example-1Name:         configmap-example-1
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
config-map-data.txt:
----
key1=value1
key2=23
Events: <none>

Our keys and values are shown at the bottom. ConfigMap successfully created.

This part of the tutorial focus on creating ConfigMaps — we can now delete it since ALL we wanted to learn was how to create a ConfigMap .

kubectl delete configmap/configmap-example-1configmap "configmap-example-1" deleted

Create a ConfigMap with comments and blank lines in it.

nano config-map-data.txtkey1=value1
key2=23
# comment 1## comment 2

Create the ConfigMap using our file just created.

kubectl create configmap configmap-example-1 --from-file=./config-map-data.txtconfigmap/configmap-example-1 created

Find out what Kubernetes knows about our newly created ConfigMap via kubectl describe .

kubectl describe configmap/configmap-example-1Name:         configmap-example-1
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
config-map-data.txt:
----
key1=value1
key2=23
# comment 1## comment 2Events: <none>

Our 2 keys and their values are shown at the bottom.

IMPORTANT : Kubernetes does not have know-how of how to ignore the comments and blank lines if we use — from-file . In section 2 you will see how — from-env-file fixes that automatically.

Alternative way to get Kubernetes to show what it knows about our ConfigMap : kubectl get configmap Note the -o yaml at the end. If you leave that off, all you will get is a simple one-line list of our ConfigMap.

-o yaml specifies the output format to be YAML.

7 lines of metadata removed from kubectl get configmap output throughout this tutorial since it adds no value to the discussions.

kubectl get configmap configmap-example-1 -o yamlapiVersion: v1
data:
config-map-data.txt: |+
key1=value1
key2=23
# comment 1 ## comment 2kind: ConfigMap

Demo complete, delete the ConfigMap.

kubectl delete configmap/configmap-example-1configmap "configmap-example-1" deleted

Basic Example: Create ConfigMaps using — from-env-file

This section shows how to create a ConfigMap using the Docker environment file format.

Create a ConfigMap using the same file from previous example: that file is in Docker environment file format.

kubectl create configmap configmap-example-1 --from-env-file=./config-map-data.txtconfigmap/configmap-example-1 created

Note the — from-env-file versus — from-file we used earlier.

kubectl describe configmap/configmap-example-1Name:         configmap-example-1
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
key1:
----
value1
key2:
----
23
Events: <none>

Note that — from-env-file ignores the blank lines and comments perfectly — as it should.

The describe command shows the keys and values perfectly.

Best Practice: have your ConfigMaps in environment file format and use — from-env-file to create your ConfigMaps.

For more information about the Docker environment file format, visit this page. Only the syntax rules at the top are relevant. You just saw Kubernetes interprets those rules perfectly.

Alternative command to show facts about our ConfigMap: kubectl get configmap Note no ugly blank lines or # comments at the top.

kubectl get configmap configmap-example-1 -o yamlapiVersion: v1
data:
key1: value1
key2: "23"
kind: ConfigMap

Basic Example: Create ConfigMaps from Literal Values

Simple example of how to create ConfigMaps from literal values.

— from-literal= syntax specifies our keys and their literal value.

kubectl create configmap literal-config-1 --from-literal=literal-key1=value1 --from-literal=literal-key2=22configmap/literal-config-1 created

Find out what Kubernetes knows about our newly created ConfigMap via kubectl describe .

kubectl describe configmap/literal-config-1Name:         literal-config-1
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
literal-key1:
----
value1
literal-key2:
----
22
Events: <none>

Our keys and their literal values are shown at the bottom. ConfigMap successfully created using literal values.

Demo done, delete it.

kubectl delete configmap/literal-config-1configmap "literal-config-1" deleted

Second literal values example.

kubectl create configmap literal-config-1 --from-literal=city=London --from-literal=population=millionsconfigmap/literal-config-1 created

Use kubectl describe to find out if it got created successfully.

kubectl describe configmap/literal-config-1Name:         literal-config-1
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
city:
----
London
population:
----
millions
Events: <none>

Basic Example: Create ConfigMaps from Directories

You will now see how to create a ConfigMap that combines the content of all files in a directory.

Run the following in your shell:

mkdir ConfigMap-Foldernano ./ConfigMap-Folder/file-1.txt
file-1-key-one:1
file-1-key-two:awesome
nano ./ConfigMap-Folder/file-2.txt
file-2-key-one:2
file-2-key-two:cool

Note that — from-file=ConfigMap-Folder refers to our FOLDER.

kubectl create configmap from-folder-configmap --from-file=ConfigMap-Folderconfigmap/from-folder-configmap created

Use kubectl describe to find out if it got created successfully.

kubectl describe configmap/from-folder-configmapName:         from-folder-configmap
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
file-1.txt:
----
file-1-key-one:1
file-1-key-two:awesome
file-2.txt:
----
file-2-key-one:2
file-2-key-two:cool
Events: <none>

It looks OK, but if we use kubectl get configmaps to show the ConfigMap we can see it is not OK.

I edited file-1 and file-2 using Windows line endings. Those r n in the output below should not be there.

kubectl get configmaps from-folder-configmap -o yamlapiVersion: v1
data:
file-1.txt: "file-1-key-one:1\r\nfile-1-key-two:awesome\r\n"
file-2.txt: "file-2-key-one:2\r\nfile-2-key-two:cool\r\n"
kind: ConfigMap

Delete wrong ConfigMap.

kubectl delete configmaps/from-folder-configmapconfigmap "from-folder-configmap" deleted

Use your editor and convert line endings to be Unix format.

Recreate the ConfigMap.

kubectl create configmap from-folder-configmap --from-file=ConfigMap-Folderconfigmap/from-folder-configmap created

Use kubectl get configmaps to show details. Perfect, n r all gone.

kubectl get configmaps from-folder-configmap -o yamlapiVersion: v1
data:
file-1.txt: |
file-1-key-one:1
file-1-key-two:awesome
file-2.txt: |
file-2-key-one:2
file-2-key-two:cool
kind: ConfigMap

You are now familiar with all the ways of creating ConfigMaps. To access these values via environment variables is slightly more complex.

Access ConfigMap data via container environment variables

We did not delete ConfigMap literal-config-1. We use it here, this is its content:

kubectl get configmaps literal-config-1 -o yamlapiVersion: v1
data:
city: London
population: millions
kind: ConfigMap

Create a Pod that references literal-config-1 using configMapKeyRef.

nano ConfigMap-demo-1.yamlapiVersion: v1
kind: Pod
metadata:
name: configmap-pod-1
spec:
containers:
- name: cm-container-1
image: alpine
imagePullPolicy: IfNotPresent
command: [ "/bin/sh", "-c", "env" ]
env:
- name: ENV_CITY
valueFrom:
configMapKeyRef:
name: literal-config-1
key: city
restartPolicy: Never

ENV_CITY defines the name we want our environment variable to have.

Its value comes from : valueFrom … literal-config-1

We want the value of the city key to be placed inside ENV_CITY .

kubectl create -f ConfigMap-demo-1.yamlpod/configmap-pod-1 created

command: [ “/bin/sh”, “-c”, “env” ] runs a command env to display a list of our environment variables.

We use kubectl logs configmap-pod-1 to show the log of our pod. ENV_CITY shown near the end.

We successfully passed our city key value into the environment variable ENV_CITY.

kubectl logs configmap-pod-1
KUBERNETES_SERVICE_PORT=443
KUBERNETES_PORT=tcp://10.96.0.1:443
HOSTNAME=configmap-pod-1
SHLVL=1
HOME=/root
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT_443_TCP_PROTO=tcp
ENV_CITY=London
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_SERVICE_HOST=10.96.0.1
PWD=/

You now know how to access ConfigMap data via container environment variables.

Get a list of our Pods. Note its status is completed. It only had to run the command env . The Pod then exited successfully.

kubectl get poNAME                  READY   STATUS      RESTARTS   AGE
pod/configmap-pod-1 0/1 Completed 0 2m46s

Here is the complete output of describe . Too much detail, so I edited it below.

kubectl describe pod/configmap-pod-1Name:               configmap-pod-1
Namespace: default
Priority: 0
PriorityClassName: <none>
Node: minikube/10.0.2.15
Start Time: Wed, 02 Jan 2019 11:24:24 +0200
Labels: <none>
Annotations: <none>
Status: Succeeded
IP: 172.17.0.5
Containers:
cm-container-1:
Container ID: docker://791e4ae1f8aad006ee77d81c401cf19221764805952cc9190e16a722d4bb9929
Image: alpine
Image ID: docker-pullable://alpine@sha256:46e71df1e5191ab8b8034c5189e325258ec44ea739bba1e5645cff83c9048ff1
Port: <none>
Host Port: <none>
Command:
/bin/sh
-c
env
State: Terminated
Reason: Completed
Exit Code: 0
Started: Wed, 02 Jan 2019 11:24:25 +0200
Finished: Wed, 02 Jan 2019 11:24:25 +0200
Ready: False
Restart Count: 0
Environment:
ENV_CITY: <set to the key 'city' of config map 'literal-config-1'> Optional: false
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-gs2wt (ro)
Conditions:
Type Status
Initialized True
Ready False
ContainersReady False
PodScheduled True
Volumes:
default-token-gs2wt:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-gs2wt
Optional: false
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute for 300s
node.kubernetes.io/unreachable:NoExecute for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 3m18s default-scheduler Successfully assigned default/configmap-pod-1 to minikube
Normal Pulled 3m17s kubelet, minikube Container image "alpine" already present on machine
Normal Created 3m17s kubelet, minikube Created container
Normal Started 3m17s kubelet, minikube Started container
Normal SandboxChanged 3m15s kubelet, minikube Pod sandbox changed, it will be killed and re-created.

Edited output below:

kubectl describe pod/configmap-pod-1Name:               configmap-pod-1
Start Time: Wed, 02 Jan 2019 11:24:24 +0200
Status: Succeeded
Containers:
cm-container-1:
State: Terminated
Reason: Completed
Exit Code: 0
Started: Wed, 02 Jan 2019 11:24:25 +0200
Finished: Wed, 02 Jan 2019 11:24:25 +0200
Ready: False
Environment:
ENV_CITY: <set to the key 'city' of config map 'literal-config-1'> Optional: false
Conditions:
Type Status
Initialized True
Ready False
ContainersReady False
PodScheduled True

Explains it all: Pod started and finished in a second. It is terminated, since it completed with exit code 0 = success.

Status:             SucceededState:          Terminated
Reason: Completed
Exit Code: 0
Started: Wed, 02 Jan 2019 11:24:25 +0200
Finished: Wed, 02 Jan 2019 11:24:25 +0200

Text below: Pod got initialized and scheduled = true.

It is NOT ready NOW since it terminated.

Type              Status
Initialized True
Ready False
ContainersReady False
PodScheduled True

Demo complete, delete Pod.

kubectl delete -f ConfigMap-demo-1.yaml --force --grace-period=0warning: Immediate deletion does not wait for confirmation that the running resource has been terminated. The resource may continue to run on the cluster indefinitely.
pod "configmap-pod-1" force deleted

Access 2 ConfigMap’s Data via Container Environment Variables

Let’s create another literal ConfigMap so we have 2 ConfigMaps to access in our Pod.

kubectl create configmap literal-config-2 --from-literal=shipping=free --from-literal=region=allconfigmap/literal-config-2 created

Check its successfully created. Looks good.

kubectl get configmaps literal-config-2 -o yamlapiVersion: v1
data:
region: all
shipping: free
kind: ConfigMap

Create a Pod that refers to 2 different ConfigMaps.

nano ConfigMap-demo-2.yamlapiVersion: v1
kind: Pod
metadata:
name: configmap-pod-2
spec:
containers:
- name: cm-container-2
image: alpine
imagePullPolicy: IfNotPresent
command: [ "/bin/sh", "-c", "env" ]
env:
- name: ENV_CITY
valueFrom:
configMapKeyRef:
name: literal-config-1
key: city
- name: ENV_SHIPPING
valueFrom:
configMapKeyRef:
name: literal-config-2
key: shipping
restartPolicy: Never

The ENV_CITY environment variable gets its value from city key in literal-config-1 ConfigMap.

The ENV_SHIPPING environment variable gets its value from shipping key in literal-config-2 ConfigMap.

kubectl create -f ConfigMap-demo-2.yamlpod/configmap-pod-2 created

Check the logs: both our environment variables are shown. Success.

You now know how to access ConfigMap data from several ConfigMaps via container environment variables.

kubectl logs configmap-pod-2KUBERNETES_SERVICE_PORT=443
KUBERNETES_PORT=tcp://10.96.0.1:443
HOSTNAME=configmap-pod-2
SHLVL=1
HOME=/root
ENV_SHIPPING=free
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT_443_TCP_PROTO=tcp
ENV_CITY=London
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_SERVICE_HOST=10.96.0.1

Access All Key-Value Pairs in a ConfigMap as Environment Variables

Show the content of both keys in literal-config-1

kubectl get configmaps literal-config-1 -o yamlapiVersion: v1
data:
city: London
population: millions

To access all the keys in a ConfigMap we just do not refer to any specific key in our spec.

nano ConfigMap-demo-3.yamlapiVersion: v1
kind: Pod
metadata:
name: configmap-pod-3
spec:
containers:
- name: cm-container-3
image: alpine
imagePullPolicy: IfNotPresent
command: [ "/bin/sh", "-c", "env" ]
envFrom:
- configMapRef:
name: literal-config-1
restartPolicy: Never

Simple spec extract below : syntax to create environment variables from all keys in ConfigMap literal-config-1

envFrom:
- configMapRef:
name: literal-config-1

Create the ConfigMap.

kubectl create -f ConfigMap-demo-3.yamlpod/configmap-pod-3 created

Show the Pod’s log. Both our keys were converted into environment variables.

Note that their names are still lower case: exactly as it is in the original literal-config-1 ConfigMap .

You have to make the names upper case in the original raw file if that is what you need.

kubectl logs configmap-pod-3KUBERNETES_PORT=tcp://10.96.0.1:443
KUBERNETES_SERVICE_PORT=443
HOSTNAME=configmap-pod-3
population=millions
SHLVL=1
HOME=/root
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT_443_TCP_PROTO=tcp
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_SERVICE_HOST=10.96.0.1
PWD=/
city=London

Access All Key-Value Pairs in a 2 ConfigMaps as Environment Variables

To access all the keys in SEVERAL ConfigMaps we just do not refer to any specific key in our spec.

nano ConfigMap-demo-4.yamlapiVersion: v1
kind: Pod
metadata:
name: configmap-pod-4
spec:
containers:
- name: cm-container-4
image: alpine
imagePullPolicy: IfNotPresent
command: [ "/bin/sh", "-c", "env" ]
envFrom:
- configMapRef:
name: literal-config-1
- configMapRef:
name: literal-config-2
restartPolicy: Never

Create this ConfigMap.

kubectl create -f ConfigMap-demo-4.yamlpod/configmap-pod-4 created

This is the content of our 2 ConfigMaps :

kubectl get configmaps literal-config-1 -o yaml | head -4apiVersion: v1
data:
city: London
population: millions
kubectl get configmaps literal-config-2 -o yaml | head -4apiVersion: v1
data:
region: all
shipping: free

The log of our Pod. Note all the keys from both the ConfigMaps are now live as environment variables.

kubectl logs configmap-pod-4KUBERNETES_SERVICE_PORT=443
KUBERNETES_PORT=tcp://10.96.0.1:443
HOSTNAME=configmap-pod-4
population=millions
SHLVL=1
HOME=/root
region=all
shipping=free
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT_443_TCP_PROTO=tcp
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
KUBERNETES_SERVICE_HOST=10.96.0.1
PWD=/
city=London

Clean Up

Get a list of your ConfigMaps :

( Note the age, I created it yesterday when I wrote first part of this tutorial. )

kubectl get cmNAME                    DATA   AGE
configmap-example-1 1 25h
from-folder-configmap 2 24h
literal-config-1 2 25h
literal-config-2 2 23h

Delete the ConfigMaps … you may have more to delete.

kubectl delete cm/configmap-example-1
kubectl delete cm/from-folder-configmap
kubectl delete cm/literal-config-1
kubectl delete cm/literal-config-2

Run kubectl get cm again to check you deleted it all.

Run kubectl get po to get list of Pods.

Delete ones you do not need anymore :

For example :

kubectl delete -f ConfigMap-demo-1.yaml --force --grace-period=0kubectl delete -f ConfigMap-demo-2.yaml --force --grace-period=0kubectl delete -f ConfigMap-demo-3.yaml --force --grace-period=0kubectl delete -f ConfigMap-demo-4.yaml --force --grace-period=0

Note: I use — force — grace-period=0 in these tutorials to immediately stop Pods. Otherwise it will take 30 seconds for Pod to gracefully shut down. Using — force in production is a sure way to cause data corruption.

Reference:https://www.alibabacloud.com/blog/how-to-create-and-use-configmaps-in-kubernetes_594724?spm=a2c41.12821011.0.0

--

--

Alibaba Cloud

Follow me to keep abreast with the latest technology news, industry insights, and developer trends. Alibaba Cloud website:https://www.alibabacloud.com