In Kubernetes, Persistent Volumes (PVs) and Persistent Volume Claims (PVCs) are two important concepts. Both are used for data storage: they handle the details of storage and its implementation, such as the volume size. On our Kubernetes platform, for example, you use them for configuring your block storage.
In this article, we explain the differences between PVs and PVCs in Kubernetes and show examples of how they're used.
Persistent Volumes vs Persistent Volume Claims
Although they may seem similar, there are differences between Persistent Volumes and Persistent Volume Claims:
Persistent Volume (PV): A PV is a piece of storage in a Kubernetes cluster. It is a resource in your cluster, just like a node is a resource. PVs have an independent lifespan from the individual pods that use them. This means that the PV remains in existence even if the pods using the PV are removed.
Persistent Volume Claim (PVC): A PVC is a request for storage, similar to how a pod consumes resources from a node. Pods consume node resources, and PVCs consume PV resources. Claims can request specific sizes and access modes (e.g., mountable as read-write or read-only).
In short, the main difference is that a Persistent Volume is bound to a cluster, while a Persistent Volume Claim is bound to a specific namespace (the default namespace if none is specified).
Are You Using a PersistentVolume and/or a PersistentVolumeClaim?
You can create a PVC without explicitly creating a PV. If you create a PVC without specifying a specific PV, Kubernetes will provision a PV with sufficient storage capacity. It will automatically bind to the PVC that requested it and will not be available for other PVCs. This is called dynamic provisioning and is a very common way to manage storage in Kubernetes. When you use both PV and PVC, it is referred to as static provisioning.
Whether you use a PV or PVC mainly depends on whether you want to preserve the PV after deleting your pods. This depends on your use case, and it is important to consider this difference before making a choice. This is not only important for your own configuration but also because many Helm Charts and online examples of .yaml objects use both PV and PVC, and you may prefer to use only a PVC.
To help you make a choice between dynamic and static provisioning, here are some advantages and disadvantages:
Advantages of Dynamic Provisioning:
- Simplifies storage management, as you don't have to manually create PVs.
- Prevents over-requesting storage because you only request the necessary amount in your PVC. In a combination of PV and PVC, you usually request more space for the PV to accommodate multiple PVCs.
Disadvantages of Dynamic Provisioning:
- Depending on your configuration, it can lead to unexpected costs. You are relatively free to request as much storage as you want, whereas static provisioning typically sets a reasonable limit.
Advantages of Static Provisioning:
- Provides more control over the specific details of how storage is created.
- Can be useful in situations where specific storage configurations are required and cannot be achieved with a StorageClass.
Disadvantages of Static Provisioning:
- Requires (slightly) more manual management than dynamic provisioning.
- May result in wasted storage space if PVs are created but not fully utilized.
Example of a PV and PVC
PVs and PVCs may still seem somewhat abstract at this point, but they become more concrete with an example. A Persistent Volume can be defined as follows (in a .yaml file):
apiVersion: v1
kind: PersistentVolume
metadata:
name: my-pv
spec:
storageClassName: transip-fast-storage
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
claimRef:
name: my-pvc
namespace: pvc-demo
We explain some of the items in the code above in our documentation on creating .yaml objects. The concepts that may be new to you are:
- spec.storageClassName: The type of storage you can use on a Kubernetes platform, obtained by running 'kubectl get sc'. In this case, transip-fast-storage (the default value, which uses NVMe) and transip-big-storage (HDD).
- spec.capacity.storage: The amount of storage expressed in Gibibytes (Gi) or Gigabytes (G), see also Kubernetes' own documentation on resource usage.
- spec.accessModes: The mode in which the volume is mounted, see this page for the available options (we only support ReadWriteOnce at this time).
- spec.claimRef: Using a claimRef helps prevent other PVC's from claiming space from a PV, see the last paragraph in this article.
A corresponding PersistentVolumeClaim can be defined as follows:
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: my-pvc spec: storageClassName: transip-fast-storage accessModes: - ReadWriteOnce resources: requests: storage: 3Gi
In these examples, there is a PersistentVolume with 10Gi of storage space and a PersistentVolumeClaim that requests 3Gi from the available 10Gi storage space in this specific PV.
Note: Unless you leave the option empty and use the default value, the storageClassName must match for both the PV and PVC. Otherwise, they cannot bind to each other.
An associated pod can utilize this PVC as follows:
apiVersion: v1 kind: Pod metadata: name: my-pod spec: containers: - name: demo-container image: nginx volumeMounts: - name: my-storage mountPath: /usr/share/nginx/html volumes: - name: my-storage persistentVolumeClaim: claimName: my-pvc
In this example, you simply specify that you want to attach additional disk space to /usr/share/nginx/html and that you want to use the earlier PersistentVolumeClaim named 'my-pvc' (with 3Gi of storage).
Reserving a PersistentVolume
In principle, a PVC automatically uses space in an available PV, or Kubernetes automatically provisions the requested PVC. However, if your use case requires it, you can explicitly indicate which PVC you want to allow using the PV. In the PV, you add a 'claimRef' that specifies the name and (if present) the namespace of the PVC that can use the PV:
claimRef:
name: my-pvc
In the PVC, you add the 'volumeName' option to refer to the specific PV:
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: my-pvc namespace: pvc-example spec: storageClassName: transip-fast-storage volumeName: my-pv ...
This concludes our guide on Persistent Volumes and Persistent Volume Claims. In our block storage tutorial, we demonstrate how to use block storage via a Persistent Volume Claim on your Kubernetes cluster.