Kubernetes ConfigMaps usage to declare env variables

In this tutorial we will learn how to set environment variables for a container using Kubernetes ConfigMaps.

 

Why do we need Kubernetes ConfigMap?

It is a good practice to make container images as reusable as possible. The same image should be able to be used for development, staging, and production. But it is possible these images are dependent on certain environment variables for example, the database URL to connect to so testing and versioning get riskier and more complicated if images need to be recreated for each new environment.

Advertisement

To overcome this problem, we can write our applications in such a way that the environment-specific data is provided to the application by the environment it is being deployed into. There are multiple ways to provide environment-specific configuration data to our application:

  • Provide command-line arguments to the Pods.
  • Provide environment variables to the Pods.
  • Mount configuration files in the containers.

 

Overview on Kubernetes ConfigMaps

  • A ConfigMap allows us to define application-related data.
  • It decouples the application data from the application so that the same application can be ported across different environments.
  • It also provides a way to inject customized data into running services from the same container image.
  • The key thing is that the ConfigMap is combined with the Pod right before it is run. This means that the container image and the Pod definition itself can be reused across many apps by just changing the ConfigMap that is used.

 

How to create ConfigMap

ConfigMaps can be created through a literal value or from a file or all the files in a directory, we will explore both these options in this tutorial. The command syntax to create a ConfigMap has the following format:

kubectl create configmap <map-name> <data-source>

Here, <map-name> is the name you want to assign to the ConfigMap and <data-source> is the directory, file, or literal value to draw the data from. The <data source> corresponds to a key-value pair in the ConfigMap, where:

  • Key is the filename or the key you provided on the command line
  • Value is the file content or the literal value you provided on the command line

When creating ConfigMaps, you can use a combination of all the options mentioned here:

$ kubectl create configmap my-config
➥   --from-file=foo.json         --> A single file
➥   --from-file=bar=foobar.conf  --> A file stored under a custom key
➥   --from-file=config-opts/     --> A whole directory
➥   --from-literal=some=thing    --> A literal value

 

Example-1: Create ConfigMap using file

Create data for the Pod

Following is a configuration file which we want to place in our nginx container. So I have created a separate file with the content to be added:

[root@controller ~]# cat nginx-custom-config.conf
server {
   listen       8888;
   server_name  localhost;
   location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
   }
}

 

Create ConfigMap

Next we will create our ConfigMap. Here cm is a short abbrevation for configmap.

Advertisement
[root@controller ~]# kubectl create cm nginx-cm --from-file nginx-custom-config.conf
configmap/nginx-cm created

 

Inspect ConfigMap content

So, our ConfigMap is successfully created, lets check the status:

[root@controller ~]# kubectl get cm
NAME       DATA   AGE
nginx-cm   1      6s

Let's see what the Kubernetes ConfigMap object looks like. Enter the kubectl get command as follows:

Ultimate guide on Kubernetes ConfigMaps & Secrets with examples

As you can see in the third line of the preceding output, the ConfigMap is created and the literal value we entered is available as a key-value pair in the data section of the ConfigMap. Here, the name of the file, nginx-custom-config.conf, becomes the key under the data section, and the entire file payload is the value of the key.

 

Create Pod using the ConfigMap

Now that we have defined our ConfigMap, the next step is to mount it onto a container. Create a YAML file named nginx-cm.yml to be used as our Pod configuration using the following content:

[root@controller ~]# cat nginx-cm.yml
apiVersion: v1
kind: Pod
metadata:
  name: nginx-cm
  labels:
    role: web
spec:
  containers:
  - name: nginx-cm
    image: nginx
    volumeMounts:
    - name: conf
      mountPath: /etc/nginx/conf.d
  volumes:
  - name: conf
    configMap:
      name: nginx-cm
      items:
      - key: nginx-custom-config.conf
        path: default.conf

First, let's focus on the volumes section in the preceding file. In this section, we are instructing Kubernetes to define a volume from our ConfigMap named conf. Here we want to include the key nginx-custom-config.conf and the entry's value should be stored at default.conf
Secondly, in the volumeMounts section, we are defining that Kubernetes should mount the volume in the /etc/nginx/conf.d directory. So the value from the key would be stored under /etc/nginx/conf.d/default.conf

NOTE:

The name field under the volume and volumeMounts sections has to be the same so that Kubernetes can identify which volume is associated with which volumeMounts.

