3.4. ConfigMaps

Similar to environment variables, ConfigMaps allow you to separate the configuration for an application from the image. Pods can access those variables at runtime which allows maximum portability for applications running in containers. In this lab, you will learn how to create and use ConfigMaps.

ConfigMap creation

A ConfigMap can be created using the kubectl create configmap command as follows:

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

Where the <data-source> can be a file, directory, or command line input.

Task 3.4.1: Java properties as ConfigMap

A classic example for ConfigMaps are properties files of Java applications which can’t be configured with environment variables.

First, create a file called java.properties with the following content:

key=value
key2=value2

Now you can create a ConfigMap based on that file:

kubectl create configmap javaconfiguration --from-file=./java.properties --namespace <namespace>

Verify that the ConfigMap was created successfully:

kubectl get configmaps --namespace <namespace>
NAME                DATA   AGE
javaconfiguration   1      7s

Have a look at its content:

kubectl get configmap javaconfiguration -o yaml --namespace <namespace>

Which should yield output similar to this one:

apiVersion: v1
kind: ConfigMap
metadata:
  name: javaconfiguration
data:
  java.properties: |
    key=value
    key2=value2    

Task 3.4.2: Attach the ConfigMap to a container

Next, we want to make a ConfigMap accessible for a container. There are basically the following possibilities to achieve this :

  • ConfigMap properties as environment variables in a Deployment
  • Command line arguments via environment variables
  • Mounted as volumes in the container

In this example, we want the file to be mounted as a volume inside the container.

Basically, a Deployment has to be extended with the following config:

      ...
        volumeMounts:
        - mountPath: /etc/config
          name: config-volume
      ...
      volumes:
      - configMap:
          defaultMode: 420
          name: javaconfiguration
        name: config-volume
      ...

Here is a complete example Deployment of a sample Java app:

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: spring-boot-example
  name: spring-boot-example
spec:
  progressDeadlineSeconds: 600
  replicas: 1
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      app: spring-boot-example
  strategy:
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 25%
    type: RollingUpdate
  template:
    metadata:
      labels:
        app: spring-boot-example
    spec:
      containers:
        - image: appuio/example-spring-boot
          imagePullPolicy: Always
          name: example-spring-boot
          resources: 
            limits:
              cpu: 1
              memory: 768Mi
            requests:
              cpu: 20m
              memory: 32Mi
          terminationMessagePath: /dev/termination-log
          terminationMessagePolicy: File
          volumeMounts:
            - mountPath: /etc/config
              name: config-volume
      dnsPolicy: ClusterFirst
      restartPolicy: Always
      schedulerName: default-scheduler
      securityContext: {}
      terminationGracePeriodSeconds: 30
      volumes:
        - configMap:
            defaultMode: 420
            name: javaconfiguration
          name: config-volume

This means that the container should now be able to access the ConfigMap’s content in /etc/config/java.properties. Let’s check:

kubectl exec <pod> --namespace <namespace> -- cat /etc/config/java.properties

Like this, the property file can be read and used by the application inside the container. The image stays portable to other environments.

Task 3.4.3: ConfigMap environment variables

Use a ConfigMap by populating environment variables into the container instead of a file.