Storage Overview¶
Container filesystems are ephemeral. For durable data, Kubernetes provides persistent storage primitives.
Ephemeral vs Persistent Storage¶
Ephemeral options:
emptyDir: temporary storage tied to pod lifetime.hostPath: host-node path mount (use sparingly, mainly for node-level agents).
Persistent options:
- PersistentVolume (PV)
- PersistentVolumeClaim (PVC)
- StorageClass
PV, PVC, and StorageClass¶
| Object | Purpose | Typical owner |
|---|---|---|
| PV | Actual storage resource | Platform automation or admin |
| PVC | Workload storage request | App team |
| StorageClass | Provisioning policy | Platform team |
The indirection exists for the same reason Services sit in front of pods: decoupling. The app team asks for "20Gi, single-writer" without knowing whether it comes from EBS, Ceph, or NFS. The platform team can change the backend without touching a single workload manifest.
How a volume reaches your pod¶
Dynamic provisioning is a chain of controllers, and each link is a distinct failure point:
sequenceDiagram
participant U as User
participant PVC as PVC (Pending)
participant CSI as CSI provisioner
participant S as Scheduler
participant K as kubelet
U->>PVC: create PVC (class: gp3-encrypted)
Note over PVC,S: WaitForFirstConsumer: nothing happens<br/>until a pod uses the PVC
U->>S: create pod referencing PVC
S->>S: pick node (zone-aware)
S->>CSI: trigger provisioning for that topology
CSI->>CSI: create backing volume, create PV
CSI->>PVC: bind PVC ↔ PV (1:1, exclusive)
K->>K: attach volume to node, mount into pod
A PVC and PV bind one-to-one and exclusively -- once bound, the pairing holds until the PVC is deleted. When a PVC is deleted, the PV moves to Released and its reclaim policy decides what happens: Delete removes the backing volume; Retain keeps the PV (and data) but it will not rebind automatically -- an admin must clean it and remove the old claimRef first. A Released PV that "won't bind" to a new PVC is expected behavior, not a bug.
PVC Example¶
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: db-data
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 20Gi
storageClassName: standard
Access Modes¶
ReadWriteOnce(RWO): mounted read-write by one node at a time. Multiple pods on the same node can all mount it.ReadWriteOncePod(RWOP): mounted read-write by exactly one pod. Stricter than RWO. Added in Kubernetes 1.22 for single-writer guarantees at the pod level.ReadWriteMany(RWX): mounted read-write by many nodes simultaneously. Requires a compatible backend (NFS, CephFS, cloud file shares).ReadOnlyMany(ROX): mounted read-only by many nodes.
StorageClass Example (CSI)¶
Prefer CSI drivers and dynamic provisioning.
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: gp3-encrypted
provisioner: ebs.csi.aws.com
parameters:
type: gp3
encrypted: "true"
allowVolumeExpansion: true
reclaimPolicy: Delete
volumeBindingMode: WaitForFirstConsumer
Note: provisioner is environment-specific. Use the CSI driver for your platform.
volumeBindingMode: WaitForFirstConsumer delays PV provisioning until a pod using the PVC is scheduled. This ensures the volume is created in the same availability zone as the pod. Use this mode for zonal storage backends (most cloud block storage). The default Immediate mode provisions the volume when the PVC is created, which can cause zone mismatches.
Reclaim Policy¶
Delete: deleting PVC removes backing storage.Retain: backing volume remains for manual recovery.
For critical stateful workloads, Retain can reduce accidental data loss risk.
Mounting a PVC in a Pod¶
apiVersion: v1
kind: Pod
metadata:
name: app
spec:
volumes:
- name: app-storage
persistentVolumeClaim:
claimName: db-data
containers:
- name: app
image: nginx:1.27
volumeMounts:
- name: app-storage
mountPath: /data
Volume Snapshots¶
CSI-backed storage supports point-in-time volume snapshots via the VolumeSnapshot API (requires the external-snapshotter controller):
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshot
metadata:
name: db-snapshot-2026-05-03
spec:
volumeSnapshotClassName: csi-snapclass
source:
persistentVolumeClaimName: db-data
Restore by creating a new PVC with dataSource pointing to the snapshot. Snapshots are much faster than full backup/restore for large volumes and are useful for pre-upgrade checkpoints.
Operational Checks¶
If PVC remains Pending, validate storage class name, CSI driver health, and topology constraints (WaitForFirstConsumer PVCs stay Pending until a pod is scheduled).
Certification notes¶
- CKA storage tasks are usually: create a StorageClass/PV/PVC chain, mount it in a pod, and diagnose a
PendingPVC. Know thatPending+WaitForFirstConsumeris normal until a pod schedules. - Access modes are enforced at attach time, per node -- RWO does not mean "one pod."
- Remember reclaim policy behavior for
RetainvsDelete; the released-PV-won't-rebind case appears in scenarios.