Learn how to configure Kubernetes apps using ConfigMap

abhirockzz

Abhishek Gupta

Posted on September 18, 2019

Learn how to configure Kubernetes apps using ConfigMap

"Separation of configuration from code" is one of the tenets of the 12-factor applications. We externalize things which can change and this in turn helps keep our applications portable. This is critical in the Kubernetes world where our applications are packaged as Docker images. A Kubernetes ConfigMap allows us to abstract configuration from code and ultimately the Docker image.

This blog post will provide a hands-on guide to app configuration related options available in Kubernetes.

As always, the code is available on GitHub. So let's get started....

To configure your apps in Kubernetes, you can use:

  • Good old environment variables
  • ConfigMap
  • Secret — this will be covered in a subsequent blog post

You will need a Kubernetes cluster to begin with. This could be a simple, single-node local cluster using minikube, Docker for Mac etc. or a managed Kubernetes service from Azure (AKS), Google, AWS etc. To access your Kubernetes cluster, you will need kubectl, which is pretty easy to install.

e.g. to install kubectl for Mac, all you need is

curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/darwin/amd64/kubectl && \
chmod +x ./kubectl && \
sudo mv ./kubectl /usr/local/bin/kubectl
Enter fullscreen mode Exit fullscreen mode

Using Environment Variables for configuration

Let’s start off with an easy peasy example to see how to use environment variables by specifying them directly within our Pod specification.

Notice how we define two variables in spec.containers.env — ENVVAR1 and ENVVAR2 with values value1 and value2 respectively.

Let’s start off by creating the Pod using the YAML specified above.

Pod is just a Kubernetes resource or object. The YAML file is something that describes its desired state along with some basic information - it is also referred to as a manifest, spec (shorthand for specification) or definition.

Use the kubectl apply command to submit the Pod information to Kubernetes.

To keep things simple, the YAML file is being referenced directly from the GitHub repo, but you can also download the file to your local machine and use it in the same way.

$ kubectl apply -f   https://raw.githubusercontent.com/abhirockzz/kubernetes-in-a-nutshell/master/configuration/kin-config-envvar-in-pod.yaml

pod/pod1 created
Enter fullscreen mode Exit fullscreen mode

To check the environment variables, we will need to execute a command "inside" of the Pod using kubectl exec — you should see the ones which were seeded in the Pod definition.

Here, we have used grep to filter for the variable(s) we’re interested in

$ kubectl exec pod1 -it -- env | grep ENVVAR

ENVVAR1=value1
ENVVAR2=value2
Enter fullscreen mode Exit fullscreen mode

What's kubectl exec? In simple words, it allows you to execute a command in specific container within a Pod. In this case, our Pod has a single container, so we don't need to specify one

Ok, with that concept out of the way, we can explore ConfigMaps.

Using a ConfigMap

The way it works is that your configuration is defined in a ConfigMap object which is then referenced in a Pod (or Deployment).

Let’s look at techniques using which you can create a ConfigMap

Using a manifest file

It’s possible to create a ConfigMap along with the configuration data stored as key-value pairs in the data section of the definition.

In the above manifest:

  • the ConfigMap named simpleconfig contains two pieces of (key-value) data — hello=world and foo=bar
  • simpleconfig is referenced by a Pod (pod2; the keys hello and foo are consumed as environment variables HELLO_ENV_VAR and FOO_ENV_VAR respectively.

Note that we have included the Pod and ConfigMap definition in the same YAML separated by a ---

Create the ConfigMap and confirm that the environment variables have been seeded

$ kubectl apply -f   https://raw.githubusercontent.com/abhirockzz/kubernetes-in-a-nutshell/master/configuration/kin-config-envvar-configmap.yaml

configmap/config1 created
pod/pod2 created

$ kubectl get configmap/config1

NAME      DATA   AGE
config1   2      18s

$ kubectl exec pod2 -it -- env | grep _ENV_

FOO_ENV_VAR=bar
HELLO_ENV_VAR=world
Enter fullscreen mode Exit fullscreen mode

Shortcut using envVar

We consumed both the config data (foo and hello) by referencing them separately, but there is an easier way! We can use envFrom in our manifest to directly refer to all key-value data in a ConfigMap.

When using ConfigMap data this way, the key is directly used as the environment variable name. That’s why you need to follow the naming convention i.e. Each key must consist of alphanumeric characters, ‘-’, ‘_’ or ‘.’

Just like before, we need to create the Pod and ConfigMap and confirm the existence of environment variables

$ kubectl apply -f   https://raw.githubusercontent.com/abhirockzz/kubernetes-in-a-nutshell/master/configuration/kin-config-envvar-with-envFrom.yaml

configmap/config2 created
pod/pod3 created

$ kubectl get configmap/config2

NAME      DATA   AGE
config2   2      25s

$ kubectl exec pod3 -it -- env | grep _ENV

HELLO_ENV=world
FOO_ENV=bar
Enter fullscreen mode Exit fullscreen mode

Nice little trick ha? :-)