Use the following command to start a Pod using the YAML file we just created:

[root@controller ~]# kubectl create -f nginx-cm.yml
pod/nginx-cm created

 

Verify ConfigMap data inside Pod's container

Next let's connect to this Pod and verify if our content was added into /etc/nginx/conf.d/default.conf:

Advertisement
[root@controller ~]# kubectl exec -it nginx-cm -- cat /etc/nginx/conf.d/default.conf
server {
   listen       8888;
   server_name  localhost;
   location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
   }
}

So we have just successfully defined a ConfigMap and mounted it as a file in a Pod that printed the name of the file.

 

Example-2: Create Kubernetes ConfigMap using command line arguments

Assign variable as command line argument

In this section we will assign single environment variables using ConfigMap by providing the key value pair as command line arguments instead of a file. Here color is the KEY while red is the VALUE of the KEY.

[root@controller ~]# kubectl create cm myconfig --from-literal=color=red
configmap/myconfig created

 

Inspect the ConfigMap

Once we create the ConfigMap, let's confirm that it is created by issuing a command to get all the ConfigMaps in the default namespace:

[root@controller ~]# kubectl get cm
NAME       DATA   AGE
myconfig   1      9s
nginx-cm   1      66m

Let's see what the Kubernetes ConfigMap object looks like. Enter the kubectl get command as follows:

Ultimate guide on Kubernetes ConfigMaps & Secrets with examples

As you can see in the highlighted section of the preceding output, the ConfigMap is created and the literal value we entered is available as a key-value pair in the data section of the ConfigMap.

 

Create Pod using ConfigMap

Now, we will create a YAML file named test-cm-pod.yml to create a Pod into which we will inject fields from our ConfigMap as an environment variable. Using your favorite text editor, create a YAML file with the following content:

[root@controller ~]# cat test-cm-pod.yml
apiVersion: v1
kind: Pod
metadata:
  name: test-pod
spec:
  containers:
  - name: test
    image: nginx
    env:
    - name: COLOR   ## Define the name of the variable
      valueFrom:
        configMapKeyRef:
          name: myconfig    ## Search for "myconfig" configmap which must be installed before creating this Pod
          key: color   ## The value of COLOR variable will be the value of "color" key in "myconfig" configmap i.e. "red"
  restartPolicy: Never

Here,

  • We are setting the environment variable called COLOR.
  • Instead of setting a fixed value, we are initializing it from a ConfigMap key.
  • The name of the ConfigMap you’re referencing is myconfig
  • We are setting the variable to whatever is stored under this key of color in the ConfigMap.

 

Verify environment variable inside the container

Once the Pod is up and running, we can connect to the Pod's container and make sure that our variable is SET:

Advertisement
[root@controller ~]# kubectl exec -it test-pod -- env | grep COLOR
COLOR=red

So we have just successfully defined an environment variable for the Pod using command line arguments with ConfigMap.

 

Example-3: Use Kubernetes ConfigMap to declare environment variables

We have performed the same exercise in the previous example but there we used input command line argument to declare the variable color=red. But if you have to define multiple variables then a YAML file solution would be more cleaner and efficient method.

In this example we will define multiple environment variables in our Pod using Kubernetes ConfigMap. To start with let us create a configmap to declare the key and value of the environment variables:

 ~]# cat configmap-1.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: declare-colors
data:
  # property-like keys; each key maps to a simple value
  color1: "red"
  color2: "blue"
  color3: "green"

Let us create this config map:

~]# kubectl create -f configmap-1.yaml
configmap/declare-colors created

Check the status of available configmaps, as you can see our configmap has 3 variables defined under DATA:

 ~]# kubectl get cm
NAME             DATA   AGE
declare-colors   3      7s

You can get the details of these variables using kubectl describe command:
Kubernetes ConfigMaps usage to declare env variables

Now we will use these KEYs inside our POD definition file. Here is a sample YAML file to create nginx pod:

 ~]# cat nginx-1.yaml
apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx
    env:
    - name: VAR1  ## Define the name of the variable
      valueFrom:
        configMapKeyRef:
          name: declare-colors   ## This must match the name of the configmap
          key: color1  ## The key to fetch
    - name: VAR2  ## Define the name of the variable
      valueFrom:
        configMapKeyRef:
          name: declare-colors   ## This must match the name of the configmap
          key: color2  ## The key to fetch
    - name: VAR3  ## Define the name of the variable
      valueFrom:
        configMapKeyRef:
          name: declare-colors   ## This must match the name of the configmap
          key: color3  ## The key to fetch
    imagePullPolicy: Always

