Kubernetes Persistent Volumes
Dynamic provisioning with CSI drivers.
Persistent Storage in Kubernetes
Kubernetes pods are ephemeral — when a pod dies, its local storage is lost. For stateful workloads like databases, file uploads, and caches, you need Persistent Volumes (PVs) that survive pod restarts and rescheduling. Understanding the PV subsystem is critical for running production stateful applications.
Storage Architecture
- PersistentVolume (PV) — A piece of storage provisioned by an admin or dynamically by a StorageClass
- PersistentVolumeClaim (PVC) — A request for storage by a pod. PVCs bind to PVs that satisfy their requirements.
- StorageClass — Defines how storage is dynamically provisioned (e.g., EBS gp3, EFS, local SSD)
Dynamic Provisioning with StorageClass
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: fast-ssd
provisioner: ebs.csi.aws.com
parameters:
type: gp3
iops: "5000"
throughput: "250"
encrypted: "true"
reclaimPolicy: Retain
volumeBindingMode: WaitForFirstConsumer
allowVolumeExpansion: truePersistentVolumeClaim
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: postgres-data
spec:
accessModes:
- ReadWriteOnce
storageClassName: fast-ssd
resources:
requests:
storage: 100GiUsing PVCs in Pods
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: postgres
spec:
serviceName: postgres
replicas: 1
template:
spec:
containers:
- name: postgres
image: postgres:15
volumeMounts:
- name: data
mountPath: /var/lib/postgresql/data
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: fast-ssd
resources:
requests:
storage: 100GiStatefulSets automatically create a unique PVC for each replica, ensuring data isolation between database instances.
Access Modes
| Mode | Abbreviation | Use Case |
|---|---|---|
| ReadWriteOnce | RWO | Single pod read/write (databases) |
| ReadOnlyMany | ROX | Multiple pods read-only (shared config) |
| ReadWriteMany | RWX | Multiple pods read/write (shared files) |
AWS Storage Options
- EBS (gp3) — Block storage, RWO only, ideal for databases. 20% cheaper than gp2 with better baseline performance.
- EFS — NFS-based, supports RWX, ideal for shared file systems. Higher latency than EBS but supports multi-AZ access.
- FSx for Lustre — High-performance parallel file system for ML and HPC workloads.
Volume Expansion
If your StorageClass has allowVolumeExpansion: true, you can resize PVCs:
# Edit the PVC to increase size
kubectl patch pvc postgres-data -p '{"spec":{"resources":{"requests":{"storage":"200Gi"}}}}'
# For file-system based volumes, the pod may need a restart
kubectl delete pod postgres-0 # StatefulSet will recreate it with expanded volumeBackup Strategies
- Volume snapshots — Use VolumeSnapshot CRDs for point-in-time backups
- Application-level backup — pg_dump, mongodump before snapshotting
- Velero — Cluster-wide backup including PVs, ideal for disaster recovery
Reclaim Policies
- Retain — PV persists after PVC deletion (recommended for production)
- Delete — PV and underlying storage are deleted with PVC (use for ephemeral environments)
Eazy SaaS Tip: We configure all production StorageClasses with
reclaimPolicy: Retainand automated VolumeSnapshot schedules. This ensures that even if a PVC is accidentally deleted, the data remains recoverable. We've saved clients from data loss multiple times with this approach.