Skip to main content
RunBook Academy

KubernetesLI · StorageClassesStorageClasses

StorageClass basics — provisioning templates, parameters, and binding modes

Advanced⏱ ~16 minkubectl

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

Not yet marked complete on this device.

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:

FieldMeaning
provisionerThe CSI driver (or in-tree plugin) that creates the volume.
parametersProvisioner-specific parameters (type, IOPS, etc.).
reclaimPolicyWhat happens to the volume when the PVC is deleted (Retain or Delete).
allowVolumeExpansionWhether the PVC can request more capacity.
volumeBindingModeWhen the volume is bound (Immediate or WaitForFirstConsumer).
allowedTopologiesTopology constraints for the volume.
mountOptionsMount 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
ModeWhen PV is created
ImmediateWhen the PVC is submitted (default).
WaitForFirstConsumerWhen 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

  1. 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?

  2. 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.

  3. 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.

  4. 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.
  • WaitForFirstConsumer for multi-AZ clusters. The PV follows the Pod; cross-AZ mounts are avoided.
  • Retain for stateful data. The reclaim policy matches the backup strategy.
  • allowVolumeExpansion: true for any workload that grows.
  • allowedTopologies for multi-region or constrained AZs. The PV is created in a topology that the cluster can reach.