The End of Manual Labor

Note

This module explores the core principles of Storage Classes, deriving solutions from first principles and hardware constraints to build world-class expertise.

Before Storage Classes, a Cluster Admin had to manually create 100 PVs in anticipation of developer needs. When those ran out, deployments failed. This is not Cloud Native.

1. Dynamic Provisioning: The Storage Vending Machine

Think of manual Persistent Volumes (PVs) as a custom-tailored suit: an Administrator has to manually measure, cut, and provision the storage beforehand. If a developer needs storage, they must wait for the Admin to fulfill the ticket. This is the Static Provisioning model.

Storage Classes (SC) transform the cluster into a Storage Vending Machine. The Administrator defines the “products” available in the vending machine (e.g., “fast-ssd”, “cheap-hdd”, “encrypted-nvme”). When a Developer submits a Persistent Volume Claim (PVC) specifying a storageClassName, they insert their coin. The Kubernetes Control Plane automatically talks to the Cloud Provider’s API to mint a brand new disk matching the requested profile, and binds it to the PVC.

No pre-provisioning. No waiting. Just instant, API-driven storage.


2. Interactive: Dynamic Provisioning Flow

Visualize how a PVC triggers the creation of real cloud infrastructure.

👤

Developer

Create PVC
Class: "fast-ssd"
⚙️

K8s Control Plane

Reads SC "fast-ssd"
Provisioner: aws-ebs
☁️

AWS API

Creating Volume...
💾

PV Created

Bound to PVC

3. Anatomy of a StorageClass

A StorageClass is an interface to a specific storage backend (the Provisioner).

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: fast-ssd  # Developers reference this name
provisioner: ebs.csi.aws.com # The CSI Driver
parameters:
  type: gp3       # AWS specific parameter
  iops: "3000"
reclaimPolicy: Delete
allowVolumeExpansion: true
volumeBindingMode: WaitForFirstConsumer

Key Fields & Technical Depth

  1. Provisioner: The plugin that executes the volume creation.
    • Historical Context: Older clusters used “in-tree” provisioners like kubernetes.io/aws-ebs. The K8s source code was bloated with cloud-provider-specific logic.
    • Modern Standard: Kubernetes migrated to the Container Storage Interface (CSI). Now, you use out-of-tree drivers like ebs.csi.aws.com. This keeps the core K8s binary lightweight and allows cloud providers to update their drivers independently.
  2. Parameters: Opaque key-value pairs passed directly to the CSI driver (e.g., “IOPS”, “Encryption Key”). Kubernetes does not validate these; it just passes them along.
  3. ReclaimPolicy: Dictates the lifecycle of the actual cloud disk when the PVC is deleted.
    • Delete (Default for dynamic provisioning): The AWS EBS volume is completely destroyed. Data is irretrievably lost.
    • Retain: The PV object becomes “Released”, but the actual cloud disk remains intact in AWS. An Admin must manually reclaim or backup the data.
  4. VolumeBindingMode: Determines when the storage is provisioned.
    • Immediate: Creates the volume instantly upon PVC creation.
    • WaitForFirstConsumer: (Crucial Best Practice) Delays volume creation until a Pod using the PVC is scheduled onto a Node.

War Story: The Cross-Zone Attachment Nightmare

Imagine a multi-zone cluster (us-east-1a, us-east-1b). You create a PVC with VolumeBindingMode: Immediate. The Provisioner talks to AWS and creates an EBS volume in us-east-1a randomly.

Later, your Deployment creates a Pod. The K8s Scheduler decides the node in us-east-1a is full, so it schedules the Pod in us-east-1b.

The result? The Pod stays in ContainerCreating forever. AWS EBS volumes are zonal; a Pod in 1b cannot attach a disk sitting in 1a. By changing the StorageClass to WaitForFirstConsumer, you force the Provisioner to wait for the Scheduler’s decision. The disk is created in 1b because the Pod was scheduled there. Problem solved.


4. The “Default” Storage Class

Every cluster usually has one StorageClass marked as default. If a PVC does not specify a storageClassName, it gets the default.

To check your classes:

kubectl get sc

Output:

NAME                 PROVISIONER             RECLAIMPOLICY   VOLUMEBINDINGMODE      AGE
standard (default)   kubernetes.io/gce-pd    Delete          Immediate              10d
premium-rwo          pd.csi.storage.gke.io   Delete          WaitForFirstConsumer   10d
Tip

Use WaitForFirstConsumer in multi-zone clusters. Without it, the provisioner might create an EBS volume in us-east-1a, but your Pod might get scheduled in us-east-1b. The Pod will fail to start because it cannot attach a volume across zones.

5. Next Steps

We have covered how to get storage (PVC) and how it is created (SC). But what if you need to run a Database Cluster where each replica needs its own unique identity and storage? Enter StatefulSets.