14. ConfigMaps

ConfigMaps can be used to decouple a container’s configuration from its image specification.

14.1. ConfigMap as environment variables

First, create the ConfigMap:

$ cat > my-config-map.txt <<EOF
  key1=value1
  key2=value2
  EOF
$ kubectl create configmap my-config --from-env-file=my-config-map.txt
configmap/my-config created
$ kubectl get cm
NAME               DATA   AGE
kube-root-ca.crt   1      176m
my-config          2      70s
$ kubectl get cm my-config -o yaml | yq
apiVersion: v1
data:
  key1: value1
  key2: value2
kind: ConfigMap
metadata:
  creationTimestamp: "2024-08-04T19:30:11Z"
  name: my-config
  namespace: default
  resourceVersion: "8903"
  uid: f1829248-7f5d-42b2-9b38-f41ab8f420ba

Then, create the pod:

config-map.yaml
apiVersion: v1
kind: Pod
metadata:
  name: config-env
spec:
  containers:
    - image: busybox
      name: config-env
      command: ["/bin/sh", "-c", "env"]
      envFrom:
        - configMapRef:
            name: my-config
  restartPolicy: Never

This pod will write the environment variables to its output, then quit

$ kubectl create -f config-map.yaml
pod/config-env created
$ kubectl get pod
NAME                     READY   STATUS      RESTARTS   AGE
config-env               0/1     Completed   0          24s
$ kubectl logs pod/config-env | grep key
key1=value1
key2=value2
$ kubectl delete pod/config-env
pod "config-env" deleted

Note the use of kubectl logs to get the output of a completed pod.

14.2. ConfigMaps as volumes

Let us define two index.html files:

green/index.html
<html>
    <head>
        <title>Welcome to GREEN App!</title>
        <style>
            body {
                width: 35em;
                margin: 0 auto;
                font-family: Arial, sans-serif;
                background-color: #009900;
            }
        </style>
    </head>
    <body>
        <h1 style=\"text-align: center;\">Welcome to GREEN App!</h1>
    </body>
</html>

Note that the above file is not a true HTML file; the double quotes have been escaped.

$ kubectl create cm green-web-cm --from-file=green/index.html
configmap/green-web-cm created
$ kubectl describe cm/green-web-cm
Name:         green-web-cm
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
index.html:
----
<html>
    <head>
        <title>Welcome to GREEN App!</title>
        <style>
            body {
                width: 35em;
                margin: 0 auto;
                font-family: Arial, sans-serif;
                background-color: #009900;
            }
        </style>
    </head>
    <body>
        <h1 style=\"text-align: center;\">Welcome to GREEN App!</h1>
    </body>
</html>


BinaryData
====

Events:  <none>
green-web.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: green-web
  name: green-web
spec:
  replicas: 1
  selector:
    matchLabels:
      app: green-web
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: green-web
    spec:
      volumes:
      - name: web-config
        configMap:
          name: green-web-cm
      containers:
      - image: nginx
        name: nginx
        ports:
        - containerPort: 80
        volumeMounts:
        - mountPath: /usr/share/nginx/html
          name: web-config
$ kubectl apply -f green-web.yaml
deployment.apps/green-web created
$ kubectl expose deploy/green-web --type=NodePort
service/green-web exposed
$ kubectl port-forward --address 0.0.0.0,:: svc/green-web 8000:80
Forwarding from 0.0.0.0:8000 -> 80
Forwarding from [::]:8000 -> 80

In another window, use sed to replace “blue with “green” in the two files, and deploy another service:

$ sed 's/green/blue/g' green-web.yaml > blue-web.yaml
$ mkdir blue
$ sed 's/GREEN/BLUE/g' green/index.html | sed 's/009900/000099/' > blue/index.html
$ kubectl create cm blue-web-cm --from-file=blue/index.html
$ kubectl get cm
NAME               DATA   AGE
blue-web-cm        1      5s
green-web-cm       1      14m
kube-root-ca.crt   1      3h38m
my-config          2      43m
$ kubectl apply -f blue-web.yaml
deployment.apps/blue-web created
$ kubectl expose deploy/blue-web --type=NodePort
service/blue-web exposed
$ kubectl port-forward --address 0.0.0.0,:: svc/blue-web 8080:80
Forwarding from 0.0.0.0:8080 -> 80
Forwarding from [::]:8080 -> 80

Note

Templating tools, e.g., Kustomize, can be used to manage the generation of similar resource declarations like the two we just made. For examples, see: https://dev.to/stack-labs/kustomize-the-right-way-to-do-templating-in-kubernetes-3ohp.