To myself...

Most apps require settings that are unique to themselves. Some of these settings can be credentials, others are not so sensitive but still need to be managed when these apps get deployed. These settings are what we usually called configs or configurations in software domain.

A little history

Going back to the old ways of doing things, when an app is deployed, it will usually contain a file alongside it that will hold the sensitive and non-sensitive configuration. After the introduction of Docker, it's a very similar way of deployment except that the image that is packaged also contains the configuration within it.

So what's so wrong with this approach? Well for one, when some config needs to be changed, the image needs to be recompiled and redeployed again. Another reason is that the confidential information such as API keys or passwords is exposed as plaintext. Anyone that can get into the system can alter these things!

What about using volumes in Docker? That's a good catch but volumes for config files still require to or mounted first before the container is started.

So is there really a way to solve these problems better? Yes of course! Using Kubernetes ConfigMap and Secret are the keys to manage these issues.

What is a ConfigMap?

ConfigMap is a top-level Kubernetes resource to store configuration data, called environment variables, inside a container in a decoupled way. At its core, ConfigMap is a map of key/value pairs.

What do you mean by decoupled? It means that the running container doesn't need to know the existence of the ConfigMap because upon the creation of ConfigMap, its contents are passed to the container as either environment variables or as files in a volume.

Creating a ConfigMap

There are 3 ways to create a ConfigMap in Kubernetes.

  1. with a literal
  2. with a manifest file
  3. with a config file
  4. with an env file

Let's start an example of informing our app how to locate the API for users. In here we define apiUrl as the key and the value is https://my-site.com/api/users

Option 1

There's no file. We directly tell Kubernetes our setting/s from the command line.

Command to run

 kubectl create configmap [cm-name]  --from-literal=apiUrl=https://my-site.com/api/users 

Option 2

There needs to be a manifest file and the format is

 apiVersion: v1 kind: ConfigMap metadata:   name: app-settings   labels:     app: app-settings data:   apiUrl: "https://my-site.com/api/users" 

Command to run

 kubectl create -f configmap.yml 

Notice that the command doesn't need to explicitly invoke the configmap. This is because the manifest file declares the kind of file as ConfigMap.

Option 3

A typical config file, let's call it api.config

 apiUrl=https://my-site.com/api/users 

Command to run

 kubectl create configmap [cm-name] --from-file=[path-to-file] 

Under the hood, Kubernetes will generate a ConfigMap

 apiVersion: v1 kind: ConfigMap data:   api.config: |-     apiUrl=https://my-site.com/api/users 

The file name api.config is the key.

Option 4

With env file, for instance, api.env

 apiUrl=https://my-site.com/api/users 

Command to run

 kubectl create configmap [cm-name] --from-env-file=[path-to-file] 

Under the hood, Kubernetes will generate a ConfigMap

 apiVersion: v1 kind: ConfigMap data:   apiUrl=https://my-site.com/api/users 

The file name api.env is not included as the key.

Consuming a ConfigMap

So now that we know how to create a ConfigMap, what's next? Well, the following step is to create it of course and let it be consumed by pods or containers.

Accessing a ConfigMap via Environment Variables

Let's say we opted for option 4 using env file. We can let the pod access the ConfigMap by appending an env key like below.

 apiVersion: apps/v1 ... spec:   template:     ...   spec:     containers: ...     env:     - name: APIURL      valueFrom:        configMapKeyRef:          name: app-settings          key: apiUrl 

The pod now has an environment variable name called APIURL with its value reference from the ConfigMap data apiUrl.

In reality, the env file will contain more entries. In this case, if there's a need to use up all the environment variables without declaring them one after another, we can use envFrom key instead of env key.

 envFrom: - configMapRef:   name: app-settings 

Now all the entries in the env file is available to the pod 🙂

Accessing a ConfigMap via Volume

With this approach, it is possible to change the settings without redeploying the container. Although there would be 30-60 second delay, for most cases, this is sufficient.

 apiVersion: v1 ... spec:   template:     ...   spec:     volumes:       - name: app-config-vol         configMap           name: app-settings     containers:       volumeMounts:         - name: app-config-vol           mountPath: /etc/config  

This free site is ad-supported. Learn more