Qingular

StorageClass and Dynamic Provisioning

·CKAk8sPractice

CKA Exam Domain 4 — StorageClass definition, dynamic PV provisioning, CSI drivers, default StorageClass

← Back to CKA Practice Index StorageClass provides administrators with a way to describe "classes" of storage, enabling dynamic PV provisioning and avoiding the need for manual PV pre-provisioning.


1. StorageClass Definition and Provisioner

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: fast
provisioner: kubernetes.io/aws-ebs
parameters:
  type: gp3
  fsType: ext4
  encrypted: "true"
reclaimPolicy: Delete
allowVolumeExpansion: true
volumeBindingMode: Immediate

Core fields:

FieldDescription
provisionerName of the storage backend driver
parametersParameters passed to the provisioner
reclaimPolicyReclaim policy for dynamically created PVs (Delete or Retain)
allowVolumeExpansionWhether to allow PVC expansion
volumeBindingModeBinding mode (Immediate or WaitForFirstConsumer)
mountOptionsMount options

2. Dynamic PV Provisioning Principles

  1. User creates PVC (specifying storageClassName: fast)
  2. Kubernetes control plane finds the corresponding StorageClass
  3. Calls the StorageClass provisioner to create storage resources
  4. Automatically creates a PV and binds it to the PVC
  5. Pod uses PVC to mount storage
User (PVC) ──► StorageClass ──► Provisioner ──► Actual Storage ──► PV

3. Default StorageClass

After setting a default StorageClass, creating a PVC without specifying storageClassName will automatically use the default StorageClass.

# View the current default StorageClass
kubectl get storageclass

# Set a StorageClass as default
kubectl patch storageclass standard -p \
  '{"metadata": {"annotations": {"storageclass.kubernetes.io/is-default-class": "true"}}}'
metadata:
  annotations:
    storageclass.kubernetes.io/is-default-class: "true"

Note: storageClassName: "" in a PVC means not using the default StorageClass, but using a static PV instead.


4. Common Provisioners

AWS EBS

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: aws-ebs-gp3
provisioner: ebs.csi.aws.com
parameters:
  type: gp3
  fsType: ext4
  encrypted: "true"
  iopsPerGB: "10"
reclaimPolicy: Delete
volumeBindingMode: WaitForFirstConsumer

GCE PD

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: gce-pd-ssd
provisioner: pd.csi.storage.gke.io
parameters:
  type: pd-ssd
  replication-type: none
reclaimPolicy: Delete
volumeBindingMode: WaitForFirstConsumer

Azure Disk

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: azure-disk
provisioner: disk.csi.azure.com
parameters:
  skuname: Premium_LRS
  cachingMode: ReadOnly
reclaimPolicy: Delete
allowVolumeExpansion: true

NFS (via CSI)

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: nfs-csi
provisioner: nfs.csi.k8s.io
parameters:
  server: nfs-server.example.com
  share: /exports
reclaimPolicy: Delete
volumeBindingMode: Immediate
mountOptions:
  - hard
  - nfsvers=4.1

5. volumeBindingMode

ModeDescription
ImmediateCreate PV and bind immediately after PVC creation
WaitForFirstConsumerWait until the first Pod uses the PVC before creating PV (AZ-aware based on Pod scheduling)

WaitForFirstConsumer is commonly used in multi-cloud/multi-AZ environments to ensure the PV is created in the same availability zone as the Pod.


6. volumeBindingMode Comparison

# Delayed binding: PV is created in the AZ where the Pod is scheduled
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: regional-ssd
provisioner: pd.csi.storage.gke.io
volumeBindingMode: WaitForFirstConsumer

7. CSI Driver Concepts and Usage

CSI (Container Storage Interface) is the recommended storage plugin mechanism for Kubernetes.

Advantages:

  • Plugins do not need to be compiled into Kubernetes binaries
  • Deployed via DaemonSet, hot-pluggable
  • Supports snapshots, expansion, cloning, and other advanced features
# View installed CSI drivers
kubectl get csidriver

# View CSI node status
kubectl get csinodes

8. Useful Commands

# View all StorageClasses
kubectl get sc
kubectl get storageclass

# View StorageClass details
kubectl describe sc <storage-class-name>

# Create StorageClass (from YAML)
kubectl create -f sc.yaml

# Delete StorageClass
kubectl delete sc <storage-class-name>

