StorageClasses & Dynamic Provisioning

StorageClasses enable dynamic provisioning of persistent storage in Kubernetes. Instead of administrators manually creating PersistentVolumes, StorageClasses allow Kubernetes to automatically provision storage when you create a PersistentVolumeClaim. Think of StorageClasses as templates that define how to create storage—you specify the template, and Kubernetes handles the rest.

What is a StorageClass?

A StorageClass is a Kubernetes resource that describes a “class” of storage. It defines:

  • Provisioner - The plugin that creates the storage (e.g., AWS EBS, GCE Persistent Disk)
  • Parameters - Configuration specific to the provisioner (e.g., disk type, zone)
  • Reclaim Policy - What happens when the PVC is deleted (Delete or Retain)
  • Binding Mode - When the volume binding occurs (Immediate or WaitForFirstConsumer)
graph TB A[StorageClass] --> B[Provisioner Plugin] A --> C[Parameters] A --> D[Reclaim Policy] A --> E[Binding Mode] B --> F[AWS EBS<br/>GCE PD<br/>Azure Disk<br/>NFS<br/>CSI Driver] C --> G[Disk Type<br/>Zone<br/>IOPS<br/>Encryption] D --> H[Delete<br/>Retain] E --> I[Immediate<br/>WaitForFirstConsumer] style A fill:#e1f5ff style F fill:#fff4e1 style G fill:#e8f5e9 style H fill:#f3e5f5 style I fill:#ffe1e1

Static vs Dynamic Provisioning

Static Provisioning (Without StorageClass)

Administrators manually create PersistentVolumes, and users create PVCs that bind to these pre-created PVs.

graph LR A[Admin creates PV] --> B[User creates PVC] B --> C[Kubernetes binds PVC to PV] style A fill:#e1f5ff style B fill:#fff4e1 style C fill:#e8f5e9

Limitations:

  • Requires manual PV creation
  • Need to know storage details upfront
  • Doesn’t scale well

Dynamic Provisioning (With StorageClass)

Users create PVCs that reference a StorageClass, and Kubernetes automatically creates the PV.

graph LR A[User creates PVC with StorageClass] --> B[Kubernetes provisions PV] B --> C[PV bound to PVC] style A fill:#e1f5ff style B fill:#e8f5e9 style C fill:#fff4e1

Benefits:

  • No manual PV creation needed
  • Automatic provisioning
  • Scales easily
  • Simpler workflow

How Dynamic Provisioning Works

Here’s the complete flow of dynamic provisioning:

sequenceDiagram participant User participant K8s as Kubernetes API participant SC as StorageClass participant Prov as Provisioner participant Storage as Storage System User->>K8s: Create PVC with storageClassName K8s->>SC: Lookup StorageClass SC->>K8s: Return provisioner and parameters K8s->>Prov: Provision volume (with parameters) Prov->>Storage: Create storage volume Storage->>Prov: Volume created (volume ID) Prov->>K8s: Create PV with volume ID K8s->>K8s: Bind PV to PVC K8s->>User: PVC bound and ready

Example StorageClass

Here’s a StorageClass for Google Cloud Platform:

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: fast-ssd
provisioner: pd.csi.storage.gke.io
parameters:
  type: pd-ssd           # SSD disk type
  replication-type: regional-pd  # Regional persistent disk
volumeBindingMode: WaitForFirstConsumer
reclaimPolicy: Delete
allowVolumeExpansion: true

This StorageClass:

  • Uses GKE’s CSI provisioner for Persistent Disks
  • Creates SSD-type disks
  • Creates regional persistent disks (replicated across zones)
  • Waits for a pod to use the PVC before provisioning (better scheduling)
  • Deletes volumes when PVCs are deleted
  • Allows volume expansion

Default StorageClass

Kubernetes clusters usually have a default StorageClass. When you create a PVC without specifying a storageClassName, Kubernetes uses the default StorageClass.

To set a StorageClass as default, add the annotation:

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: standard
  annotations:
    storageclass.kubernetes.io/is-default-class: "true"
provisioner: kubernetes.io/gce-pd
parameters:
  type: pd-standard

Common StorageClass Patterns

Fast Storage (SSD)

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: fast-ssd
provisioner: pd.csi.storage.gke.io
parameters:
  type: pd-ssd
reclaimPolicy: Retain  # Protect data

Standard Storage (HDD)

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: standard-hdd
provisioner: pd.csi.storage.gke.io
parameters:
  type: pd-standard
reclaimPolicy: Delete  # Auto-cleanup

Encrypted Storage

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: encrypted
provisioner: pd.csi.storage.gke.io
parameters:
  type: pd-ssd
  disk-encryption-kms-key: projects/my-project/locations/us/keyRings/my-keyring/cryptoKeys/my-key

Using StorageClasses in PVCs

Reference a StorageClass in your PVC:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: my-pvc
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: fast-ssd  # References the StorageClass
  resources:
    requests:
      storage: 50Gi

Best Practices

  1. Use dynamic provisioning - Prefer StorageClasses over static provisioning for simplicity
  2. Create multiple StorageClasses - Different classes for different use cases (fast, standard, encrypted)
  3. Set appropriate reclaim policies - Retain for production, Delete for development
  4. Use WaitForFirstConsumer - For better pod scheduling, especially with zone-aware storage
  5. Document StorageClasses - Document which StorageClass to use for which use case
  6. Test provisioning - Verify that StorageClasses work correctly in your cluster
  7. Set default StorageClass - Configure a sensible default for your cluster

Topics

See Also