Kubernetes Persistent Volume Practical - Hands-on PV & PVC Tutorial

Comprehensive hands-on tutorial for Kubernetes Persistent Volumes covering PV & PVC configuration, data persistence testing, kubectl commands, YAML examples, storage classes, and practical data persistence verification with BusyBox containers

Persistent Volume Example

Download the YAML configuration files for the Persistent Volume example

Create the Persistent Volume

kubectl apply -f pv.yaml

Creates a Persistent Volume with the configuration from pv.yaml.

Look at the PV

kubectl get pv

Displays the Persistent Volumes in the cluster.

Deploy the Claim

kubectl apply -f pvc.yaml

Creates a Persistent Volume Claim with the configuration from pvc.yaml.

Look at the PVC

kubectl get pvc

Displays the Persistent Volume Claims in the cluster.

Deploy the Pod

kubectl apply -f pod.yaml

Creates a Pod that uses the Persistent Volume Claim.

Connect to the Busybox Instance

kubectl exec mybox -it -- /bin/sh

Opens a shell inside the running Busybox container.

Create a File

cd demo
cat > hello.txt
Hello World
Enter and Ctrl-D
ls
exit

Creates a file in the mounted volume to test persistence.

Delete the Pod

kubectl delete -f pod.yaml --force --grace-period=0

Deletes the pod to test if the file persists.

Deploy the Pod Again

kubectl apply -f pod.yaml

Recreates the pod to verify persistence.

Connect and Verify

kubectl exec mybox -it -- /bin/sh
cd demo
ls
cat hello.txt
exit

Verifies that the file still exists after pod recreation.

Cleanup

kubectl delete -f pod.yaml --force --grace-period=0
kubectl delete -f pvc.yaml
kubectl delete -f pv.yaml

Deletes all resources created during this exercise.

YAML Configuration Files

pv.yaml

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv001
  labels:
    type: local
spec:
  storageClassName: ssd 
  capacity:
    storage: 10Mi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  hostPath:
    path: "/data/"

Persistent Volume Explanation:

Basic Structure:
  • apiVersion: v1 → Kubernetes API version
  • kind: PersistentVolume → Defines a Persistent Volume resource
  • metadata.name: pv001 → Names the PV "pv001"
Specification:
  • storageClassName: ssd → Defines a storage class for dynamic provisioning
  • capacity.storage: 10Mi → Allocates 10 MiB of storage
  • volumeMode: Filesystem → Volume will be mounted as a directory
  • accessModes: ReadWriteOnce → Can be mounted as read-write by a single node
  • persistentVolumeReclaimPolicy: Retain → PV will be retained after PVC deletion
  • hostPath.path: "/data/" → Uses a directory on the host node for storage

pvc.yaml

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: myclaim
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Mi
  storageClassName: ssd

Persistent Volume Claim Explanation:

Basic Structure:
  • apiVersion: v1 → Kubernetes API version
  • kind: PersistentVolumeClaim → Defines a Persistent Volume Claim resource
  • metadata.name: myclaim → Names the PVC "myclaim"
Specification:
  • accessModes: ReadWriteOnce → Requests read-write access by a single node
  • resources.requests.storage: 10Mi → Requests 10 MiB of storage
  • storageClassName: ssd → Requests storage from the "ssd" storage class
  • The PVC will bind to the PV that matches these requirements

pod.yaml

apiVersion: v1
kind: Pod
metadata:
  name: mybox
spec:
  restartPolicy: Always
  containers:
  - name: mybox
    image: busybox
    resources:
      requests:
        cpu: 100m
        memory: 128Mi
      limits:
        cpu: 250m
        memory: 256Mi    
    command:
      - sleep
      - "3600"
    volumeMounts:
      - mountPath: "/demo/"
        name: mypd
  volumes:
    - name: mypd
      persistentVolumeClaim:
        claimName: myclaim

Pod Explanation:

Basic Structure:
  • apiVersion: v1 → Kubernetes API version
  • kind: Pod → Defines a Pod resource
  • metadata.name: mybox → Names the pod "mybox"
Pod Specification:
  • restartPolicy: Always → Pod will be restarted if it fails
  • containers.name: mybox → Names the container "mybox"
  • image: busybox → Uses the lightweight BusyBox image
Resources:
  • requests.cpu: 100m → Requests 0.1 CPU cores
  • requests.memory: 128Mi → Requests 128 MiB of memory
  • limits.cpu: 250m → Limits to 0.25 CPU cores
  • limits.memory: 256Mi → Limits to 256 MiB of memory
Volume Configuration:
  • command: sleep "3600" → Keeps the container running for 1 hour
  • volumeMounts.mountPath: "/demo/" → Mounts the volume at /demo/ in the container
  • volumes.name: mypd → Names the volume "mypd"
  • persistentVolumeClaim.claimName: myclaim → Uses the PVC named "myclaim"