18.3 Consuming ConfigMaps as Mounted Files
Right, so you’ve defined your ConfigMap. Good for you. Now, how do you actually get those configuration values into your grumpy little application that expects a good old-fashioned file on the filesystem? You mount it. This is the most robust and common way to consume ConfigMaps, and it works exactly like it sounds: you take the contents of the ConfigMap and make them appear as files in a directory inside your Pod.
Think of it as a highly specialized, read-only network drive that gets plumbed directly into your container. Your application doesn’t need to know a thing about Kubernetes; it just wakes up and finds its config.yaml sitting right where it expects it, blissfully unaware of the containerized magic that put it there.
The Basic Mount
Here’s the anatomy of a Pod spec that mounts a ConfigMap. Let’s assume you have a ConfigMap named app-config with a single key, application.properties.
apiVersion: v1
kind: Pod
metadata:
name: config-pod
spec:
containers:
- name: my-app
image: nginx
volumeMounts:
- name: app-config-volume # This must match the volume name below
mountPath: /etc/config # The directory inside the container where files will appear
volumes:
- name: app-config-volume # This defines a volume for the Pod
configMap:
name: app-config # The name of the ConfigMap we created earlier
Apply this, and then kubectl exec into the pod. You’ll find a file at /etc/config/application.properties containing the exact data you had in your ConfigMap’s key. Every key in the ConfigMap becomes its own file in the mounted directory, with the key as the filename and the key’s value as the file’s content. It’s beautifully straightforward.
Controlling File Permissions and Paths
Now, the default mode for these mounted files is 644 (-rw-r--r--). This is usually fine, but sometimes your ancient legacy application demands a specific, more restrictive permission, like 600. Kubernetes has you covered, though its implementation is a bit… quirky.
volumes:
- name: app-config-volume
configMap:
name: app-config
defaultMode: 0600 # Sets permissions for all files in the mount
Here’s the quirky part: you specify the mode in decimal notation, not octal. So while you’d use chmod 600 on a Linux shell, you use 0600 (which is 600 in decimal) in your YAML. It’s a common trip-up. If you need to set different permissions for different keys, you’re out of luck on a single mount; you’ll need to use separate ConfigMaps or volumes.
You can also project specific keys into specific paths, which is incredibly useful if you don’t want the entire ConfigMap dumped into a directory.
volumes:
- name: app-config-volume
configMap:
name: app-config
items:
- key: application.properties # The key in the ConfigMap
path: app/props.cfg # The name of the file to create at the mountPath
With this, only the application.properties key gets mounted, and it shows up as /etc/config/app/props.cfg. The rest of the ConfigMap’s keys are ignored for this volume. This is your best friend for avoiding a messy directory when you only need one or two files.
The Magical Live Update (And Its Gotchas)
This is the coolest part, and nobody tells you about it: ConfigMap mounts are not static. If you update the ConfigMap with kubectl apply, the changes are automatically propagated to all Pods that have it mounted. The file inside the running container will change. Magic!
But—and this is a massive “but”—this behavior is both a feature and a foot-cannon.
How it works: The kubelet on each node watches for changes to the mounted ConfigMap and updates the symbolic links in the Pod’s volume directory. The application sees the updated file content the next time it reads the file.
Why it’s a pitfall: Most applications do not watch for changes to their config files. They read the config once on startup and then never again. So your update will be completely ignored until the Pod is restarted. For applications that do watch for live changes (like NGINX, which reloads its config on a signal), this feature is pure gold.
The other, subtler gotcha is update propagation time. The kubelet checks for updates on a sync interval, which by default can take up to a minute. Your change is not instantaneous.
What Happens If the ConfigMap Doesn’t Exist?
Let’s be honest, you’re going to do this eventually. You’ll typo the ConfigMap name in your Pod spec and apply it. What happens?
The Pod will fail to start. The volume manager will look for the ConfigMap, can’t find it, and will refuse to schedule the container. It’s actually the best possible behavior. A failing Pod is obvious. A Pod that starts with missing configuration is a silent, runtime failure waiting to happen, and those are a nightmare to debug. Kubernetes saves you from yourself here.
The inverse is also important: if a Pod is running and you delete the ConfigMap it’s using, the mounted files don’t disappear. They’re still there, frozen in time. The Pod will keep running. Try to kubectl describe the Pod, and you’ll see angry warnings about the volume referencing a non-existent ConfigMap. It’s a weird, inconsistent state you should avoid. Always update ConfigMaps, never delete and recreate them while Pods are using them.