Kuber­netes Per­sist­ent Volumes (PVs) play a crucial role in the efficient man­age­ment of data in Kuber­netes clusters. They abstract data and allow con­sist­ent storage over the li­fe­cycles of pods.

What is a Kuber­netes Per­sist­ent Volume?

A Kuber­netes Per­sist­ent Volume (PV) is a fun­da­ment­al resource within the Kuber­netes or­ches­tra­tion, designed for efficient and scalable man­age­ment of data in container clusters. The purpose of a PV is to provide a stand­ard­ised and per­sist­ent storage area. A PV can be used by different pods, re­gard­less of which physical storage resources the cluster accesses. This creates a higher level of ab­strac­tion by sep­ar­at­ing the storage details from the ap­plic­a­tion logic.

PVs come in static and dynamic forms. Static pro­vi­sion­ing means that storage resources are manually pre­defined, while dynamic pro­vi­sion­ing means that PVs are auto­mat­ic­ally created when a pod has specific storage re­quire­ments. This flex­ib­il­ity ensures efficient man­age­ment of per­sist­ent data in Kuber­netes clusters, making ap­plic­a­tions robust and scalable.

Tip

Managed Kuber­netes from IONOS auto­mat­ic­ally sets up Kuber­netes clusters for you on high-per­form­ance virtual servers. Thanks to the flexible con­fig­ur­a­tion of the worker nodes, you can adapt resources precisely to your needs. Use SDKs and config man­age­ment tools for smooth in­teg­ra­tion and optimised operation.

What’s the dif­fer­ence between volume und per­sist­ent volume?

There are two basic types of storage volumes in Kuber­netes: volumes and per­sist­ent volumes. A normal volume is bound to the lifetime of a single pod. It’s declared directly in the pod con­fig­ur­a­tion and is mainly used for temporary data storage during the execution of the as­so­ci­ated pod. When the pod is ter­min­ated, the normal volume is also released and all the data it contains is deleted.

In contrast, a Kuber­netes Per­sist­ent Volume has a longer lifetime and is in­de­pend­ent of a specific pod. It can be claimed and released by multiple pods in different li­fe­cycles. Per­sist­ent volumes are declared sep­ar­ately from the pods and then bound to Per­sist­ent Volume Claims (PVCs). The binding between a PVC and a PV is done dy­nam­ic­ally or manually. Per­sist­ent volumes are ideal for data that needs to last beyond the lifetime of a single pod and provide a way to share and store data between different pods, even if pods are created or deleted.

What types of per­sist­ent volumes are there?

In Kuber­netes, there are different types of per­sist­ent volumes that represent different storage solutions and tech­no­lo­gies. Here are some of the most common types of per­sist­ent volumes:

  • hostPath: The hostPath type binds a per­sist­ent volume to a path on the host node in the Kuber­netes cluster. This allows access to local storage resources of the host and is well suited to de­vel­op­ment and test en­vir­on­ments. However, it should be used with caution in pro­duc­tion en­vir­on­ments as the data is not rep­lic­ated between the nodes.
  • emptyDir: emptyDir creates a temporary and idle volume each time a pod is created. It’s suitable for temporary data or data exchange between con­tain­ers within the same pod. However, the volume is deleted when the pod is ter­min­ated.
  • GCEPersistentDisk, AWSElasticBlockStore, AzureDisk, AzureFile: These types bind a Kuber­netes Per­sist­ent Volume to external cloud storage solutions such as Google Compute Engine Per­sist­ent Disks, Amazon EBS Volumes, or Azure Disks and Azure File Shares. They provide a way to persist data across pods and even clusters and are well suited to ap­plic­a­tions deployed in cloud en­vir­on­ments.
  • nfs (Network File System): NFS-type PVs bind to a network share that is made available via the Network File System (NFS). This allows data to be shared between different pods and is useful when multiple pods need to access shared files.
  • iscsi (Internet Small Computer System Interface): ISCSI-based PVs bind to block storage devices that are available via the ISCSI protocol. It’s a way to utilise external block storage devices in Kuber­netes clusters and provides a flexible and scalable solution for per­sist­ent data.
  • local: The local type enables direct access to physical storage resources on the local node in the Kuber­netes cluster. This is par­tic­u­larly useful for ap­plic­a­tions that rely on fast local storage. However, you should exercise caution as local storage resources are not rep­lic­ated between the nodes and data may be lost if the node fails.
  • csi (Container Storage Interface): The CSI type allows external storage providers to be in­teg­rated via the Container Storage Interface. Container or­ches­tra­tion systems such as Kuber­netes can thus com­mu­nic­ate with various third-party storage solutions. This creates flex­ib­il­ity and allows the use of a wide range of storage systems that support the CSI.
  • cephfs: CephFS is a dis­trib­uted file system and per­sist­ent volumes of type CephFS are bound to this dis­trib­uted file system. This type of PV is used for ap­plic­a­tions that require shared file access and are operated in a dis­trib­uted storage en­vir­on­ment, as is the case with Ceph.
  • fc (Fibre Channel): FC-based per­sist­ent volumes are bound to Fibre Channel storage devices. This type allows you to access external Fibre Channel-based storage solutions. It’s common in en­vir­on­ments where Fibre Channel networks are used to provide block-based storage.
  • rbd (RADOS Block Device): The RBD type binds to block-based storage devices in the Ceph cluster that act as RADOS Block Devices. This type allows you to access the block-based storage system of Ceph, which is par­tic­u­larly ad­vant­age­ous in dis­trib­uted storage en­vir­on­ments with high scalab­il­ity.

