Stage 5 · Platform
Configuration & Secrets Management
Environment & Volume Injection
envFrom, valueFrom, projected volumes, subPath mounts, and update propagation behavior.
Environment Variable Injection
Kubernetes injects environment variables from ConfigMaps, Secrets, and the Downward API. envFrom injects all keys from a resource. env injects specific keys. Environment variables are set at container creation and do not change without restart.
apiVersion: v1
kind: Pod
metadata:
name: env-demo
spec:
containers:
- name: app
image: my-app:1.0
envFrom:
- configMapRef:
name: app-config
- secretRef:
name: db-credentials
- configMapRef:
name: feature-flags
prefix: FEATURE_ # Adds FEATURE_ prefix to all keys
env:
- name: SPECIFIC_VALUE
valueFrom:
configMapKeyRef:
name: app-config
key: LOG_LEVEL
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-credentials
key: password
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.nameenvFrom injects all keys. prefix adds a prefix to avoid name collisions. env with valueFrom injects specific keys. fieldRef injects pod metadata. These are set at container start and never change.
valueFrom Sources
valueFrom supports four sources: configMapKeyRef (ConfigMap key), secretKeyRef (Secret key), fieldRef (pod/container metadata), and resourceFieldRef (resource limits/requests). Each provides different types of runtime information.
env:
- name: CONFIG_VALUE
valueFrom:
configMapKeyRef:
name: my-config
key: some-key
- name: SECRET_VALUE
valueFrom:
secretKeyRef:
name: my-secret
key: some-key
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
- name: CPU_LIMIT
valueFrom:
resourceFieldRef:
containerName: app
resource: limits.cpu
divisor: 1m # Expose as millicoresresourceFieldRef exposes resource limits as env vars. The divisor converts the value — 1m means millicores (e.g., 500m = 500). This lets applications self-configure based on their allocated resources.
Projected Volumes
Projected volumes combine multiple volume sources into a single mount. You can project ConfigMaps, Secrets, service account tokens, and downward API items into one directory. This simplifies volume management.
apiVersion: v1
kind: Pod
metadata:
name: projected-demo
spec:
containers:
- name: app
volumeMounts:
- name: config-volume
mountPath: /etc/config
readOnly: true
volumes:
- name: config-volume
projected:
sources:
- configMap:
name: app-config
items:
- key: config.yaml
path: config.yaml
- secret:
name: db-credentials
items:
- key: password
path: db/password
- secret:
name: api-key
items:
- key: key
path: api/key
- serviceAccountToken:
path: token
expirationSeconds: 3600
audience: api
- downwardAPI:
items:
- path: labels
fieldRef:
fieldPath: metadata.labelsProjected volumes mount multiple sources into /etc/config. The directory contains config.yaml, db/password, api/key, token, and labels. This is cleaner than multiple volume mounts.
subPath Mounts
subPath mounts a specific file or subdirectory from a volume instead of the entire volume. This is useful when you need one file from a ConfigMap without mounting the entire ConfigMap.
apiVersion: v1
kind: Pod
metadata:
name: subpath-demo
spec:
containers:
- name: app
volumeMounts:
- name: nginx-config
mountPath: /etc/nginx/nginx.conf
subPath: nginx.conf
readOnly: true
- name: app-config
mountPath: /app/config.yaml
subPath: config.yaml
readOnly: true
volumes:
- name: nginx-config
configMap:
name: nginx-config
- name: app-config
configMap:
name: app-configsubPath mounts only nginx.conf from the nginx-config ConfigMap, not all keys. The file appears at /etc/nginx/nginx.conf. The rest of the volume is not affected. Note: subPath mounts don't update automatically when the ConfigMap changes.
subPath-mounted files do NOT update when the ConfigMap changes. This is a common gotcha. If you need automatic updates, mount the entire ConfigMap and use items to control which files appear. Or use Stakater Reloader to restart pods on ConfigMap changes.
Update Propagation
ConfigMap and Secret volume updates are propagated to mounted volumes with a delay. kubelet checks for changes every 60 seconds (sync frequency). After detecting a change, it updates the volume within 60 seconds. subPath-mounted files are not updated.
# kubelet sync frequency (node config)
# --sync-frequency=1m (default)
# ConfigMap volume update flow:
# 1. kubelet detects ConfigMap change (up to 60s)
# 2. kubelet updates the volume content (atomic)
# 3. inotify event triggers in the pod
# 4. Application reads new content
# Important: subPath-mounted files are NOT updated
# Use full volume mount with items insteadVolume updates are atomic — the entire volume is replaced at once. This prevents partial updates. Applications can use inotify (fsnotify in Go) to detect changes and reload configuration.
Downward API
The Downward API exposes pod and container metadata as environment variables or files. This includes pod name, namespace, IP, labels, annotations, and resource limits. Applications can use this for self-configuration.
apiVersion: v1
kind: Pod
metadata:
name: downward-api-demo
labels:
app: demo
version: v1
spec:
containers:
- name: app
volumeMounts:
- name: downward-api
mountPath: /etc/podinfo
volumes:
- name: downward-api
projected:
sources:
- downwardAPI:
items:
- path: "labels"
fieldRef:
fieldPath: metadata.labels
- path: "annotations"
fieldRef:
fieldPath: metadata.annotations
- path: "name"
fieldRef:
fieldPath: metadata.name
- path: "namespace"
fieldRef:
fieldPath: metadata.namespace
- path: "cpu-limit"
resourceFieldRef:
containerName: app
resource: limits.cpuLabels and annotations are exposed as files in /etc/podinfo. Each file contains the key=value pairs. Applications can read these for self-configuration, logging context, or feature flags.
Projected volumes reduce the number of volume mounts. Instead of 5 separate mounts for ConfigMaps, Secrets, and tokens, use one projected volume. This simplifies pod specs and reduces mount points.
Mark this lesson complete to store local progress and unlock a cleaner resume path the next time you visit.