Skip to main content

Lab 6.2 - PersistentVolumes and PersistentVolumeClaims

Lab Objectives

By the end of this lab, you will be able to:

  • Create a PersistentVolume (PV) manually.
  • Create a PersistentVolumeClaim (PVC).
  • Bind a PVC to a Pod.
  • Understand the lifecycle of a PV and a PVC.
  • Verify data persistence.

Estimated Duration

45-60 minutes

Prerequisites

  • kubectl installed and configured.
  • Functional local Kubernetes cluster (minikube or kind).
  • Knowledge of PersistentVolumes and PVCs (Chapter 6.2).

Part 1: Creating a PersistentVolume

We will manually create a PersistentVolume. For a local cluster (minikube/kind), we will use a hostPath volume type that mounts a directory from the node.

Step 1.1: Create the PersistentVolume

Create a file pv-example.yaml:

# pv-example.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-example
labels:
type: local
spec:
storageClassName: manual # StorageClass name (or "" for no class)
capacity:
storage: 1Gi # Volume size
accessModes:
- ReadWriteOnce # RWO: a single node can mount in read-write mode
persistentVolumeReclaimPolicy: Retain # What to do when PVC is deleted: Retain, Delete, Recycle
hostPath:
path: /tmp/k8s-pv-example # Path on the node (for minikube/kind)
type: DirectoryOrCreate # Create the directory if it does not exist

Explanation:

  • storageClassName: manual: Indicates this PV is manually provisioned (not by a StorageClass).
  • accessModes: ReadWriteOnce: The volume can be mounted in read-write mode by a single node at a time.
  • persistentVolumeReclaimPolicy: Retain: When the PVC is deleted, the PV is retained (data is not deleted).
  • hostPath: For a local cluster, we use a node directory. In production, you would use cloud volumes (EBS, Azure Disk, GCE Persistent Disk) or NFS.

Apply the PersistentVolume:

kubectl apply -f pv-example.yaml

Verify the PV is created:

kubectl get pv pv-example

You should see the PV with status Available (available, not yet bound to a PVC).

Check the details:

kubectl describe pv pv-example

Part 2: Creating a PersistentVolumeClaim

A PVC requests a volume with specific characteristics (size, access mode, StorageClass).

Step 2.1: Create the PersistentVolumeClaim

Create a file pvc-example.yaml:

# pvc-example.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-example
spec:
storageClassName: manual # Must match the PV's storageClassName
accessModes:
- ReadWriteOnce # Must match or be a subset of the PV's accessModes
resources:
requests:
storage: 500Mi # Requests 500 MiB (the PV has 1 GiB, so it works)

Explanation:

  • storageClassName: manual: The PVC looks for a PV with this StorageClass.
  • accessModes: ReadWriteOnce: The PVC requests a volume with this access mode.
  • resources.requests.storage: 500Mi: The PVC requests at least 500 MiB.

Apply the PersistentVolumeClaim:

kubectl apply -f pvc-example.yaml

Verify the PVC is created and bound to the PV:

kubectl get pvc pvc-example

You should see the PVC with status Bound (bound to the PV).

Verify the PV is now bound:

kubectl get pv pv-example

The status should be Bound and the CLAIM column should show default/pvc-example.


Part 3: Using the PVC in a Pod

Now, we will create a Pod that uses the PVC to store persistent data.

Step 3.1: Create a Pod with the PVC

Create a file pod-with-pvc.yaml:

# pod-with-pvc.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-with-pvc
spec:
containers:
- name: app-container
image: busybox
command: ["/bin/sh", "-c"]
args: ["echo 'Persistent data - $(date)' >> /data/persistent-data.txt && cat /data/persistent-data.txt && sleep 3600"]
volumeMounts:
- name: persistent-storage
mountPath: /data # Path where the volume will be mounted in the container
volumes:
- name: persistent-storage
persistentVolumeClaim:
claimName: pvc-example # Name of the PVC to use

Apply the Pod:

kubectl apply -f pod-with-pvc.yaml

Wait for the Pod to be Running:

kubectl get pods pod-with-pvc

Check the logs to see the written data:

kubectl logs pod-with-pvc

You should see the message with the date.

Step 3.2: Verify Persistence

Delete the Pod:

kubectl delete pod pod-with-pvc

Create a new Pod that reads the data:

# pod-read-pvc.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-read-pvc
spec:
containers:
- name: app-container
image: busybox
command: ["/bin/sh", "-c"]
args: ["cat /data/persistent-data.txt && sleep 3600"]
volumeMounts:
- name: persistent-storage
mountPath: /data
volumes:
- name: persistent-storage
persistentVolumeClaim:
claimName: pvc-example

Apply the new Pod:

kubectl apply -f pod-read-pvc.yaml

Check the logs:

kubectl logs pod-read-pvc

You should see the data written by the first Pod, proving persistence!


Part 4: Cleanup

Delete the created resources:

kubectl delete pod pod-read-pvc
kubectl delete -f pvc-example.yaml
kubectl delete -f pv-example.yaml

Note: With persistentVolumeReclaimPolicy: Retain, even after the PVC is deleted, the PV remains with status Released. The data is preserved. To completely delete the PV, you must delete it manually:

kubectl delete pv pv-example

Lab Summary

In this lab, you explored PersistentVolumes and PersistentVolumeClaims. You learned to manually create a PV, create a PVC that automatically binds to the PV, and use the PVC in a Pod to store persistent data. You also verified that data survives Pod deletion and recreation.


Next Steps

The next lab will introduce you to StorageClasses and dynamic provisioning, which greatly simplify storage management.

Lab 6.3: StorageClasses and Dynamic Provisioning


Lab created: December 2024