Kuber­netes Per­sist­ent Volume Access Modes

In Kuber­netes, Per­sist­ent Volume Access Modes determine how pods can access the per­sist­ent volumes bound to them. There are three main types of access modes:

  • ReadWriteOnce (RWO): This mode allows a single pod to mount the per­sist­ent volume in read and write mode sim­ul­tan­eously. It’s useful for ap­plic­a­tions that require exclusive write access control. A PV with this mode can only be mounted by one pod at a time.
  • ReadOnlyMany (ROX): ReadOnlyMany allows multiple pods to mount the per­sist­ent volume sim­ul­tan­eously in read-only mode. This is useful for ap­plic­a­tions that can share data in a common mode, but where write access is re­stric­ted. Multiple pods can access the data in parallel but only in read-only mode.
  • ReadWriteMany (RWX): With ReadWriteMany, multiple pods can mount the per­sist­ent volume sim­ul­tan­eously in both read and write access mode. This mode is used in situ­ations where a shared database is required and where multiple pods can have write access to the data.

When defining the access mode, you should consider the type of data access your ap­plic­a­tion requires and check that the selected mode supports the required access patterns.

Please note that not all storage classes and volume types support all three access modes. The support depends on the un­der­ly­ing storage in­fra­struc­ture and the specific per­sist­ent volume type. Therefore, it’s advisable to check the doc­u­ment­a­tion of the re­spect­ive storage class and per­sist­ent volume type to make sure that the access patterns you want are permitted.

The lifecycle of a per­sist­ent volume (PV)

The li­fe­cycles of Kuber­netes Per­sist­ent Volumes can be divided into different phases that represent the process of pro­vi­sion­ing, using and releasing per­sist­ent storage in the cluster.

  1. Pro­vi­sion­ing : The lifecycle of a PV begins with creation or pro­vi­sion­ing. A cluster ad­min­is­trat­or creates a per­sist­ent volume and con­fig­ures it either stat­ic­ally with fixed storage resources or dy­nam­ic­ally by using a storage class that enables dynamic pro­vi­sion­ing.
  2. Binding: A PV is bound to a PVC (Per­sist­ent Volume Claim) when a pod declares a storage re­quire­ment that matches the PV’s spe­cific­a­tions. This step ensures that the PV meets the re­quire­ments of a specific pod.
  3. Usage by the pod: After the binding process is complete, the PV can be used by a pod. The pod can read or write to the mounted volume, depending on the access modes set during PV creation.
  4. Ex­pir­a­tion of use: When a pod ends its service or is deleted, the as­so­ci­ated PV can be reused by another pod. The PV is retained until it is deleted manually or by a dynamic storage class.
  5. Release: A PV can be ex­pli­citly released by dis­con­nect­ing it from a PVC. This allows the PV to be re-bonded, possibly from another PVC or pod.
  6. Delete: Finally, you can also delete a PV if it’s no longer required. This can be done manually or auto­mat­ic­ally if PV rep­lic­a­tion is set by the storage class.

How to create a Kuber­netes Per­sist­ent Volume

Creating a per­sist­ent volume in Kuber­netes is a multi-stage process that requires careful con­fig­ur­a­tion.

Step 1: Con­fig­ur­ing the per­sist­ent volume

The first step involves opening a text editor and creating a YAML file that contains the con­fig­ur­a­tion of the Kuber­netes Per­sist­ent Volumes. You could name this file pv.yaml, for instance. Below, we give you a simple example of a PV con­fig­ur­a­tion:

