Configmap contents can be imported into a container in a number of ways, which will mostly be related to how the application is written. This post gives a couple of examples of how to make use of ConfigMaps to populate data within a container.
Creating Environmental Values from a ConfigMap
In this example a ConfigMap will be used to create some environmental values for a container and this will be confirmed using different techniques.
The aim of this exercise is to set 2 environmental values KEY1 and KEY2, which are stored in an existing ConfigMap. Further details of how to create a ConfigMap can be found here
The ConfigMap contents are shown below:
salterje@k8s-master:~/YAML/configmaps$ kubectl describe cm my-test-cm
Name: my-test-cm
Namespace: default
Labels: app=mytest
Annotations: <none>
Data
====
KEY1.properties:
----
This is some data that has been inserted into KEY1
KEY2.properties:
----
This is KEY2 from KEY2.properties
This gives two Key-Pair values, KEY1.properties and KEY2.properties which will be imported into a container.
The values are set within the manifest file of a POD within the spec section. As normal the indent level must be correct within the file to allow the creation of the object.
The extract below shows two environmental variables being created KEY1 and KEY2. It can be seen that both of them will be imported from the my-test-cm ConfigMap and use the KEY1.properties and KEY2.properties.
spec:
containers:
- image: nginx
imagePullPolicy: Always
name: mytest-nginx
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
ports:
- containerPort: 80
env: # Setting an Environmental value within Container
- name: KEY1 # The Name of the ENV Value
valueFrom:
configMapKeyRef:
name: my-test-cm # The Name of the ConfigMap
key: KEY1.properties # The Name of the value within the ConfigMap
- name: KEY2 # The Name of the ENV Value
valueFrom:
configMapKeyRef:
name: my-test-cm # The Name of the ConfigMap
key: KEY2.properties # The Name of the value with the ConfigMap
There are a number of ways that we will confirm these variables have been created.
The first is by connecting to the container itself and checking directly. This is done by finding the correct POD (in our case the POD is part of a deployment) and executing the env command.
The command has been further narrowed down by piping the output to grep and searching just for the KEY values.
salterje@k8s-master:~/YAML/configmaps$ kubectl get pods
NAME READY STATUS RESTARTS AGE
mytest-deployment-54bbbf5b4-sgsvb 1/1 Running 0 9m47s
#salterje@k8s-master:~/YAML/configmaps$ kubectl exec -it mytest-deployment-54bbbf5b4-sgsvb -- env | grep KEY
KEY1=This is some data that has been inserted into KEY1
KEY2=This is KEY2 from KEY2.properties
An easier way, that doesn't involve connecting to a running container is to describe the deployment and confirm the environmental values.
kubectl describe deployments mytest-deployment
salterje@k8s-master:~/YAML/configmaps$ kubectl describe deployments.apps mytest-deployment
Name: mytest-deployment
Namespace: default
CreationTimestamp: Fri, 10 Jul 2020 15:20:21 +0000
Labels: <none>
Annotations: deployment.kubernetes.io/revision: 4
Selector: app=mytest-deployment
Replicas: 1 desired | 1 updated | 1 total | 1 available | 0 unavailable
StrategyType: RollingUpdate
MinReadySeconds: 0
RollingUpdateStrategy: 25% max unavailable, 25% max surge
Pod Template:
Labels: app=mytest-deployment
Containers:
mytest-nginx:
Image: nginx
Port: 80/TCP
Host Port: 0/TCP
Environment:
KEY1: <set to the key 'KEY1.properties' of config map 'my-test-cm'> Optional: false
KEY2: <set to the key 'KEY2.properties' of config map 'my-test-cm'> Optional: false
Mounts: <none>
Volumes: <none>
It can be seen that this confirms the values have been imported and where from but it doesn't actually confirm what they have been set to. Of course it is a simple matter of looking at the ConfigMap.
Mounting ConfigMap Data into a Container
As well as setting environmental variables it is also possible to directly mount the data into the container. This is particularly useful for application config files that can be mounted directly into /etc.
We will now use the same ConfigMap and mount the values into /etc/config within the container.
This means that a VolumeMount must be created within the container which will define the MountPath as well as linking to a Volume, also defined within the manifest file.
The Volume defines that a ConfigMap will be used and will also link to the ConfigMap itself.
The relevent section of the manifest is shown below.
spec:
containers:
- image: nginx
imagePullPolicy: Always
name: mytest-nginx2
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
ports:
- containerPort: 80
volumeMounts: # volumeMount determines where to mount
- name: config-volume # Linking to the Volume
mountPath: /etc/config # Where to mount the Data within Container
volumes:
- name: config-volume # Linking to the VolumeMount
configMap: # This determines the volume is a ConfigMap
name: my-test-cm # This is the name of the actual ConfigMap
Care should be taken with the indentation of the volumes section which should should be the same as the containers section (the volumeMounts is part of the container section so should be indented accordingly).
We'll confirm the success of the operation in a similar manner to before, first logging onto the container and then through describing the deployment.
salterje@k8s-master:~/YAML/configmaps$ kubectl get pods
NAME READY STATUS RESTARTS AGE
mytest-deployment-54bbbf5b4-sgsvb 1/1 Running 0 44m
mytest-deployment2-7cb9d7dfdf-8x7jl 1/1 Running 0 10m
salterje@k8s-master:~/YAML/configmaps$ kubectl exec -it mytest-deployment2-7cb9d7dfdf-8x7jl -- /bin/bash
root@mytest-deployment2-7cb9d7dfdf-8x7jl:/# ls -lh /etc/config
total 0
lrwxrwxrwx 1 root root 22 Jul 10 16:27 KEY1.properties -> ..data/KEY1.properties
lrwxrwxrwx 1 root root 22 Jul 10 16:27 KEY2.properties -> ..data/KEY2.properties
root@mytest-deployment2-7cb9d7dfdf-8x7jl:/#
root@mytest-deployment2-7cb9d7dfdf-8x7jl:/# cat /etc/config/KEY1.properties
This is some data that has been inserted into KEY1
root@mytest-deployment2-7cb9d7dfdf-8x7jl:/# cat /etc/config/KEY2.properties
This is KEY2 from KEY2.properties
root@mytest-deployment2-7cb9d7dfdf-8x7jl:/#
It can be seen that the data within the ConfigMap has been mounted as two seperate files within the container.
The other way of proving the success is to describe the POD and look at the Volumes mounted.
ame: mytest-deployment2-7cb9d7dfdf-8x7jl
Namespace: default
Priority: 0
Node: k8s-node-2/192.168.56.31
Start Time: Fri, 10 Jul 2020 16:27:06 +0000
Labels: app=mytest-deployment2
pod-template-hash=7cb9d7dfdf
Annotations: cni.projectcalico.org/podIP: 192.168.140.90/32
cni.projectcalico.org/podIPs: 192.168.140.90/32
Status: Running
IP: 192.168.140.90
IPs:
IP: 192.168.140.90
Controlled By: ReplicaSet/mytest-deployment2-7cb9d7dfdf
Containers:
mytest-nginx2:
Container ID: docker://7972ad98e575567cf818bfc4ef19a623515dcb556a8356481222a26189683ba6
Image: nginx
Image ID: docker-pullable://nginx@sha256:21f32f6c08406306d822a0e6e8b7dc81f53f336570e852e25fbe1e3e3d0d0133
Port: 80/TCP
Host Port: 0/TCP
State: Running
Started: Fri, 10 Jul 2020 16:27:10 +0000
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/etc/config from config-volume (rw) # VolumeMount confirmed
/var/run/secrets/kubernetes.io/serviceaccount from default-token-jvv47 (ro)
Conditions:
Type Status
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
config-volume:
Type: ConfigMap (a volume populated by a ConfigMap)
Name: my-test-cm # ConfigMap mounted
Optional: false
default-token-jvv47:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-jvv47
Optional: false
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute for 300s
node.kubernetes.io/unreachable:NoExecute for 300s
It can be seen that the description of the POD shows the mount but the information needs to be combined with the description of the ConfigMap.
Conclusions
The two methods give an indication of how to use ConfigMaps to insert data into containers, rather then hard-coding into the application. This allows the same applications to have different configuration data by the simple modification of ConfigMap objects.
It can also be seen that there are a number of ways of confirming the operation including logging onto a container directly, although this wouldn't always be practical.