ConfigMap

ConfigMap is the Kubernetes resource that allows you to externalize your application’s configuration.

An app’s config is everything that is likely to vary between deploys (staging, production, developer environments, etc).

Environment Variables

MyRESTController.java includes a small chunk of code that looks to the environment

   @RequestMapping("/configure")
   public String configure() {
        String databaseConn = environment.getProperty("DBCONN","Default");
        String msgBroker = environment.getProperty("MSGBROKER","Default");
        String hello = environment.getProperty("GREETING","Default");
        String love = environment.getProperty("LOVE","Default");
        return "Configuration: \n"
            + "databaseConn=" + databaseConn + "\n"
            + "msgBroker=" + msgBroker + "\n"
            + "hello=" + hello + "\n"
            + "love=" + love + "\n";
   }

Environment variables can be manipulated at the Deployment level. Changes cause Pod redeployment.

Deploy myboot:

kubectl apply -f apps/kubefiles/myboot-deployment.yml

Deploy myboot Service:

kubectl apply -f apps/kubefiles/myboot-service.yml

And watch the pods status:

watch -n 1 -- kubectl get pods

Ask the application for its configuration:

  • Minikube

  • Hosted

IP=$(minikube ip -p devnation)
PORT=$(kubectl get service/myboot -o jsonpath="{.spec.ports[*].nodePort}")

If using a hosted Kubernetes cluster like OpenShift then use curl and the EXTERNAL-IP address with port 8080 or get it using kubectl:

IP=$(kubectl get service myboot -o jsonpath="{.status.loadBalancer.ingress[0].ip}")
PORT=$(kubectl get service myboot -o jsonpath="{.spec.ports[*].port}")
If you are in AWS, you need to get the hostname instead of ip.
IP=$(kubectl get service myboot -o jsonpath="{.status.loadBalancer.ingress[0].hostname}")

Curl the Service:

curl $IP:$PORT
curl $IP:$PORT/configure
Configuration for : myboot-66d7d57687-jsbz7
databaseConn=Default
msgBroker=Default
greeting=Default
love=Default

Set Environment Variables

kubectl set env deployment/myboot GREETING="namaste" \
  LOVE="Aloha" \
  DBCONN="jdbc:sqlserver://45.91.12.123:1443;user=MyUserName;password=*****;"

Watch the pods being reborn:

NAME                      READY   STATUS        RESTARTS   AGE
myboot-66d7d57687-jsbz7   1/1     Terminating   0          5m
myboot-785ff6bddc-ghwpc   1/1     Running       0          13s
curl $IP:$PORT/configure
Configuration for : myboot-5fd9dd9c59-58xbh
databaseConn=jdbc:sqlserver://45.91.12.123:1443;user=MyUserName;password=*****;
msgBroker=Default
greeting=namaste
love=Aloha

Describe the deployment:

kubectl describe deployment myboot
...
  Containers:
   myboot:
    Image:      quay.io/burrsutter/myboot:v1
    Port:       8080/TCP
    Host Port:  0/TCP
    Environment:
      GREETING:  namaste
      LOVE:      Aloha
      DBCONN:    jdbc:sqlserver://45.91.12.123:1443;user=MyUserName;password=*****;
    Mounts:      <none>
  Volumes:       <none>
...

Remove environment variables:

kubectl set env deployment/myboot GREETING- \
  LOVE- \
  DBCONN-

And verify that they have been removed:

curl $IP:$PORT/configure
Configuration for : myboot-66d7d57687-xkgw6
databaseConn=Default
msgBroker=Default
greeting=Default
love=Default

Create a ConfigMap

kubectl create cm my-config --from-env-file=apps/config/some.properties
kubectl get cm
kubectl get cm my-config
kubectl get cm my-config -o json
...
    "data": {
        "GREETING": "jambo",
        "LOVE": "Amour"
    },
    "kind": "ConfigMap",
...

Or you can describe the ConfigMap object:

kubectl describe cm my-config
Name:         my-config
Namespace:    myspace
Labels:       <none>
Annotations:  <none>

Data
====
GREETING:
====
jambo
LOVE:
====
Amour
Events:  <none>
Using kubectl edit to view resources

For large files you might find using kubectl edit is more convenient for viewing resources on the cluster. In our case, we can view the config map by running the following (and aborting any changes!):

If you’re running this tutorial from within VSCode or would like to use VSCode to edit the resource targeted, make sure you set the following environment variable before issuing the kubectl edit:

export KUBE_EDITOR="code -w"
kubectl edit cm my-config

Now deploy the app with its request for the ConfigMap:

kubectl apply -f apps/kubefiles/myboot-deployment-configuration.yml

And get its configure endpoint:

curl $IP:$PORT/configure
Configuration for : myboot-84bfcff474-x6xnt
databaseConn=Default
msgBroker=Default
greeting=jambo
love=Amour

And switch to the other properties file by recreating the ConfigMap:

kubectl delete cm my-config
kubectl create cm my-config --from-env-file=apps/config/other.properties
kubectl delete pod -l app=myboot --wait=false
curl $IP:$PORT/configure
Configuration for : myboot-694954fc6d-nzdvx
databaseConn=jdbc:sqlserver://123.123.123.123:1443;user=MyUserName;password=*****;
msgBroker=tcp://localhost:61616?jms.useAsyncSend=true
hello=Default
love=Default

There are a lot more ways to have fun with ConfigMaps. The core documentation has you manipulate a Pod specification instead of a Deployment, but the results are basically the same: https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap

Clean Up

kubectl delete deployment myboot
kubectl delete cm my-config
kubectl delete service myboot