What is a StorageClass, and how does dynamic provisioning work?
Quick Answer
A StorageClass defines a category of storage a cluster can provision on demand. It names a specific provisioner (e.g., the AWS EBS CSI driver) and parameters (disk type, IOPS, filesystem type) describing how to create matching storage. When a PersistentVolumeClaim references a StorageClass and no existing PersistentVolume already satisfies it, the StorageClass's provisioner automatically creates both a new PersistentVolume object and the real underlying storage resource, actually calling the cloud provider's API to create a disk. This eliminates the need for an administrator to manually pre-provision storage ahead of time.
Detailed Answer
Defining a StorageClass
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: fast-ssd
provisioner: ebs.csi.aws.com # which CSI driver actually creates the storage
parameters:
type: gp3
iopsPerGB: "50"
reclaimPolicy: Delete # what happens to the PV when its PVC is deleted
volumeBindingMode: WaitForFirstConsumer
Requesting storage from it
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: database-pvc
spec:
storageClassName: fast-ssd # references the StorageClass above
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 100Gi
What happens when this PVC is created
- The PVC controller checks for an existing, unbound PV matching the request. If none exists (the common case with dynamic provisioning, since PVs aren't pre-created), it proceeds to provisioning.
- The
fast-ssdStorageClass's provisioner (ebs.csi.aws.com, a CSI — Container Storage Interface — driver) gets invoked, and calls the actual cloud provider API to create a real 100Gigp3EBS volume. - A new PersistentVolume object is automatically created, representing this newly-created real disk.
- The PVC binds to this new PV — the whole process happens automatically, with no administrator needing to have anticipated this specific request ahead of time.
The Container Storage Interface (CSI) — another standard plugin interface
Similar in spirit to CRI (for container runtimes) and CNI (for networking), CSI standardizes how Kubernetes talks to storage systems, so any storage vendor can write a CSI driver Kubernetes can use without storage-vendor-specific code baked into Kubernetes core. This lets the same StorageClass mechanism work uniformly whether the underlying provisioner is AWS EBS, GCP Persistent Disk, Azure Disk, or an on-prem storage system's CSI driver.
volumeBindingMode — an important, easy-to-miss setting
WaitForFirstConsumer (increasingly the recommended default) delays actually provisioning the volume until a Pod that will use the PVC is scheduled. This matters because the volume might have topology constraints — an EBS volume can only be attached to a node in the same availability zone it was created in — and provisioning it before knowing which node/zone the Pod will run in could create a volume in the wrong zone entirely, making the Pod unschedulable. The older default, Immediate, provisions the volume as soon as the PVC is created, without waiting to see where the consuming Pod lands. That's a real source of "PVC bound to a volume in the wrong availability zone" issues if not configured carefully.
Default StorageClass
A cluster can designate one StorageClass as the default, via an annotation, used automatically for any PVC that doesn't explicitly specify storageClassName. Worth knowing when a PVC's storage behavior seems to "just work" without an explicit StorageClass reference — it's still using one, just implicitly.
Cluster operators typically define a small number of StorageClasses representing meaningful tiers — fast-ssd for databases needing high IOPS, standard for general-purpose storage, cold-archive for infrequently accessed data — and application teams simply reference the appropriate one by name in their PVCs. This keeps the "what kind of storage, from which provider, with which performance characteristics" decision centralized and consistent across the cluster.