Sling Academy
Home/DevOps/Understanding Storage Classes and Dynamic Provisioning in Kubernetes (4 Examples)

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

Last updated: January 30, 2024

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.

Next Article: Deploying System-wide Tools Using DaemonSets in Kubernetes

Previous Article: Using PVCs to Request Storage in Kubernetes: Tutorial & Examples

Series: Kubernetes Tutorials

DevOps

You May Also Like

  • How to reset Ubuntu to factory settings (4 approaches)
  • Making GET requests with cURL: A practical guide (with examples)
  • Git: What is .DS_Store and should you ignore it?
  • NGINX underscores_in_headers: Explained with examples
  • How to use Jenkins CI with private GitHub repositories
  • Terraform: Understanding State and State Files (with Examples)
  • SHA1, SHA256, and SHA512 in Terraform: A Practical Guide
  • CSRF Protection in Jenkins: An In-depth Guide (with examples)
  • Terraform: How to Merge 2 Maps
  • Terraform: How to extract filename/extension from a path
  • JSON encoding/decoding in Terraform: Explained with examples
  • Sorting Lists in Terraform: A Practical Guide
  • Terraform: How to trigger a Lambda function on resource creation
  • How to use Terraform templates
  • Understanding terraform_remote_state data source: Explained with examples
  • Jenkins Authorization: A Practical Guide (with examples)
  • Solving Jenkins Pipeline NotSerializableException: groovy.json.internal.LazyMap
  • Understanding Artifacts in Jenkins: A Practical Guide (with examples)
  • Using Jenkins with AWS EC2 and S3: A Practical Guide