From Static to Dynamic Provisioning
In static provisioning, a cluster administrator manually creates PersistentVolume objects ahead of time, pointing to pre-allocated disks, and PVCs simply bind to whatever matches. This does not scale: teams create PVCs constantly, and pre-guessing every size and access mode combination is wasteful. Dynamic provisioning flips the model — a PVC that references a StorageClass with a valid provisioner triggers the external-provisioner sidecar (part of the CSI driver) to call the storage backend's API and create a brand-new volume sized exactly to the request, then a matching PV object is created and bound automatically, all without an administrator touching anything.
Cricket analogy: Static provisioning is like a groundskeeper pre-preparing five practice pitches hoping they match team needs, while dynamic provisioning is like an automated pitch-rolling machine that builds a custom pitch the instant a team books practice.
The CSI Provisioning Workflow
Concretely, the flow is: a user creates a PVC referencing StorageClass 'fast-ssd'; the external-provisioner controller watching PVCs notices it's unbound and its class has a provisioner; if volumeBindingMode is WaitForFirstConsumer, it waits until the scheduler tentatively assigns a Pod to a node; then it calls the CSI driver's CreateVolume gRPC method with the StorageClass parameters and topology constraints; the storage backend allocates the disk and returns a volume handle; Kubernetes creates a PV object referencing that handle and binds it to the PVC; finally the kubelet's CSI node plugin calls NodeStageVolume and NodePublishVolume to actually attach and mount the disk into the Pod's filesystem.
Cricket analogy: This is like the sequence of a DRS review: the on-field umpire (PVC controller) refers upward, the third umpire (CSI driver) checks ball-tracking data (CreateVolume call), and only then is the final decision (PV binding) relayed back to the players.
# Watch dynamic provisioning happen live
kubectl apply -f pvc.yaml
kubectl get pvc my-claim -w
# NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS
# my-claim Pending fast-ssd
# my-claim Bound pvc-3f2a9c11-7e3d-4b1a-9c2e-1a2b3c4d5e6f 10Gi RWO fast-ssd
kubectl describe storageclass fast-ssd
kubectl logs -n kube-system -l app=ebs-csi-controller -c csi-provisioner --tail=20You can inspect exactly which provisioner handled a request by checking the PVC's events: kubectl describe pvc my-claim shows a 'ProvisioningSucceeded' event with the external provisioner's name and the volume ID it created.
- Dynamic provisioning automatically creates PVs on demand instead of requiring pre-created ones.
- The external-provisioner sidecar watches PVCs and calls the CSI driver's CreateVolume.
- WaitForFirstConsumer delays creation until the Pod is scheduled, ensuring correct topology.
- NodeStageVolume and NodePublishVolume perform the actual attach and mount on the node.
- PVC events show which provisioner and volume ID were used for troubleshooting.
- Dynamic provisioning is what makes StorageClasses genuinely useful at scale.
Practice what you learned
1. What triggers dynamic provisioning of a new volume?
2. Which CSI call is responsible for actually creating the backend storage volume?
3. Why does WaitForFirstConsumer matter for dynamic provisioning in a multi-zone cluster?
4. Where would you look first to debug why a PVC's dynamic provisioning failed?
Was this page helpful?
You May Also Like
Storage Classes
Understand how StorageClass objects define provisioners, parameters, and policies that govern how storage is dynamically created in Kubernetes.
Persistent Volumes and Claims
Learn how Kubernetes decouples storage provisioning from storage consumption using PersistentVolume and PersistentVolumeClaim objects.
Volume Snapshots
Learn how the Kubernetes VolumeSnapshot API enables point-in-time backups and cloning of PersistentVolumes via the CSI snapshot controller.