A container's own filesystem is disposable
Everything a container writes to its image filesystem lives in its writable layer (11.22), and that layer is thrown away when the container restarts - not only when the pod is deleted. A crash-looping database that writes to /var/lib/data without a volume starts empty on every restart. Volumes are how data outlives a container; the volume's type decides for how long.
What you need to know already: mounts (4.18), Docker volumes, bind mounts and tmpfs (11.22), pods, restarts and CrashLoopBackOff (15.14), sidecars (15.35), ConfigMap and Secret volumes (15.29, 15.33), kubectl debug node (16.3), memory limits and cgroups (5.11).
Declaring a volume
A volume in Kubernetes is storage attached to a pod. It takes two parts in the pod spec: volumes: (what the storage is, with a name) and, in each container, volumeMounts: (where that named volume appears in the container's filesystem, like docker run -v):
spec:
containers:
- name: app
volumeMounts:
- {name: cache, mountPath: /cache}
- {name: node, mountPath: /node}
- {name: data, mountPath: /data}
volumes:
- name: cache
emptyDir: {} # sizeLimit: 1Gi, medium: Memory
- name: node
hostPath: {path: /var/lib/lab-notes, type: DirectoryOrCreate}
- name: data
persistentVolumeClaim: {claimName: notes}
The three types used here, and how long their data lives:
volume lives as long as survives container survives pod follows the pod
restart deletion to another node
container layer the container no no no
emptyDir the POD (on its node) yes no no
hostPath the node's disk yes yes* no - it is THAT node's dir
PVC (network) the PersistentVolume yes yes yes (within its topology)
configMap/secret the object (read-only) yes yes yes
* only if the next pod lands on the same node. "Topology" = where the storage can be reached from, for example one zone (16.41).
emptyDir
An emptyDir is created empty when the pod starts on a node, and deleted with the pod. All containers of the pod can mount it - the standard way for a sidecar and the app to exchange files, and for scratch space, caches and unpacked files.
medium: Memorymakes it a tmpfs (11.22): fast, but it counts against the container's memory limit.sizeLimitcaps its size; exceed it and the pod is evicted (the kubelet stops it and removes it from the node).
hostPath - and why it is a security hole
A hostPath volume mounts a directory of the node into the pod - a bind mount (11.22) from the node. Legitimate users are node agents: log shippers reading /var/log, network and storage plugins, the kube-proxy DaemonSet. For applications it is wrong twice:
- Scheduling: the data is on one node. Reschedule the pod elsewhere and it sees a different (usually empty) directory. Nothing warns you.
- Security: a pod that can mount
/of the node owns the node. It can read/etc/kubernetes/pki(the cluster's private keys), the kubelet's credentials, every other pod's secrets on disk, write a pod manifest the kubelet will run, or control the container runtime through/run/containerd/containerd.sock(like the Docker socket of 11.29).kubectl debug node/is exactly that pod - which is why it is an admin tool.
Later (Ch 17): Pod Security Standards - the "baseline" profile forbids hostPath entirely.
configMap, secret, projected
Read-only views of API objects (15.29, 15.33): files that update when the object changes (except when mounted with subPath, a single file). A projected volume merges several sources (the pod's ServiceAccount token, a ConfigMap, a Secret) into one directory.
persistentVolumeClaim
The pod does not name a disk. It names a claim - a PersistentVolumeClaim (PVC): "I need 10Gi, read-write, of class lab-disk". The cluster binds that claim to a PersistentVolume (PV), an actual piece of storage (a cloud disk, a network file share, a storage-cluster volume). The data lives on the volume, which exists independently of any pod:
# writer/reader: two pods sharing the claim above (the volumes mission)
k exec -n data writer -- sh -c 'echo hello > /data/f.txt'
k delete pod writer -n data --grace-period=0 --force
k apply -f reader.yaml # a new pod, same claim
k exec -n data reader -- cat /data/f.txt
hello
sh -c '...' runs a small shell command inside the container. --grace-period=0 --force deletes the pod immediately, without the usual shutdown wait. The new pod using the same claim still finds the file.
The rest of this part is about that indirection: who creates volumes (16.39), who may mount them where (16.41), and what happens when the claim goes away (16.44).
What you can now do:
- pick emptyDir, hostPath or a PVC by how long the data must live
- explain why hostPath is dangerous for applications
- mount a claim into a pod and show the data outlives the pod