1. Introduction

Nowadays, Kubernetes is a significant tool for managing containers and software hosted in the cloud. One of the crucial aspects of managing this software is persistent data storage.

Kubernetes uses PersistentVolume (PV) and PersistentVolumeClaims (PVC) for such purposes. In this article, we’ll introduce PV and PVC fundamentals and elaborate on how to bind them correctly.

2. Fundamentals

PV is a storage resource that is controlled by the cluster admin. PV represents physical resources used for data storage such as NFS, iSCSI, or local disks.

PVCs are requests made by applications for non-physical storage resources while PVs are physical storage resources. PVC declares what resources are necessary to store the data; for example, required on-disk size and control access permissions.

Below we can see a visualization of PVC and PV binding workflow:

PV and PVC

Let’s elaborate on each of them separately.

2.1. PersistentVolume (PV)

As we said, a PersistentVolume is a piece of storage in the Kubernetes cluster. This storage can be provided by a variety of mass memory types but also by external storage services such as Amazon EBS or Google Persistent Disk.

PV is a resource independent of any pod‘s lifecycle. Additionally, a single PV can be accessed by multiple pods. Thus, this feature decouples the storage from the pods.

PersistentVolume provides a storage resource definition, that defines the setting of storage resource including its size, mass memory type, and access modes.

Moreover, PV specification describes a few important fields namely:

Below we can see an example of a PV definition in a .yaml file:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-example
spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: fast
  hostPath:
    path: /data

The example configures a PV with a capacity of 10 Gigabytes. The accessModes contains only a single setting, ReadWriteOnce. Thus, it enables a single node to mount the volume as read-write.

Moreover, the persistentVolumeReclaimPolicy is set to Retain value. Therefore, the PV won’t be removed automatically when a PVC is removed. The manifest file creates a storageClassName of value fast which provisions SSD-like persistent disks.

PV is accessible by applications after defining an appropriate PVC. When the PVC is created, Kubernetes can automatically match a PV that meets the requirements of the PVC request. While matched, the PV is reserved by a specific PVC and can’t be used by other PVCs until it’s released.

2.2. PersistentVolumeClaim (PVC)

PVC is a mechanism that allows applications to request specific PVs inside the Kubernetes cluster. It provides a declarative description of storage data requirements whereas Kubernetes manages binding appropriate PVs that meet those requirements.

PVC allows clients to describe what data storage resources are needed including their capacity, type, and access privileges. PVC manifest contains important fields including:

  • resources.requests.storage – specifies the amount of data storage the application needs, for example, 10Gi (10 gigabytes)
  • accessModes – defines the access modes that are required by the application
  • storageClassName – describes the storage class that PVC uses to match the appropriate PV

Below we can see an example PVC manifest:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-example
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi
  storageClassName: fast

As we can see, the PVC’s manifest is similar to the PV’s. However, there is a significant difference between PV and PVC purposes. PersistentVolume defines the actual storage resource that’ll be created. Whereas, PersistentVolumeClaim represents a client’s request for a storage resource with specific requirements.

3. How to Bind a PVC to a Specific PV

Correct binding of a PVC to a PV is crucial for stable and secure data management in Kubernetes. It ensures durable data storage, effective disk resource management, increased data security through data isolation, and flexible scalability. Let’s see an example process on how to bind PVC to PV.

3.1. Create PV Manifest

Firstly, let’s create a PV with specific attributes, such as storage capacity, access modes, and storage class. We must also define a claimRef to reserve this PV for a particular PVC.

Let’s create an example PV manifest:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: example-pv
spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: manual
  nfs:
    path: /path/to/nfs
    server: nfs-server.example.com
  claimRef:
    namespace: default
    name: example-pvc

This manifest contains the following important attributes:

  • name – defines the name of the PV as example-pv
  • capacity.storage 10Gi – specifies the storage size
  • accessModes – specifies the access mode (in this case, ReadWriteOnce)
  • storageClassName – defines the storage class as manual. Moreover, nfs provides the NFS server details and path.
  • claimRef – reserves this PV for a PVC named example-pvc in the default namespace

3.2. Create PVC

Now, let’s create a PVC that matches the specifications of the PV. Thus, the PVC name should match the value specified in the claimRef of the PV.

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: example-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi
  storageClassName: manual

In this manifest, we can notice:

  • name – defines the name value of the PVC (example-pvc). The PVC name should match the name specified in the claimRef of the PV.
  • accessModes – specifies the access mode (ReadWriteOnce)
  • resources.requests.storage: 10Gi – specifies the requested storage size
  • storageClassName – matches the storage class of the PV

3.3. Apply and Verify

Now, we need to apply both manifests to the Kubernetes cluster using kubectl interface:

$ kubectl apply -f pv-manifest.yaml
$ kubectl apply -f pvc-manifest.yaml

The above command will create a PV and a PVC in the cluster. Further, we can verify if the binding is correct. We can achieve that by presenting the PVC information using kubectl get.

Thus, the result should show that the PVC is in a Bound state as in the example below:

$ kubectl get pvc
NAME          STATUS    VOLUME        CAPACITY   ACCESS MODES   STORAGECLASS   AGE
example-pvc   Bound     example-pv    10Gi       RWO            manual         5m

In this section, we presented an example of how to bind a PVC to a PV manually.

4. Common Problems and Solutions

In this section, we’ll discuss the most common problems while binding PVCs and PVs and how to troubleshoot them.

To begin with, one of the popular issues is storageClassName mismatch. In such a case, we must ensure that storageClassName in PVC and PV are the same. If one of these resources has a different or missing storageClassName (another PV has a default storage class), the binding will not occur correctly.

The second frequent issue is capacity mismatch. It occurs when the storage capacity requested by PVC exceeds the capacity of the PV. The solution is simple, we need to ensure that the PVC requests storage capacity that is less than or equal to the PV’s storage capacity.

The next mismatch that can occur is accessModes mismatch. Similarly, as in the previous problem, we need to make certain that accessModes in the PVC and PV are the same to bind them correctly.

Other types of problems that can occur are configuration problems. An example of such a case is an invalid configuration of the NFS server or its path. We should ensure that those data are correct and that we have the required permissions to access the server.

Finally, if we use namespaces in our manifests we need to ensure that PV and PVC are located in the same namespace. In another case, the PV and PVC won’t be visible to each other.

We’ve discussed a few common problems related to binding PV and PVC. A good understanding of these resources, characteristics, and problems is significant for building stable and reliable Kubernetes-based software.

5. Conclusion

PersistentVolumes and PersistentVolumeClaims are significant Kubernetes resources when it comes to managing persistent storage.

In this article, we’ve learned the differences between them, how to bind them, and why it’s important. That knowledge is crucial for building a reliable cloud-hosted application that operates on data stored in a variety of storage providers.