Data written inside a container is lost when the container/pod is recreated. A volume gives the pod storage that every container in the pod can share. Declare it in spec.volumes and mount it into containers with volumeMounts — the name must match on both sides.
spec:
containers:
- name: html-generator
image: busybox:1.36
command: ["sh", "-c", "while true; do date > /html/index.html; sleep 10; done"]
volumeMounts: [{ name: html, mountPath: /html }]
- name: web
image: nginx:1.27
volumeMounts: [{ name: html, mountPath: /usr/share/nginx/html, readOnly: true }]
volumes:
- name: html
emptyDir: {}
flowchart LR
G["container html-generator"] --> V[("emptyDir html")]
V --> N["container nginx"]
| Type | Behaviour |
|---|---|
emptyDir |
An empty directory created when the pod is assigned to a node, gone when the pod is deleted. Good for sharing files between containers in a pod or a temporary cache |
hostPath |
Mounts a file/directory of the node. Survives pod deletion but only on that node; a pod moving to another node "loses" the data; risky because the pod touches the host filesystem |
configMap, secret, downwardAPI |
Provide configuration/pod information as files |
persistentVolumeClaim |
Durable storage independent of the pod (next lesson) |
| NFS, CSI (EBS, Azure Disk, EFS…) | Network or block storage through a driver |
Note: gitRepo is deprecated (use an init container running git clone into an emptyDir); in-tree plugins such as awsElasticBlockStore and azureDisk have moved to CSI drivers.
| Command | Meaning |
|---|---|
kubectl explain pod.spec.volumes.emptyDir |
The fields of emptyDir |
kubectl port-forward pod/fortune 8080:80 -n dev |
Try an nginx pod on localhost:8080 |
emptyDir options
emptyDir normally uses the node's disk. medium: Memory puts it in RAM (tmpfs) for very fast scratch space, and that memory counts against the container's limit. sizeLimit: 500Mi caps it; a pod that writes more is evicted. emptyDir survives container restarts inside the pod, only the pod's deletion removes it.
Projected and downward API volumes
A projected volume combines several sources into one directory: a ConfigMap, a Secret, downward API fields, and a short-lived ServiceAccount token. The downward API exposes the pod's own information without calling the API:
env:
- name: POD_NAME
valueFrom: { fieldRef: { fieldPath: metadata.name } }
- name: MEM_LIMIT
valueFrom: { resourceFieldRef: { containerName: app, resource: limits.memory } }
Apps use this to include the pod name in logs or to size caches from the memory limit.
subPath
subPath: nginx.conf mounts a single file from a volume instead of hiding the whole target directory, so other files the image ships in that directory stay visible. The catch: subPath mounts do not receive ConfigMap updates.
Ephemeral volumes from storage classes
A generic ephemeral volume declares a PVC template inside the pod; Kubernetes creates a real disk from a StorageClass when the pod starts and deletes it with the pod. It suits large scratch space that is bigger than the node's local disk.
hostPath with care
When a hostPath is unavoidable (log agents reading /var/log), mount it read-only, use the narrowest path, and set type: Directory so the pod fails instead of creating a random directory. Pod Security's baseline and restricted levels block hostPath for ordinary apps, which is the right default.
Where CSI fits
The Container Storage Interface lets storage vendors ship drivers outside Kubernetes itself. Each driver runs a controller (create, attach, snapshot) and a node DaemonSet (mount on each node). Next lessons show how PVCs and StorageClasses use these drivers.