Kubernetes Persistent Volume, PVC for Pod

 

Note: This example uses a bare Pod and not a Deployment. In real world production you would use deployment which manages the pod for you.  See the separate Deployment example for that.

Overview

The flow is always:

PV (admin creates storage) → PVC (app claims storage) → Pod (uses the storage)
 Bare PodDeployment
Who manages the podNobody — we do it manuallyDeployment controller
Update volumesDelete and recreate pod manuallykubectl apply and it recreates automatically
Used inLearning / course exercisesReal world / production

References

Step 1 — Create the Persistent Volume (PV)

pv-nginx-data.yml

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-nginx-data
  labels:
    type: local
spec:
  storageClassName: local-path
  capacity:
    storage: 100Mi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: "/data"
kubectl apply -f pv-nginx-data.yml
kubectl get pv

Step 2 — Create the Persistent Volume Claim (PVC)

nginx-data-pvc.yml

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nginx-data-pvc
spec:
  accessModes:
    - ReadWriteOnce
  volumeMode: Filesystem
  resources:
    requests:
      storage: 100Mi
  storageClassName: local-path
kubectl apply -f nginx-data-pvc.yml
kubectl get pvc

Step 3 — Create the Pod

deploy.yaml

apiVersion: v1
kind: Pod
metadata:
  labels:
    run: pod
  name: nginx-app
spec:
  volumes:
    - name: nginx-data
      persistentVolumeClaim:
        claimName: nginx-data-pvc
  containers:
    - name: nginx-app
      image: nginx
      volumeMounts:
        - mountPath: "/nginx-data"
          name: nginx-data
kubectl apply -f deploy.yaml
kubectl get pods

Verify Everything

kubectl get pv
kubectl get pvc
kubectl get pods

Expected output:

NAME            STATUS   VOLUME          CAPACITY   ACCESS MODES   STORAGECLASS
nginx-data-pvc  Bound    pv-nginx-data   100Mi      RWO            local-path

NAME        READY   STATUS    RESTARTS   AGE
nginx-app   1/1     Running   0          30s

Key Points

 PVPVC
Created byAdminDeveloper/App
DefinesActual storageRequest for storage
Storage sizecapacity.storageresources.requests.storage
Names must matchstorageClassNamestorageClassName
  • The name in volumes and volumeMounts inside the pod spec must match
  • claimName in the pod spec must match the PVC metadata.name

K3s automatically creates the PV and stores data at:

/var/lib/rancher/k3s/storage/pvc-<uid>/

To bind a PVC to a specific PV, use labels and selectors:

PV — add a unique label:

yaml

metadata:
  name: pv-nginx-data
  labels:
    pv: pv-nginx-data   # ← can be any key/value, just make it unique

PVC — add a selector to match:

yaml

spec:
  selector:
    matchLabels:
      pv: pv-nginx-data  # ← must match the PV label

This ensures the PVC only ever binds to that exact PV.

(Visited 7 times, 1 visits today)

By Ash Thomas

Ash Thomas is a seasoned IT professional with extensive experience as a technical expert, complemented by a keen interest in blockchain technology.