# Check default StorageClass
kubectl get sc -o jsonpath='{.items[*].metadata.annotations.storageclass\.kubernetes\.io/is-default-class}'

9. Exam Key Points

  • PVC without storageClassName = uses default StorageClass
  • PVC with storageClassName: "" = uses static PV (manually created)
  • WaitForFirstConsumer is very important in topology-aware environments
  • Dynamic PV reclaimPolicy defaults to Delete
  • CSI is the currently recommended official storage extension method

🧪 Complete Hands-on Example: Dynamically Creating PVs Using StorageClass

Scenario

Define a StorageClass and use it to automatically create PVs, observing the complete dynamic provisioning process and the effect of the reclaim policy (Delete).

Prerequisites

  • The cluster needs a CSI driver provisioner (e.g., ebs.csi.aws.com, pd.csi.storage.gke.io, etc.)
  • If using minikube, enable the standard StorageClass; the following example uses the local standard as a simulation

Steps

Step 1: View Existing StorageClasses in the Cluster

kubectl get sc
# NAME                   PROVISIONER                     RECLAIMPOLICY   VOLUMEBINDINGMODE      ALLOWVOLUMEEXPANSION   AGE
# standard (default)     k8s.io/minikube-hostpath        Delete          Immediate             false                  15d

Step 2: Create a Custom StorageClass

cat <<EOF | kubectl apply -f -
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: fast-storage
provisioner: k8s.io/minikube-hostpath
parameters:
  type: pd-ssd
reclaimPolicy: Delete
volumeBindingMode: Immediate
allowVolumeExpansion: true
EOF

kubectl get sc
# NAME                   PROVISIONER                     RECLAIMPOLICY   VOLUMEBINDINGMODE      ALLOWVOLUMEEXPANSION   AGE
# fast-storage           k8s.io/minikube-hostpath        Delete          Immediate             true                   5s
# standard (default)     k8s.io/minikube-hostpath        Delete          Immediate             false                  15d

Step 3: Create a PVC Referencing This StorageClass

cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: dynamic-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
  storageClassName: fast-storage
EOF

Step 4: Observe the PV Being Dynamically Created

kubectl get pvc
# NAME          STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
# dynamic-pvc   Bound    pvc-8f3b2c1d-...                          1Gi        RWO            fast-storage    10s

kubectl get pv
# NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                 STORAGECLASS   AGE
# pvc-8f3b2c1d-...                           1Gi        RWO            Delete           Bound    default/dynamic-pvc   fast-storage    10s

The PV name is a dynamically generated UUID format, and RECLAIM POLICY automatically inherits Delete from the StorageClass.

Step 5: View Detailed Information of the Dynamic PV

kubectl describe pv pvc-8f3b2c1d-...
# ...
# Source:
#     Type:          HostPath (bare host directory volume)
#     Path:          /data/hostpath-provisioner/default/dynamic-pvc
# ...
# Reclaim Policy:  Delete
# StorageClass:    fast-storage

Step 6: Delete PVC and Observe PV Auto-Deletion

kubectl delete pvc dynamic-pvc

kubectl get pvc
# No resources found in default namespace.

kubectl get pv
# (the previously dynamically created PV has been automatically deleted, not displayed)

Due to reclaimPolicy: Delete, the associated PV is automatically deleted after PVC deletion, no manual intervention required.

Verification

# Verify the StorageClass was created successfully
kubectl get sc fast-storage -o jsonpath='{.provisioner}'
# k8s.io/minikube-hostpath

# Verify the PVC references the correct StorageClass
kubectl get pvc dynamic-pvc -o jsonpath='{.spec.storageClassName}'
# fast-storage

# Verify the dynamic PV reclaim policy
kubectl get pv -o jsonpath='{.items[0].spec.persistentVolumeReclaimPolicy}'
# Delete

Exam Tips

  • A PVC without storageClassName uses the cluster's default StorageClass
  • A PVC with storageClassName: "" means using a static PV, dynamic provisioning not enabled
  • Dynamic PV reclaim policy defaults to Delete; change to Retain if you want to preserve data
  • In WaitForFirstConsumer mode, the PVC STATUS remains Pending after creation until the first Pod uses it
  • In the exam, if a dynamic provisioning scenario appears, remember to check whether the StorageClass provisioner matches

Official Documentation