Kubernetes volumes cheatsheet.
Volume types
- emptyDir: ephemeral, deleted with pod.
- hostPath: bind mount from node (avoid in multi-node).
- configMap / secret: inject configs.
- persistentVolumeClaim (PVC): durable storage.
- csi: CSI driver-backed (cloud disks, NFS, etc).
emptyDir
spec:
containers:
- name: app
volumeMounts:
- { name: cache, mountPath: /cache }
volumes:
- name: cache
emptyDir:
sizeLimit: 1Gi
medium: Memory # tmpfs
Per-pod scratch. Shared between containers in same pod.
PVC + PV
apiVersion: v1
kind: PersistentVolumeClaim
metadata: { name: data }
spec:
accessModes: [ReadWriteOnce]
resources:
requests: { storage: 10Gi }
storageClassName: gp3
Use in pod:
spec:
containers:
- name: db
volumeMounts: [{ name: data, mountPath: /var/lib/data }]
volumes:
- name: data
persistentVolumeClaim: { claimName: data }
Access modes
ReadWriteOnce(RWO): one node.ReadOnlyMany(ROX): many nodes read-only.ReadWriteMany(RWX): many nodes read-write (needs NFS / EFS / Filestore).ReadWriteOncePod(RWOP): single pod.
Most cloud disks are RWO. For sharing across pods, use object storage or NFS.
StorageClass
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata: { name: gp3 }
provisioner: ebs.csi.aws.com
parameters:
type: gp3
throughput: "125"
iops: "3000"
volumeBindingMode: WaitForFirstConsumer
reclaimPolicy: Delete
allowVolumeExpansion: true
WaitForFirstConsumer delays binding until pod is scheduled (zone-aware).
Default StorageClass
kubectl patch storageclass gp3 \
-p '{"metadata":{"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'
PVCs without storageClassName use the default.
Static PV (pre-provisioned)
apiVersion: v1
kind: PersistentVolume
metadata: { name: nfs-pv }
spec:
capacity: { storage: 50Gi }
accessModes: [ReadWriteMany]
nfs:
server: nfs.example.com
path: /exports/data
persistentVolumeReclaimPolicy: Retain
Then bind a PVC. Usually you don’t need this — dynamic provisioning is preferred.
Resize PVC
spec:
resources:
requests: { storage: 20Gi } # increase from 10Gi
Requires allowVolumeExpansion: true in StorageClass.
kubectl edit pvc data
# Save, then pod may need restart to see new size
Snapshot + restore
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshot
metadata: { name: snap-1 }
spec:
volumeSnapshotClassName: csi-snapclass
source:
persistentVolumeClaimName: data
Restore:
apiVersion: v1
kind: PersistentVolumeClaim
metadata: { name: restored }
spec:
storageClassName: gp3
dataSource:
name: snap-1
kind: VolumeSnapshot
apiGroup: snapshot.storage.k8s.io
resources:
requests: { storage: 10Gi }
accessModes: [ReadWriteOnce]
StatefulSet volume
spec:
volumeClaimTemplates:
- metadata: { name: data }
spec:
accessModes: [ReadWriteOnce]
resources: { requests: { storage: 10Gi } }
Creates one PVC per replica (web-0, web-1…).
Volumes with CSI
Most modern storage uses CSI. Examples:
- AWS EBS:
ebs.csi.aws.com - GCP PD:
pd.csi.storage.gke.io - Azure Disk:
disk.csi.azure.com - Longhorn (self-hosted):
driver.longhorn.io - Rook/Ceph:
rook-ceph.rbd.csi.ceph.com
Local PV
apiVersion: v1
kind: PersistentVolume
metadata: { name: local-pv }
spec:
capacity: { storage: 100Gi }
accessModes: [ReadWriteOnce]
storageClassName: local-storage
local: { path: /mnt/disks/ssd1 }
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- { key: kubernetes.io/hostname, operator: In, values: [node-1] }
Pod stuck on specific node. High-perf use case.
hostPath (avoid)
volumes:
- name: data
hostPath:
path: /var/data
type: Directory
Pod stuck on the node; data lost if node lost. Acceptable for cluster-level tools (logs, metrics agents).
projected volumes
volumes:
- name: combined
projected:
sources:
- configMap: { name: app-config }
- secret: { name: app-secrets }
- downwardAPI:
items:
- { path: "namespace", fieldRef: { fieldPath: metadata.namespace } }
Single mount with multiple sources.
Common mistakes
- RWO PVC + multiple replicas — only one pod schedules.
- Default StorageClass deletes volume on PVC delete (
reclaimPolicy: Delete). - Cross-AZ PVC + pod scheduled to wrong zone — use
WaitForFirstConsumer. - Resizing PVC < current size — invalid.
- StatefulSet PVCs leak after delete — manual cleanup needed.
Read this next
If you want my storage templates (EBS, NFS, Longhorn), they’re at rajpoot.dev .
Building something AI-, backend-, or data-heavy and want a second pair of eyes? I do consulting and freelance work — see my projects and ways to reach me at rajpoot.dev .