Configuration data as files

Another interesting way to consume configuration data is by pointing to a ConfigMap in the spec.volumes section of your Deployment or Pod spec.

If you have no clue what Volumes (in Kubernetes) are, don’t worry. They will be covered in upcoming blogs. For now, just understand that volumes are a way of abstracting your container from the underlying storage system e.g. it could be a local disk or in the cloud such as Azure Disk, GCP Persistent Disk etc.

In the above spec, pay attention to the spec.volumes section — notice that it refers to an existing ConfigMap. Each key in the ConfigMap is added as a file to the directory specified in the spec i.e. spec.containers.volumeMount.mountPath and the value is nothing but the contents of the file.

Note that the files in volumes are automatically updated if the ConfigMap changes.

In addition to traditional string based values, you can also include full-fledged files (JSON, text, YAML, etc.) as values in a ConfigMap spec.

In the above example, we have embedded an entire JSON within the data section of our ConfigMap. To try this out, create the Pod and ConfigMap

$ kubectl apply -f   https://raw.githubusercontent.com/abhirockzz/kubernetes-in-a-nutshell/master/configuration/kin-config-envvar-json.yaml

configmap/config3 created
pod/pod4 created

$ kubectl get configmap/config3

NAME      DATA   AGE
config3   1     11s
Enter fullscreen mode Exit fullscreen mode

As an exercise, confirm that the environment variable was seeded into the Pod. Few pointers:

  • the name of the Pod is pod4
  • double-check the name of the environment variable you should be looking for

You can also use kubectl CLI to create a ConfigMap. It might not be suitable for all use cases but it certainly makes things a lot easier

Using kubectl

There are multiple options:

Using --from-literal to seed config data

We’re seeding the following key-value pairs into the ConfigMap — foo_env=bar and hello_env=world

$ kubectl create configmap config4 --from-literal=foo_env=bar --from-literal=hello_env=world
Enter fullscreen mode Exit fullscreen mode

Using --from-file

$ kubectl create configmap config5 --from-file=/config/app-config.properties
Enter fullscreen mode Exit fullscreen mode

This will create a ConfigMap (config5) with

  • a key with the same name of the file i.e. app-config.properties in this case
  • and, value as the contents of the file

You can choose to use a different key (other than the file name) to override the default behavior

$ kubectl create configmap config6 --from-file=CONFIG_DATA=/config/app-config.properties
Enter fullscreen mode Exit fullscreen mode

In this case, CONFIG_DATA will be the key

From files in a directory

You can seed data from multiple files (in a directory) at a time into a ConfigMap

$ kubectl create configmap config7 --from-file=/home/foo/config/
Enter fullscreen mode Exit fullscreen mode

You will end up with

  • multiple keys which will the same as the individual file name
  • the value will be the contents of the respective file

Good to know

Here is a (non-exhaustive) list of things which you should bear in mind when using ConfigMaps:

  • Once you define environment variables ConfigMap, you can utilize them in the command section in Pod spec i.e. spec.containers.command using the $(VARIABLE_NAME) format
  • You need to ensure that the ConfigMap being referenced in a Pod is already created — otherwise, the Pod will not start. The only way to get around this is to mark the ConfigMap as optional.
  • Another case in which might prevent the Pod from starting is when you reference a key that actually does not exist in the ConfigMap.

You can also refer the ConfigMap API

That's it for this edition of the "Kubernetes in a Nutshell" series. Stay tuned for more!

If you are interested in learning Kubernetes and Containers using Azure, simply create a free account and get going! A good starting point is to use the quickstarts, tutorials and code samples in the documentation to familiarize yourself with the service. I also highly recommend checking out the 50 days Kubernetes Learning Path. Advanced users might want to refer to Kubernetes best practices or watch some of the videos for demos, top features and technical sessions.

I really hope you enjoyed and learned something from this article! Please like and follow if you did. Happy to get feedback via @abhi_tweeter or just drop a comment.

💖 💪 🙅 🚩
abhirockzz
Abhishek Gupta

Posted on September 18, 2019

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related