Chapter 18 of 47 · Configuration and security, part 1

ConfigMaps: configuration outside the image

In chapter 17 the same EVENT_BUS_URL was copied into four Deployments. A ConfigMap is a small Kubernetes object that holds settings in one place, separate from your image and from your Deployments. Pods then read it as environment variables or as files.

Why decouple config

Image, ConfigMap and PodThe image holds code. The ConfigMap holds settings. The Pod combines both when it starts. Dev and prod use the same image with different ConfigMaps. Image micro-posts:1.0code only, built once ConfigMap app-configLOG_LEVEL=debugEVENT_BUS_URL=… Podcode + settings Same image everywhere: dev → app-config (debug) test → app-config (info) prod → app-config (error) Change a setting withoutrebuilding the image.

A ConfigMap

It is just a list of keys and values under data. Click the parts:

apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:
  LOG_LEVEL: debug
  EVENT_BUS_URL: http://event-bus-srv:4005
  MAX_UPLOAD_MB: "10"
  config.json: |
    {
      "featureFlags": { "newEditor": true },
      "pageSize": 20
    }

data

Keys and values, all text. Like env vars, numbers and true need quotes: "10".

Three ways to use it

containers:
  - name: posts
    image: micro-posts:1.0
    env:
      - name: LOG_LEVEL              # name inside the container
        valueFrom:
          configMapKeyRef:
            name: app-config         # which ConfigMap
            key: LOG_LEVEL           # which key in it

Pick single keys. The env var name can differ from the key. Instead of value: you write valueFrom:. Everything else from chapter 16 stays the same: your app reads process.env.LOG_LEVEL.

Creating one with kubectl

$ kubectl create configmap app-config \
    --from-literal=LOG_LEVEL=debug \
    --from-literal=MAX_UPLOAD_MB=10

Values typed on the command line.

What happens on a change

You edit the ConfigMap and apply it. Do running Pods see the new value? Try it:

Used asAfter you change the ConfigMap
env var (valueFrom, envFrom)Never updated in a running container. Restart: kubectl rollout restart deployment/<name>
volume (files)Files are updated after a short delay (up to about a minute). Your app must re-read them. Not updated if mounted with subPath.
Simple rule: after changing a ConfigMap, run kubectl rollout restart on the Deployments that use it. Every Pod then starts fresh with the new values.

Fixing the blog app

Back to chapter 17: the event bus URL was repeated in four Deployments. Move it into one ConfigMap:

Before (×4)

env:
  - name: EVENT_BUS_URL
    value: http://event-bus-srv:4005

After

# services-config.yaml (once)
apiVersion: v1
kind: ConfigMap
metadata:
  name: services-config
data:
  EVENT_BUS_URL: http://event-bus-srv:4005
  POSTS_URL: http://posts-srv:4000
  COMMENTS_URL: http://comments-srv:4001
  QUERY_URL: http://query-srv:4002
  MODERATION_URL: http://moderation-srv:4003

# in every Deployment's container
envFrom:
  - configMapRef:
      name: services-config

Rename a Service now and you change one line, not four. Each service simply ignores the URLs it does not need.

Good to know

Recap

Quick check

You change LOG_LEVEL in the ConfigMap and apply. kubectl apply on the Deployment says "unchanged" and the Pods still log at debug. Why?
Show answer

The Deployment's YAML did not change, only the ConfigMap did, so no rollout happened. The Pods still hold the env var they got at start. Run kubectl rollout restart deployment/posts-depl.

ConfigMaps: common questions

Do Pods see ConfigMap changes automatically?

Env vars never change in a running container; restart the Deployment with kubectl rollout restart. Files mounted from a ConfigMap volume are refreshed after a short delay.