Understanding Storage Classes and Dynamic Provisioning in Kubernetes (4 Examples)

Updated: January 30, 2024 By: Guest Contributor Post a comment

Overview

Managing storage in a containerized environment can be complex, but Kubernetes offers powerful abstractions to handle persistent data storage needs. Two essential concepts in the Kubernetes storage paradigm are ‘Storage Classes’ and ‘Dynamic Provisioning’. This tutorial will demystify these concepts and walk you through code examples that incrementally build your understanding of how to effectively manage storage in Kubernetes.

Introduction to Storage in Kubernetes

Before diving into Storage Classes and Dynamic Provisioning, it’s important to understand the storage primitives that Kubernetes offers:

  • Persistent Volumes (PVs): Cluster resources that represent storage in the network, which can be consumed by applications.
  • Persistent Volume Claims (PVCs): Requests for storage by users which can be bound to PVs.

PVs and PVCs are static forms of volume management. Storage Classes, on the other hand, enable dynamic volume provisioning, allowing storage resources to be created on-demand.

Understanding Storage Classes

In Kubernetes, a Storage Class provides a way to define the ‘class’ of storage you require. Storage classes allow you to abstract the details of how storage is provisioned from how it is consumed.

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: standard
provisioner: kubernetes.io/aws-ebs
parameters:
  type: gp2
reclaimPolicy: Retain
allowVolumeExpansion: true
mountOptions:
  - debug
volumeBindingMode: Immediate

The above YAML snippet is an example of a StorageClass object that defines a class of storage backed by AWS’s Elastic Block Store (EBS), with specific parameters like `type`, `reclaimPolicy`, and others.

Example 1: Creating a Storage Class

Let’s start with a simple StorageClass definition for Google Cloud’s Persistent Disk:

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: slow
provisioner: kubernetes.io/gce-pd
parameters:
  type: pd-standard
  replication-type: none

Apply this definition using kubectl apply -f storage-class.yaml. To confirm creation, use kubectl get sc, which should yield:

NAME   PROVISIONER            AGE
slow   kubernetes.io/gce-pd   32s

Dynamic Provisioning

With Storage Classes in place, you don’t need to create PVs manually; instead, you define PVCs and Kubernetes dynamically provisions the appropriate storage through the Storage Class.

Example 2: Dynamic PVC Provisioning

Create a PVC that utilizes the previously defined Storage Class:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mypvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi
  storageClassName: slow

After applying this PVC with kubectl apply -f pvc.yaml, you can inspect its status using kubectl get pvc mypvc, which should automatically bind to a newly created PV, showing STATUS: Bound.

Advanced Usage of Storage Classes

As you become more experienced with Kubernetes, you’ll encounter advanced use-cases for Storage Classes.

Example 3: Using StorageClass for StatefulSets

Here is a StatefulSet definition that uses our StorageClass for each of its Pods:

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  selector:
    matchLabels:
      app: nginx
  serviceName: "nginx"
  replicas: 3
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: k8s.gcr.io/nginx-slim:0.8
        ports:
        - containerPort: 80
          name: web
        volumeMounts:
        - name: www
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates:
  - metadata:
      name: www
    spec:
      accessModes: [ "ReadWriteOnce" ]
      storageClassName: "slow"
      resources:
        requests:
          storage: 1Gi

Each Pod in the StatefulSet will now dynamically provision its own storage based on the specified StorageClass.

Example 4: Snapshots and Cloning

Kubernetes 1.17 introduced VolumeSnapshot resources that allow you to create a snapshot of the data within a PV. Here’s an example that demonstrates creating a snapshot:

apiVersion: snapshot.storage.k8s.io/v1alpha1
kind: VolumeSnapshot
metadata:
  name: new-snapshot
spec:
  snapshotClassName: csi-gce-pd-snapshot-class
  source:
    name: mypvc
    kind: PersistentVolumeClaim

Similarly, you can create a PVC from a snapshot, enabling cloning of volumes.

Best Practices

When working with dynamic provisioning and Storage Classes, you should:

  • Understand the specific parameters and features offered by your chosen storage backend.
  • Choose the right reclaim policy for PVs to adapt to your retention requirements.
  • Use labeling and resource quotas to manage and monitor storage consumption.

Conclusion

Storage Classes and Dynamic Provisioning in Kubernetes facilitate a more agile and flexible way to manage storage resources in a cloud-native environment. By leveraging these features, developers can focus on building applications rather than worrying about underlying storage details.