KubernetesLI · StorageClassesStorageClasses
StorageClass basics — provisioning templates, parameters, and binding modes
What you'll learn
- Describe the StorageClass structure and fields
- Explain the provisioner, parameters, and binding mode
- Identify the production pattern for StorageClass naming
- Apply the operational discipline for managing StorageClasses
Prerequisites
Verified against Kubernetes 1.34.x · kubeadm 1.34.x · kubectl 1.34.x · etcd 3.6.x · CoreDNS 1.11.x · containerd 1.7.x / 2.x · 2026-08-16
The StorageClass is the user’s pointer to a provisioning template. It defines what provisioner creates the volume, what parameters the provisioner uses, when the volume is bound, what happens to the volume when the PVC is deleted, and whether the volume can be expanded. This lesson walks each field.
The StorageClass structure
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: db-ssd
annotations:
storageclass.kubernetes.io/is-default-class: "false"
provisioner: ebs.csi.aws.com
parameters:
type: io2
iops: "10000"
throughput: "500"
fsType: ext4
reclaimPolicy: Retain
allowVolumeExpansion: true
volumeBindingMode: WaitForFirstConsumer
allowedTopologies:
- matchLabelExpressions:
- key: topology.kubernetes.io/zone
values: ["us-east-1a", "us-east-1b", "us-east-1c"]
mountOptions:
- debug
The fields:
| Field | Meaning |
|---|---|
provisioner | The CSI driver (or in-tree plugin) that creates the volume. |
parameters | Provisioner-specific parameters (type, IOPS, etc.). |
reclaimPolicy | What happens to the volume when the PVC is deleted (Retain or Delete). |
allowVolumeExpansion | Whether the PVC can request more capacity. |
volumeBindingMode | When the volume is bound (Immediate or WaitForFirstConsumer). |
allowedTopologies | Topology constraints for the volume. |
mountOptions | Mount options passed to the kubelet. |
The provisioner field
The provisioner is the CSI driver name:
provisioner: ebs.csi.aws.com
provisioner: ebs.csi.aws.com
provisioner: cephfs.csi.ceph.com
provisioner: nfs.csi.k8s.io
provisioner: csi.tigera.io # for Calico BGP-routed Pod CIDR (not for storage)
The provisioner must be a CSI driver name (or a legacy in-tree plugin name, though these are deprecated). The provisioner is implemented as a Deployment or StatefulSet in the cluster.
The parameters field
The parameters are provisioner-specific:
# AWS EBS CSI
parameters:
type: gp3
iops: "3000"
throughput: "125"
fsType: ext4
encrypted: "true"
# GCP Persistent Disk CSI
parameters:
type: pd-ssd
replication-type: regional-pd
# Ceph RBD CSI
parameters:
clusterID: <ceph-cluster-id>
pool: rbd-pool
imageFormat: "2"
imageFeatures: layering
# NFS CSI
parameters:
server: nfs.prod.example.com
path: /exports/data
The parameters are opaque to Kubernetes; the provisioner interprets them. Validation happens at the provisioner level, not at the API server.
The volumeBindingMode
volumeBindingMode: WaitForFirstConsumer
volumeBindingMode: Immediate
| Mode | When PV is created |
|---|---|
Immediate | When the PVC is submitted (default). |
WaitForFirstConsumer | When a Pod that consumes the PVC is scheduled. |
WaitForFirstConsumer is critical for multi-AZ clusters.
The PV is created in the same AZ as the Pod; cross-AZ
mounts are avoided.
sequenceDiagram
participant U as User
participant API as API server
participant S as Scheduler
participant CSI as CSI provisioner
Note over U,S: Immediate mode
U->>API: submit PVC
API->>CSI: provision volume (in any AZ)
CSI-->>API: PV created
API-->>U: PVC bound
Note over U,S: WaitForFirstConsumer mode
U->>API: submit PVC
API-->>U: PVC Pending (no Pod scheduled)
U->>API: create Pod (with PVC)
API->>S: schedule Pod
S->>API: Pod scheduled to AZ-a
API->>CSI: provision volume in AZ-a
CSI-->>API: PV created in AZ-a
API-->>U: PVC bound in AZ-a
The reclaimPolicy
reclaimPolicy: Retain
reclaimPolicy: Delete
The reclaim policy cascades to PVs provisioned from this StorageClass. See the previous lesson for details.
The allowVolumeExpansion
allowVolumeExpansion: true
When true, the user can request more capacity:
kubectl edit pvc data
# Change spec.resources.requests.storage from 100Gi to 200Gi
The CSI driver handles the expansion. Not all CSI drivers support online expansion; check the driver’s documentation.
The allowedTopologies
allowedTopologies:
- matchLabelExpressions:
- key: topology.kubernetes.io/zone
values: ["us-east-1a", "us-east-1b"]
The PV is created in a zone that matches the expression.
Combined with WaitForFirstConsumer, the PV is created
in the Pod’s zone (which must match).
Quiz
Knowledge check · 4 questions
Q1. A multi-AZ cluster uses a StorageClass with `volumeBindingMode: Immediate`. A Pod is scheduled to us-east-1b. The PV was created in us-east-1a. What happens?
Q2. The provisioner field of a StorageClass must reference a CSI driver that is running in the cluster; otherwise, PVCs on this StorageClass remain Pending.
Q3. Your team needs a new StorageClass for high-performance databases on AWS EKS. Design the StorageClass.
PostgreSQL StatefulSet on EKS. Required: high IOPS, Retain reclaim, multi-AZ awareness, volume expansion support, encryption at rest.
Q4. Explain the difference between `volumeBindingMode: Immediate` and `WaitForFirstConsumer` and when each is appropriate.
Passing score: 75%. Answers are checked in this browser.
Production discipline
- One StorageClass per workload class. Databases get one StorageClass; web apps get another; batch processing gets a third.
WaitForFirstConsumerfor multi-AZ clusters. The PV follows the Pod; cross-AZ mounts are avoided.Retainfor stateful data. The reclaim policy matches the backup strategy.allowVolumeExpansion: truefor any workload that grows.allowedTopologiesfor multi-region or constrained AZs. The PV is created in a topology that the cluster can reach.