apiVersion: v1
kind: PersistentVolume
metadata:
    name: my-pv
spec:
    capacity:
        storage: 1Gi
    volumeMode: Filesystem
    accessModes:
        - ReadWriteOnce
    persistentVolumeReclaimPolicy: Retain
    storageClassName: manual
    hostPath:
        path: "/mnt/data"
yaml
  • apiVersion: Specifies the Kuber­netes API version. Here it’s v1.
  • kind: The type of the Kuber­netes object, in this case Per­sist­ent­Volume.
  • metadata: Contains metadata for the per­sist­ent volume, for example the name of the volume. spec: Defines the spe­cific­a­tion of the volume.
  • capacity: Specifies the storage capacity, in this example 1 GB.
  • volumeMode: The mode for the volume is specified here, either Filesystem or Block. In this example, we use Filesystem.
  • accessModes: Defines the access modes. Here ReadWriteOnce stands for exclusive read and write access.
  • persistentVolumeReclaimPolicy: Specifies how the volume should be handled when it’s no longer required. Retain means that the volume must be deleted manually.
  • storageClassName: Assigns a storage class to the per­sist­ent volume.
  • hostPath: Defines the path in the host file system that’s used as storage for the per­sist­ent volume.

Step 2: Applying the con­fig­ur­a­tion

Once you have described the PV con­fig­ur­a­tion file, you can activate it with Kubelet:

kubectl apply -f pv.yaml
shell

This command sends the con­fig­ur­a­tion file to the Kuber­netes cluster, which creates the resources it contains.

Step 3: Checking the con­fig­ur­a­tion

To make sure that the Kuber­netes Per­sist­ent Volume has been suc­cess­fully created, you can use the following command:

kubectl get pv
shell

This lists all existing per­sist­ent volumes in the cluster.

NAME   CAPACITY  ACCESS MODES  RECLAIM POLICY  STATUS  CLAIM  STORAGECLASS  REASON  AGE
my-pv    1Gi          RWX          Retain     Available           manual             1h
shell

Step 4: Creating a Per­sist­ent Volume Claim (PVC)

Fill a YAML file that defines the con­fig­ur­a­tion of the Per­sist­ent Volume Claim:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
    name: my-pvc
spec:
    accessModes:
        - ReadWriteOnce
    resources:
        requests:
            storage: 1Gi
    storageClassName: manual
yaml

Apply the PVC con­fig­ur­a­tion file to the Kuber­netes cluster:

kubectl apply -f pvc.yaml
shell

To check if the Per­sist­ent Volume Claim has been suc­cess­fully created, use the following command:

kubectl get pvc
shell

The output should look similar to this:

NAME      STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
my-pvc     Bound    my-pv     1Gi           RWO          manual       1m
shell

Now we create the YAML manifest pvc-dynamic.yaml to demon­strate the dynamic pro­vi­sion­ing of a Per­sist­ent Volume Claim (PVC) in Kuber­netes. The manifest auto­mat­ic­ally creates and claims a new Kuber­netes Per­sist­ent Volume with a size of 1 gigabyte, which is supported by the storage class standard.

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
    name: pvc-dynamic
spec:
    accessModes:
        - ReadWriteOnce
    resources:
        requests:
            storage: 1Gi
    storageClassName: standard
yaml

Once the con­fig­ur­a­tions have been defined, we activate the manifest:

kubectl apply -f pvc-dynamic.yaml
shell

Step 5: Attaching PVCs to pods

To pair the PVC with the pod, you need to set up the con­fig­ur­a­tion for the pod that will use the per­sist­ent storage.

apiVersion: v1
kind: Pod
metadata:
    name: mypod
spec:
    volumes:
    - name: mypvc-volume
        persistentVolumeClaim:
            claimName: my-pvc
    containers:
    - name: mycontainer
        image: myimage
        volumeMounts:
        - mountPath: "/app/data"
            name: mypvc-volume
yaml

Apply the pod con­fig­ur­a­tion to the Kuber­netes cluster to create the pod:

kubectl apply -f pod.yaml
shell

If you’re just getting started with Kuber­netes, you’ll find everything you need to know about in­stalling and setting up a cluster in the Kuber­netes tutorial in our guide.

IONOS Cloud Managed Kuber­netes
Container workloads in expert hands

The ideal platform for demanding, highly scalable container ap­plic­a­tions. Managed Kuber­netes works with many cloud-native solutions and includes 24/7 expert support.

Go to Main Menu