How do PersistentVolume, PersistentVolumeClaim, and StorageClass work together for dynamic provisioning?
Quick Answer
A StorageClass defines how to provision storage (e.g., gp3 on AWS), a PersistentVolumeClaim requests a specific size and access mode, and a PersistentVolume is the actual backing storage. With dynamic provisioning, creating a PVC triggers the StorageClass to automatically provision a matching PV through a CSI driver.
Detailed Answer
Think of renting a storage unit. The StorageClass is the catalog that lists available unit types (climate-controlled, standard, fireproof). The PersistentVolumeClaim is your rental application form where you specify how much space you need and what kind. The PersistentVolume is the actual physical storage unit assigned to you. With dynamic provisioning, you never need to pre-build units; the facility constructs one on demand the moment your application is approved.
In Kubernetes, storage decouples the lifecycle of data from the lifecycle of pods. A PersistentVolume (PV) represents a piece of storage in the cluster, whether it is an AWS EBS volume, a GCP Persistent Disk, an NFS share, or a local SSD. It has a capacity, access modes (ReadWriteOnce, ReadWriteMany, ReadOnlyMany), and a reclaim policy that determines what happens when the claim is released. A PersistentVolumeClaim (PVC) is a namespaced request that binds to a PV matching its requirements. The StorageClass is the blueprint that tells Kubernetes which CSI driver to use, what parameters to pass (volume type, IOPS, encryption), and what reclaim policy to apply.
Dynamic provisioning eliminates the need for cluster administrators to pre-create PVs manually. When a PVC references a StorageClass, the provisioner watches for unbound claims, calls the cloud API through the CSI driver to create the actual disk, then creates a PV object and binds it to the PVC. The pod mounts the PVC by name and gets access to the underlying volume. This flow means developers only need to know what size and class they want, while the platform handles the infrastructure. CSI (Container Storage Interface) is the standard plugin mechanism that connects Kubernetes to any storage backend, whether cloud-managed or on-premises.
In production, storage configuration directly impacts availability and cost. Setting the wrong reclaim policy to Delete means data is destroyed when a PVC is removed, which can be catastrophic for database volumes. Using ReadWriteOnce with a Deployment that has multiple replicas causes scheduling failures because the volume can only attach to one node. Volume binding mode WaitForFirstConsumer ensures the PV is provisioned in the same availability zone as the pod, avoiding cross-AZ attachment failures. Teams running StatefulSets for databases like PostgreSQL or Kafka typically use volumeClaimTemplates with a StorageClass that has reclaimPolicy set to Retain.
The non-obvious gotcha is that PVCs bound to a PV cannot be resized unless the StorageClass has allowVolumeExpansion set to true. Another common production issue is zone mismatch: a PV provisioned in us-east-1a cannot be mounted by a pod scheduled in us-east-1b. Teams discover this after a node failure forces pod rescheduling. Additionally, if the default StorageClass is accidentally deleted or changed, new PVCs remain Pending indefinitely with no obvious error unless you describe the PVC and check events.