Create this Pod:

~]# kubectl create -f nginx-1.yaml
pod/nginx created

Wait till the pod is in running state:

 ~]# kubectl get pods
NAME                            READY   STATUS    RESTARTS   AGE
nginx                           1/1     Running   0          14s

Now you can verify if your environment variables are set inside the Pod container as we defined in our Pod definition file:

~]# kubectl exec -it nginx -- printenv | grep VAR
VAR1=red
VAR2=blue
VAR3=green

 

Example-4: Kubernetes mount ConfigMap as file

In this example we will declare environment variables but rather than applying it to the Pod, we will store them in a separate file. This file will basically be mounted as read-only on the define path of the Pod container. We did something similar in Example-1 where we mounted nginx configuration file nginx-custom-config.conf on /etc/nginx/conf.d as default.conf. But there we had created our configmap from a file while here we will manually create our ConfigMap with the list of variables and filename.

Here is our YAML file to create the ConfigMap to mount variables as a file. I have defined the name of the data file as variables.conf. Inside this we have defined key value pairs.

NOTE:

There are two important points to note which are different compared to our previous example.
➥Here I am using equal to (=) sign to map the key and value instead of semi-colon (:). This is done to directly source variables.conf inside the Pod and use the data as variables.
➥Also here you will not have an option to provide an alternate variable name as we did earlier by using VAR1, VAR2 and VAR3 in previous example. Here the variable will be defined as color1: red and so on where color1 will act as the variable name.
~]# cat configmap-2.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: declare-vars
data:
  variables.conf: |
    color1="red"
    color2="blue"
    color3="green"

Let us create this configmap:

~]# kubectl create -f configmap-2.yaml
configmap/declare-vars created

Check the status of this configmap:

~]# kubectl get cm
NAME             DATA   AGE
declare-colors   3      90m
declare-vars     1      68s

Here DATA contains single value because we are storing all the variables inside variables.conf file.

Next we will create YAML file to create a Pod which will use this configmap. I have added enough comments to help you understand the chart:

~]# cat nginx-vars.yaml
apiVersion: v1
kind: Pod
metadata:
  name: nginx-vars
spec:
  containers:
  - name: nginx
    image: nginx
    volumeMounts:
    - name: variables
      mountPath: "/dir1"  ## This will be created if not present
  volumes:
    # You set volumes at the Pod level, then mount them into containers inside that Pod
    - name: variables  ## This must be same as name used under volumeMounts
      configMap:
        # Provide the name of the ConfigMap you want to mount.
        name: declare-vars
        # An array of keys from the ConfigMap to create as files
        items:
        - key: "variables.conf"  ## Key to fetch
          path: "default.conf"   ## Mount the file using this name.

Let us create this Pod and make sure it is in Running state:

~]# kubectl create -f nginx-vars.yaml
pod/nginx-vars created

~]# kubectl get pods
NAME                            READY   STATUS    RESTARTS   AGE
nginx                           1/1     Running   0          76m
nginx-vars                      1/1     Running   0          13s

Connect to this Pod and check if our default.conf file is mounted on /dir1:

[root@controller ~]# kubectl exec -it nginx-vars -- bash
root@nginx-vars:/# cat /dir1/default.conf
color1="red"
color2="blue"
color3="green"
root@nginx-vars:/# source /dir1/default.conf

root@nginx-vars:/# echo $color1
red
root@nginx-vars:/# echo $color2
blue
root@nginx-vars:/# echo $color3
green

 

 

Conclusion

In this Kubernetes Tutorial, we have seen the different ways that Kubernetes provides to associate environment-specific data with our applications running as containers. Kubernetes provides ways to store normal application data as ConfigMaps. We have also seen how to create ConfigMaps and associate it with our containers via CLI. Associating data with containers enables us to use the same container across different environments in our IT systems (for example, in test and production). Separating configuration from application code will make your applications more reliable and reusable.

Didn't find what you were looking for? Perform a quick search across GoLinuxCloud

If my articles on GoLinuxCloud has helped you, kindly consider buying me a coffee as a token of appreciation.

Buy GoLinuxCloud a Coffee

For any other feedbacks or questions you can either use the comments section or contact me form.

Thank You for your support!!

Leave a Comment