KubernetesXX · ConfigurationConfiguration
Mounted volumes — ConfigMap as files inside the container
What you'll learn
- Configure a Pod that mounts a ConfigMap as files
- Distinguish file-mount semantics from env-var semantics
- Use subPath to mount a single key at a specific path
- Configure the application to reload when files change
Prerequisites
Verified against Kubernetes 1.34.x · kubeadm 1.34.x · kubectl 1.34.x · etcd 3.6.x · CoreDNS 1.11.x · containerd 1.7.x / 2.x · 2026-08-16
The file-mount consumption pattern projects ConfigMap keys as files inside a container. Unlike env vars, files update when the ConfigMap changes — but the update is eventually consistent (default ~60 seconds), and the application must detect and reload. This lesson covers the mount patterns, the timing, and the production discipline.
Mounting a ConfigMap as files
spec:
containers:
- name: web
image: web:v1
volumeMounts:
- name: config
mountPath: /etc/web
volumes:
- name: config
configMap:
name: web-config
The container sees every key in the ConfigMap as a file
under /etc/web:
/etc/web/log_level # contents: info
/etc/web/database_url # contents: postgres://...
/etc/web/feature_flags # contents: {...}
flowchart LR
A["ConfigMap<br/>keys + values"] -->|projected as files| B["/etc/web/"]
B --> C["Container process<br/>reads files"]
The files are tmpfs mounts managed by the kubelet. They
are not regular files; they are bind mounts from the
kubelet’s data directory. A df inside the container shows
the mount:
tmpfs 1G 0 1G 0% /etc/web
subPath for selective mounts
volumeMounts:
- name: config
mountPath: /etc/web/app.conf
subPath: app.conf
volumes:
- name: config
configMap:
name: web-config
subPath mounts a single key as a file at the specified
path. Useful when:
- The application expects a specific filename
(
/etc/web/app.conf, not/etc/web/app_conf). - The mount path overlaps with a directory the container
also writes to (a
subPathmount does not hide the directory’s existing contents).
flowchart TB
A[ConfigMap keys] -->|with subPath| B["/etc/web/app.conf<br/>(only this file)"]
A -->|without subPath| C["/etc/web/<br/>(all keys as files)"]
items for key selection
volumes:
- name: config
configMap:
name: web-config
items:
- key: log_level
path: log.txt
- key: database_url
path: db.txt
items projects a subset of keys. Each entry maps a key to
a path inside the mount. Useful when the ConfigMap has more
keys than the application needs.
Update semantics — eventually consistent
flowchart LR
A["ConfigMap updated<br/>in API server"] --> B["Kubelet watches<br/>API server"]
B --> C{Period elapsed?<br/>default syncPeriod}
C -->|yes| D[Kubelet updates
mount]
C -->|no| E[Wait]
D --> F["Container sees<br/>new file contents"]
The kubelet syncs the mount periodically. The default
syncPeriod is configurable via
--config-sync-period on the kubelet (typically 60s in
kubeadm clusters). The mount’s contents update within that
window after the ConfigMap change is observed.
Detecting the change in the application
The container sees the new file contents, but the application must detect and reload:
import time
import os
mtime = os.stat('/etc/web/log_level').st_mtime
while True:
time.sleep(5)
new_mtime = os.stat('/etc/web/log_level').st_mtime
if new_mtime != mtime:
reload_config()
mtime = new_mtime
The kubelet updates the file’s mtime when the contents change. The application polls the mtime (or the file contents directly) and triggers a reload.
Many applications support a SIGHUP for reload:
# PID of the application process, from `ps` inside the container.
# A container's main process is usually PID 1:
APP_PID=1
# Application receives SIGHUP and re-reads config
kill -HUP "$APP_PID"
A sidecar (e.g., a Reloader) can watch the file and send
SIGHUP to the main process when it changes.
flowchart TB
A[ConfigMap updated] --> B[Kubelet updates mount]
B --> C[File mtime changes]
C --> D{Application<br/>detects change?}
D -->|yes, poll| E[Reload config]
D -->|yes, SIGHUP| E
D -->|no| F["Application uses<br/>stale config"]
Default mode (file permissions)
volumes:
- name: config
configMap:
name: web-config
defaultMode: 0644
The kubelet creates the files with the specified mode. The
default is 0644 (world-readable). For sensitive files
(secrets, certificates), use 0400 (owner-readable only).
Real-world patterns
Pattern: nginx config
data:
nginx.conf: |
events { worker_connections 1024; }
http {
server {
listen 80;
location / { proxy_pass http://backend; }
}
}
volumeMounts:
- name: nginx-config
mountPath: /etc/nginx/nginx.conf
subPath: nginx.conf
volumes:
- name: nginx-config
configMap:
name: web-config
nginx -s reload reads the new config without restarting
the master process. The pattern: a sidecar watches the file
and runs nginx -s reload on change.
Pattern: Java application.properties
data:
application.properties: |
spring.datasource.url=jdbc:postgresql://db/data
spring.datasource.username=app
logging.level.root=INFO
volumeMounts:
- name: spring-config
mountPath: /app/config/application.properties
subPath: application.properties
Spring Boot reads application.properties at startup; for
hot reload, the application must be designed with
@RefreshScope or spring-cloud-config integration. A
plain Spring Boot does not reload on file change.
Pattern: TLS certificate as a file (intermediate)
data:
tls.crt: |
-----BEGIN CERTIFICATE-----
...
volumeMounts:
- name: tls
mountPath: /etc/tls/tls.crt
subPath: tls.crt
A TLS cert can be stored in a ConfigMap. (This is acceptable for non-secret certs and intermediate CAs; for private keys, use a Secret.) The application reads the file and uses it without restart.
Quiz
Knowledge check · 4 questions
Q1. How long does it take for a mounted ConfigMap file to reflect a change in the ConfigMap?
Q2. The kubelet's default sync period for ConfigMap and Secret volumes is 60 seconds, configurable via kubelet flags.
Q3. Your team's web application reads a config file mounted from a ConfigMap. The application does not reload on file change. Diagnose and remediate.
Application web reads /etc/web/app.conf at startup. The ConfigMap is updated to enable a feature. The kubelet updates the file within ~60s; the application continues with the old config.
Q4. Explain subPath in a ConfigMap volume mount, and when to use it.
Passing score: 75%. Answers are checked in this browser.
Production discipline
- Use file mounts for configuration that should update at runtime. Env vars are wrong for log levels, feature flags, or URLs that may change.
- Test the reload path. A mounted ConfigMap that the application does not reload is a config change that does nothing.
- Verify the kubelet’s syncPeriod. A 60-second default means 60 seconds of staleness after a ConfigMap change.
- Use
subPathwhen the application expects a specific filename. Mounting all keys at/etc/web/works only if the application reads that path. - Set
defaultModedeliberately. A0644mode on a Secret-mounted file is not what you want; use0400.
File mounts are the right pattern for configuration that must update at runtime. The application must be designed to detect the change and act; the kubelet’s syncPeriod determines the propagation delay. Operators who understand the timing have ConfigMaps that work.