Persistent Volume Claims (PVC)

A PersistentVolumeClaim (PVC) is how a Pod requests storage from the cluster. The developer specifies how much storage they need and what access mode is required; Kubernetes finds a matching PersistentVolume and binds the PVC to it. The developer does not need to know whether the storage is backed by NFS, a cloud disk, or a local directory — they just request storage and mount it. This separation of concerns is the design intent: administrators manage PVs, developers consume PVCs.

What is a PVC?

PVC binding process:

  Developer creates PVC:
    "I need 5Gi of ReadWriteOnce storage, storageClass=standard"
                    |
                    v
  Kubernetes control plane searches for matching PV:
    - capacity >= 5Gi
    - accessMode = ReadWriteOnce
    - storageClass = standard
                    |
         match found? yes
                    |
                    v
  PVC STATUS: Bound  ←→  PV STATUS: Bound
  (they are now exclusively linked)
                    |
                    v
  Pod mounts PVC as a volume

Creating a PVC

nano mysql-pvc.yaml

mysql-pvc.yaml

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-pvc
  namespace: default
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi
  storageClassName: local-path    # Use k3s default, or "standard" on cloud
kubectl apply -f mysql-pvc.yaml

# Check PVC status:
kubectl get pvc

kubectl get pvc output

NAME        STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
mysql-pvc   Bound    pvc-4a2b8c1d-e3f4-5678-abcd-ef1234567890   10Gi       RWO            local-path     15s
# STATUS = Bound means a PV was found and allocated
# If STATUS = Pending, either:
# - No matching PV exists (and no StorageClass for dynamic provisioning)
# - No StorageClass matches the requested storageClassName
# Debug:
kubectl describe pvc mysql-pvc    # Shows events explaining why it is Pending

Using a PVC in a Pod

nano mysql-deployment.yaml

mysql-deployment.yaml — using the PVC

apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql
spec:
  replicas: 1    # Only 1 replica for RWO volumes (one node can mount at a time)
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
        - name: mysql
          image: mysql:8.0
          env:
            - name: MYSQL_ROOT_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: mysql-secret
                  key: password
          volumeMounts:
            - name: mysql-storage
              mountPath: /var/lib/mysql    # MySQL data directory
      volumes:
        - name: mysql-storage
          persistentVolumeClaim:
            claimName: mysql-pvc           # Reference the PVC by name

StatefulSets and PVCs

# StatefulSets automatically create PVCs per replica using volumeClaimTemplates:
# (Used for databases, Kafka, Elasticsearch — anything that needs unique storage per replica)
nano mysql-statefulset.yaml

mysql-statefulset.yaml — automatic PVC per replica

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mysql-cluster
spec:
  replicas: 3
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
        - name: mysql
          image: mysql:8.0
          volumeMounts:
            - name: data
              mountPath: /var/lib/mysql
  volumeClaimTemplates:
    - metadata:
        name: data
      spec:
        accessModes: ["ReadWriteOnce"]
        resources:
          requests:
            storage: 10Gi
# Creates: data-mysql-cluster-0, data-mysql-cluster-1, data-mysql-cluster-2
# Each replica gets its own dedicated PVC

Conclusion

For stateless applications, use regular Deployments with a single PVC. For stateful applications that need unique storage per replica (databases, message queues), use StatefulSets with volumeClaimTemplates — they automatically create and manage one PVC per Pod. Never run a database with replicas: 3 on an RWO PVC; all three replicas would fight over the same volume (only one can mount it). Either use RWX storage or use a StatefulSet with separate PVCs per replica.

FAQ

Is Persistent Volume Claims (PVC) important for Ubuntu administrators?+

Yes. It supports practical Ubuntu administration because it connects directly to server reliability, security, troubleshooting, or daily operations.

Should I practice this on a live server?+

Use a lab VM first. After you understand the command output and rollback path, apply the workflow carefully on real systems.

What should I do after reading this article?+

Run the practice commands, write down what each one shows, and continue to the next article in the Ubuntu roadmap.

Need help with Ubuntu administration?

Work directly with Muhammad Irfan Aslam for Ubuntu Server, Linux, cloud, Docker, DevOps, CI/CD, or infrastructure troubleshooting support.

Hire Me for Support