Introduction to Storage Classes
The previous installment in this series outlined two volume provisioning methods, static and dynamic. The exercise on creating a PersistentVolume was based on static volume provisioning, while this segment will focus on the dynamic method using StorageClass. You’ll learn how to make a volume request of any size, without worrying about whether or not it’s available in the storage pool.
Here’s what we’ll cover:
- What is a StorageClass?
- How to create a StorageClass
- How to reference a StorageClass in a PersistentVolumeClaim (PVC)
- How do StorageClasses help to make data persistence more dynamic?
What Is a Kubernetes StorageClass?
A StorageClass is a Kubernetes resource that enables dynamic storage provisioning. The administrator configures the StorageClass, which can then no longer be modified. First the StorageClass is created, then the PersistentVolumeClaim and finally the Pod. When a PVC is created, Kubernetes creates a PersistentVolume and binds it to the PVC automatically, depending on the VolumeBindingMode used in the StorageClass configuration. These three Kubernetes objects are required to check the test case of a StorageClass.
How to Create and Reference a StorageClass in a PVC
Creating a StorageClass is similar to the way we created previous Kubernetes objects, except that it has its own properties and values, which will be described later. The configuration file below is an example of a StorageClass manifest file:
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: my-storageclass
provisioner: kubernetes.io/aws-ebs
volumeBidingMode: WaitForFirstConsumer
The apiVersion, kind, and metadata are common properties that you will be familiar with from our previous exercises on Kubernetes objects. The new, additional properties are:
- Provisioner: This property is essential, and it must be specified. It is a field that determines which volume plugin should be used to provision the PVs. There are many volume plugins that are classified as either internal or external provisioners. (e.g., GCEPersistentDisk, Azuredisk, Azurefile, AWSElasticBlockStore, NFS, Flexvolume, Local, etc.). The first four use internal provisioner plugins, while the last three are external. Each of these has its config example used as part of the provisioner field’s value, depending on which volume plugin you want to use.
The table below shows the standard volume plugins and their provisioners.
You can find more volume plugins and their provisioners in the Kubernetes official documentation.
volumeBindingMode: This property has two values, Immediate and WaitForFirstConsumer.
- Immediate Mode: This mode involves the automatic volume binding of PVs to PVCs with a StorageClass once a PVC is created.
- WaitForFirstConsumer Mode: This mode will delay the binding and dynamic provisioning of PVs, until a Pod that will use it is created.
The following stages will guide you through how to create and use a StorageClass.
Stages:
- Create a StorageClass
- Create a PVC for storage request from StorageClass
- Create a Pod to consume the claim by referencing the PVC in the Pod
Hands-on Practice
Basic knowledge of Pod, Deployment, Volume, PersistentVolume and PersistentVolumeClaim is recommended to make the most of this hands-on practice. Please refer to our previous posts on these concepts if you need to familiarize yourself with them. In addition, a running Kubernetes cluster is required for this exercise. You can simply create a single Node cluster using Kubeone. The documentation and guide can be found here.
Stage 1:
Create a StorageClass: Here are the steps to create a StorageClass:
Step 1: Create a file with vim or any editor of your choice:
$ vim st-class.yaml
Step 2: Copy and paste the above StorageClass manifest file into the created YAML file and create the StorageClass with kubectl create
command.
$ kubectl create -f st-class.yaml
storageclass.storage.k8s.io/my-storageclass created
Step 3: Check the details of the StorageClass:
$ kubectl get sc my-storageclass
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE AGE
my-storageclass kubernetes.io/aws-ebs Delete WaitForFirstConsumer 9s
Stage 2:
Create a PVC: You can read more on PVC in this previous chapter in the series. A “storageClassName” property should be added to the PVC manifest file, with the StorageClass name created in stage 1 as its value, which in this case will be “my-storageclass”. When this field is omitted, the default StorageClass, which is “Standard,”, will be provisioned with the PVC. It is always suggested to reference the StorageClass name in the PVC to use the desired StorageClass. The complete configuration will look like this:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: my-claim
spec:
accessModes:
- ReadWriteOnce
storageClassName: my-storageclass
resources:
requests:
storage: 2Gi
Step 1: Create the PVC with kubectl create
command:
$ kubectl create -f my-pvc.yaml
persistentvolumeclaim/my-claim created
Step 2: Check the status of the PVC:
$ kubectl get pvc my-claim
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
my-claim Pending my-storageclass 9s
The status output shows that the PVC is pending, because WaitForFirstConsumer is used as the VolumeBindingMode value in the StorageClass configuration. It will remain in this state until a Pod that will consume the claim is created.
Now, Check the PersistentVolume status using kubectl get
command:
$ kubectl get pv
No resources found
You can’t see an available PersistentVolume on the cluster, even though a PVC has been created. Delete the PVC and then the StorageClass, change the volumeBindingMode value in the StorageClass manifest file to “Immediate,” create the two objects again and check the status. You can now go to stage 3 and create a Pod.
Stage 3:
Create a Pod to consume the claim: The previous configuration will be used. The PVC name must be the same as the persistentClaimVolume.claimName field’s value in the Pod. The configuration will look like this:
$ vim st-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- name: stclass-test
image: nginx
volumeMounts:
- mountPath: "/app/data"
name: my-volume
volumes:
- name: my-volume
persistentVolumeClaim:
claimName: my-claim
Step 1: Create the Pod with kubectl create
command:
$ kubectl create -f st-pod.yaml
pod/my-pod created
Step 2: Check the Pod status:
$ kubectl get pods my-pod
NAME READY STATUS RESTARTS AGE
my-pod 1/1 Running 0 3m
Check the status of the PVC again:
$ kubectl get pvc my-claim
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
my-claim Bound pvc-6e5dae64 2Gi RWO my-storageclass 10m
As shown above, the status of the PVC has changed from a pending to a bound state. This simply means that all three objects created are now bound or reference one another.
The next step is to check the PersistentVolume status again using the kubectl get
command:
$ kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS AGE
pvc-6e5dae64 2Gi RWO Delete Bound default/my-claim my-storageclass 99s
If everything works correctly, you should see the same output as above. You can now see that a PersistentVolume was automatically created when we created the Pod. This is dynamic volume provisioning using StorageClass.
The persistent functionality can be tested using ssh in the Pod; create and save a file inside the Pod, then delete the Pod. Re-create the Pod again and check for the file that was created before deleting the Pod. You can do this by following these steps:
Step 1: Exec into the Pod:
$ kubectl exec -it my-pod -- bin/bash
root@my-pod:/#
Step 2: Change to the mount directory—The same directory for volumeMount in the Pod manifest file.
root@my-pod:/# cd app/data
root@my-pod:/app/data#
Step 3: Create and store some data in a text file and check the file to be sure the data is written in the file, and exit the Pod:
root@my-pod:/app/data# echo My StorageClass Message > stclass.txt
root@my-pod:/app/data# cat stclass.text
My StorageClass Message
Step 4: Now delete the Pod:
$ kubectl delete pod my-pod
pod "my-pod" deleted
$ kubectl get pods
No resources found
Recreate it:
$ kubectl create -f st-pod.yaml
pod/my-pod created
Check the Pod status to confirm if it is running:
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
my-pod 1/1 Running 0 89s
Step 5: Exec into the Pod again and check that the file was created before the Pod was deleted:
$ kubectl exec -it my-pod -- bin/bash
root@my-pod:/# cd /app/data
root@my-pod:/app/data# ls
stclass.text
root@my-pod:/app/data# cat stclass.text
My StorageClass Message
The data that was created remained beyond the Pod’s lifecycle
Clean-Up:
To clean up your Kubernetes environment after this exercise, you can delete the Pod, PVC, and StorageClass using the kubectl delete
command. This ensures that no residual resources are left running in your cluster, especially if you’re managing limited resources.
By using the command kubectl delete storageclass
, you can remove the StorageClass resource from your Kubernetes cluster when it’s no longer needed, making sure you’re not using up resources you don’t need.
Summary: StorageClass is a Kubernetes object that preserves your application data by storing it in the cloud. It is based on which volume plugin is used to provision the StorageClass. (e.g., in the above case, the AWS cloud). Manual provisioning of PersistentVolume in advance is not required, as it is in the static provisioning method. Instead, the StorageClass object must be created before the PersistentVolumeClaim.
Next in our series, we’ll look at the best practice for taking care of stateful applications by introducing another Kubernetes object, a StatefulSet. Applications in Kubernetes can be either stateful or stateless. We have worked on various stateless applications in previous parts of this series, so the next will focus on creating applications using a StatefulSet.
We’d love to hear from you! Please do not hesitate to contact us with any thoughts or questions, or any clarifications you might want about Kubernetes Storage Classes.
Learn More
- Learn more about Storage Classes
- Check our more StorageClass resources
- Read more on Setting the default StorageClass