Skip to main content
RunBook Academy

KubernetesXLIX · VolumesVolumes

Volume mounts — how Pods consume volumes, subPaths, and projections

Advanced⏱ ~16 minkubectl

What you'll learn

  • Describe how a Pod's volumes and volumeMounts are connected
  • Use subPath to mount a subdirectory of a volume
  • Distinguish the four projected volume sources
  • Apply the production pattern for volume mounts in multi-container Pods

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

Not yet marked complete on this device.

The Pod’s volumes declare what is mounted; the volumeMounts declare where and how. This lesson walks the Pod-level volume declaration, the subPath option, and the projected volume sources (ConfigMap, Secret, downwardAPI, serviceAccountToken).

Volumes and volumeMounts

A Pod declares two things for each mounted volume:

  1. volumes: the source (PVC, emptyDir, hostPath, etc.).
  2. volumeMounts: where to mount the source in each container.
apiVersion: v1
kind: Pod
metadata:
  name: app
spec:
  containers:
  - name: app
    image: app:v1
    volumeMounts:
    - name: data
      mountPath: /var/lib/app
    - name: scratch
      mountPath: /tmp
  volumes:
  - name: data
    persistentVolumeClaim:
      claimName: data
  - name: scratch
    emptyDir: {}

The Pod has two volumes: data (a PVC) and scratch (an emptyDir). The app container mounts both: /var/lib/app is the persistent data; /tmp is the scratch.

subPath

The subPath option mounts a subdirectory of a volume into a container, instead of mounting the entire volume:

volumeMounts:
- name: data
  mountPath: /var/lib/app/data
  subPath: app-data
- name: data
  mountPath: /var/lib/app/logs
  subPath: app-logs

The container sees /var/lib/app/data and /var/lib/app/logs, both backed by different subdirectories of the same PVC. Without subPath, mounting the PVC at two paths would result in one directory hiding the other.

The subPathExpr variant allows templated paths:

volumeMounts:
- name: data
  mountPath: /var/lib/app/config
  subPathExpr: $(POD_NAME)-config

subPathExpr evaluates the expression at mount time. It is useful for mounting Pod-specific data on a shared volume.

Projected volumes

A projected volume combines multiple sources into a single mount. The four projected sources:

  • configMap: a ConfigMap as files.
  • secret: a Secret as files.
  • downwardAPI: Pod metadata as files.
  • serviceAccountToken: a token for the ServiceAccount.
volumes:
- name: projected
  projected:
    sources:
    - configMap:
        name: app-config
    - secret:
        name: app-credentials
    - downwardAPI:
        items:
        - path: pod-name
          fieldRef:
            fieldPath: metadata.name
        - path: pod-namespace
          fieldRef:
            fieldPath: metadata.namespace
    - serviceAccountToken:
        path: token
        audience: api
        expirationSeconds: 3600

The Pod’s containers see all four sources as files under a single mount path. This is the standard pattern for mounting configuration and secrets.

ConfigMap as volume

volumes:
- name: config
  configMap:
    name: app-config
    items:
    - key: app.conf
      path: app.conf
    - key: log.conf
      path: log.conf

The ConfigMap’s keys become files at the mount path. The items field allows renaming or selecting specific keys.

When the ConfigMap is updated, the kubelet updates the mount within a few seconds (the --sync-frequency/--config-sync-frequency interval). For application consumption, the application must either poll for changes or use a config-reload mechanism.

Secret as volume

volumes:
- name: secrets
  secret:
    secretName: app-credentials
    defaultMode: 0400

The Secret’s keys become files at the mount path. The defaultMode sets the file permissions (octal). For sensitive Secrets, use 0400 (read-only by owner).

Secret volumes are stored in tmpfs (RAM), not on disk. The kubelet mounts them as tmpfs volumes; the files are in memory and never touch disk.

Multi-container volume sharing

Multi-container Pods share volumes via the same mount mechanism:

containers:
- name: app
  volumeMounts:
  - name: data
    mountPath: /output
- name: sidecar
  volumeMounts:
  - name: data
    mountPath: /input
volumes:
- name: data
  emptyDir: {}

The app writes to /output; the sidecar reads from /input. Both see the same emptyDir because they share the Pod’s mount namespace.

Quiz

Knowledge check · 4 questions

  1. Q1. A Pod mounts the same PVC at two different `mountPath` values. Without `subPath`, what happens?

  2. Q2. Secret volumes are mounted on the node's filesystem, exposing them to anyone with shell on the node.

  3. Q3. Your team designs a Pod with a main application container and a sidecar that reads the application's log files. Walk through the volume design.

    App container writes to /var/log/app/. Sidecar forwards log lines to a central aggregator. The Pod must survive container restarts without losing the log files in flight.

  4. Q4. Explain the difference between a regular volume mount and a projected volume mount, and when each is appropriate.

Passing score: 75%. Answers are checked in this browser.

Production discipline

  • Every volume in volumes is mounted by at least one container. An unused volume is dead weight.
  • subPath hides updates. For ConfigMap and Secret updates, mount the full volume or use environment variables.
  • Secret volumes are tmpfs-mounted. The data is in memory, not on disk.
  • Projected volumes for configuration. ConfigMap, Secret, downwardAPI, serviceAccountToken — combined into one mount.
  • Multi-container Pods share volumes via the same mount. The containers share the Pod’s mount namespace.