What is a Kubernetes StorageClass, and how does a PersistentVolumeClaim that references one end up with real storage mounted into a Pod?
answer
- Class = provisioner + parameters
- Tier name, not a disk name
- PVC Pending until provisioner creates PV
- Cluster-scoped, no namespace
- provisioner/parameters effectively immutable
basics
~20 sA StorageClass is a named storage tier: a provisioner plus its parameters. When a PersistentVolumeClaim names that class, the provisioner creates real storage and a matching PersistentVolume, which is bound to the claim. No admin pre-creates the volume.
solid answer
~50 sA **StorageClass** is a cluster-scoped object describing one *tier* of storage the cluster can create on demand. Its key fields are `provisioner` (which driver does the work, e.g. `ebs.csi.aws.com`), `parameters` (driver-specific knobs such as disk type or IOPS), plus `reclaimPolicy`, `volumeBindingMode` and `allowVolumeExpansion`. The flow: a developer writes a PVC asking for a size and `storageClassName: fast-ssd`. The provisioner for that class notices an unbound PVC pointing at it, calls the storage backend to create a real disk, and creates a PersistentVolume object describing it. The control plane binds PV and PVC one-to-one. When a Pod references the PVC, kubelet attaches and mounts that volume into the container. This is **dynamic provisioning**. The alternative is static provisioning, where an administrator hand-creates PV objects in advance. StorageClasses turn storage into self-service: developers ask for a tier and a size, never for a specific disk.
code
yaml · 23 linesapiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: fast-ssd
provisioner: ebs.csi.aws.com
parameters:
type: gp3
iops: "6000"
encrypted: "true"
reclaimPolicy: Delete
allowVolumeExpansion: true
volumeBindingMode: WaitForFirstConsumer
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: data
spec:
storageClassName: fast-ssd
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 20Gigo deeper
Be able to say: class = provisioner + parameters, PVC names a class, PV is created automatically and mounted by the Pod. Show a two-file example.
Add the field list — reclaimPolicy, volumeBindingMode, allowVolumeExpansion — and describe the provisioner watch/CreateVolume/bind sequence, plus what Pending means.
Talk about class names as a portable contract, immutability of provisioner and parameters, driver-specific parameter validation happening only at provision time, and how you smoke-test a new class.
Frame classes as the storage policy surface for the platform: how many tiers to expose, naming that survives a cloud migration, and who owns changing them.
## The problem it solves Without StorageClasses, persistent storage is a manual handshake. An administrator provisions a disk in the infrastructure (a cloud block device, an NFS export, a SAN LUN), writes a PersistentVolume (PV) object describing it, and only then can a developer's PersistentVolumeClaim (PVC) find and bind to it. That is *static provisioning*: it does not scale, because every new application waits on a human. A StorageClass replaces the human with a controller. It is a cluster-scoped API object (no namespace) that names a *class* of storage the cluster knows how to manufacture. Developers stop naming disks and start naming tiers: "give me 20Gi of `fast-ssd`". ## Anatomy of a StorageClass - `provisioner` — the identity of the component that creates volumes for this class. Today this is normally a CSI driver name such as `ebs.csi.aws.com`, `pd.csi.storage.gke.io`, `disk.csi.azure.com` or `rook-ceph.rbd.csi.ceph.com`. The special value `kubernetes.io/no-provisioner` means "nothing provisions for this class" and is used for statically created local volumes. - `parameters` — an opaque string map passed to that driver. The keys are defined by the driver, not by Kubernetes: `type: gp3`, `iops: "6000"`, `fsType: ext4`, `encrypted: "true"`. Kubernetes does not validate them; a typo surfaces later as a provisioning error event on the PVC. - `reclaimPolicy` — what happens to the created PV when its claim is deleted. Defaults to `Delete`; `Retain` keeps the volume and its data. - `volumeBindingMode` — `Immediate` (bind and provision as soon as the PVC exists) or `WaitForFirstConsumer` (wait until a Pod using it is scheduled, so the volume lands in the right topology). - `allowVolumeExpansion` — whether a bound PVC of this class may later request more space. - `mountOptions` and `allowedTopologies` — mount flags applied to created PVs, and a restriction on which zones/nodes the class may provision into. ## What actually happens on `kubectl apply` of a PVC 1. The PVC is created with `spec.storageClassName: fast-ssd`, an access mode and `resources.requests.storage`. 2. If no existing PV matches, the PVC stays `Pending`. 3. The external provisioner sidecar for the class watches unbound PVCs whose class points at its driver name. It calls `CreateVolume` on the driver. 4. The driver creates the real disk in the backend and returns its identifier and capacity. 5. The provisioner creates a PV object with `spec.storageClassName: fast-ssd`, a `claimRef` pointing back at the PVC, and the driver's volume handle. 6. Binding controller marks both `Bound`. The PVC's `spec.volumeName` now names the PV. 7. When a Pod mounting that PVC is scheduled, the attach/detach controller attaches the device to the node and kubelet formats (if needed) and mounts it into the container path. Capacity semantics matter here: the PVC *request* is a minimum. A backend that only sells 10Gi increments may return more, and the PV records the real capacity. ## Class names are the contract The class name is what application manifests hardcode, so treat it as an API. `standard`, `fast-ssd`, `retain-db` are portable names you can point at different provisioners in different clusters; a name like `gp3-encrypted-us-east-1a` leaks provider detail into every chart. Most fields of an existing StorageClass — notably `provisioner`, `parameters` and `reclaimPolicy` — are effectively immutable: you cannot re-tune a class in place. The normal workflow is to create a new class and migrate workloads to it. Editing an existing PV's reclaim policy is still possible and is a common one-off rescue. ## Where it sits relative to the rest of storage StorageClass is the *policy* layer: it says what kind of volume to make and under which rules. The PV is the *resource*, the PVC is the *request*, and the CSI driver is the *mechanism*. A cluster can have many classes at once, including one flagged as the default so PVCs that name no class still work. A useful mental check for interviews: if you can delete every PV in the cluster and a redeployed application still comes up with fresh storage, you have dynamic provisioning working. If it comes up `Pending` forever, someone was relying on hand-made PVs.
- What happens if a PVC names a StorageClass that does not exist in the cluster?The PVC is accepted by the API server but stays Pending forever, because no provisioner claims it and no pre-created PV carries that class name. `kubectl describe pvc` shows a `ProvisioningFailed` or simply no provisioning events. Any Pod mounting it stays Pending too, with a FailedScheduling event about an unbound claim.
- Who validates the values in a StorageClass `parameters` map?Only the driver, at provisioning time. Kubernetes treats parameters as an opaque string map and will happily accept nonsense keys or values. The failure surfaces asynchronously as a ProvisioningFailed event on the first PVC that uses the class, which is why a new class should always be smoke-tested with a throwaway PVC.
A StorageClass is a menu item, not a plate of food. The PVC is the order ("one fast-ssd, 20Gi"); the provisioner is the kitchen that makes it to order; the PV is the plate that comes back.
saying these in an interview costs you the question
- Saying a StorageClass is namespaced or must exist in each namespace
- Thinking the StorageClass itself holds the data or capacity
- Believing the PVC gets exactly the requested size (it is a minimum)
- Assuming you can edit provisioner or parameters on an existing class in place
- Confusing StorageClass with the PV: the class is policy, the PV is the resource