5.2 PersistentVolumes (PV) & PersistentVolumeClaims (PVC) Lifecycle

Key Takeaways

  • PersistentVolumes (PVs) are cluster-scoped storage resources provisioned statically by administrators or dynamically by CSI drivers, while PersistentVolumeClaims (PVCs) are namespace-scoped user requests for storage.
  • The PV-PVC lifecycle moves through four sequential stages: Provisioning (Static vs. Dynamic) -> Binding -> Using -> Reclaiming (Retain, Delete, Recycle).
  • A PV progresses through four operational states: Available (unbound), Bound (exclusively linked to a PVC), Released (PVC deleted, storage retained), and Failed (automated reclamation error).
  • Binding is a strict 1-to-1 two-way relationship evaluated by persistentvolume-controller based on capacity (PV >= PVC), accessModes, volumeMode, storageClassName, and label selectors.
  • volumeMode determines whether storage is presented as a formatted filesystem (volumeMode: Filesystem mounted via volumeMounts) or a raw block device (volumeMode: Block mapped via volumeDevices).
Last updated: August 2026

5.2 PersistentVolumes (PV) & PersistentVolumeClaims (PVC) Lifecycle

Managing persistent state in a containerized, distributed orchestration platform requires abstracting the underlying storage implementation details from application developers. In traditional on-premise or cloud environments, configuring storage arrays (such as iSCSI LUNs, NFS shares, AWS EBS volumes, or Ceph RBD pools) requires infrastructure-level privileges and vendor-specific configuration. Exposing these low-level parameters directly inside application Pod manifests breaks workload portability and violates the principle of least privilege.

Kubernetes solves this decoupling challenge through two core API primitives: the PersistentVolume (PV) and the PersistentVolumeClaim (PVC). This architectural separation enforces a strict division of responsibilities: cluster administrators manage the provisioned storage capacity (PVs), while application developers consume storage via declarative requests (PVCs) without needing knowledge of the backing storage fabric.


1. The Storage Abstraction Architecture & Persona Separation

+-----------------------------------------------------------------------------------------+
|                                    CLUSTER SCOPE                                        |
|                                                                                         |
|  +-----------------------------+                 +-----------------------------------+  |
|  |    STORAGE ADMINISTRATOR    |                 |      PersistentVolume (PV)        |  |
|  |  - Provisions SAN/NFS/Cloud |  ------------>  |  - Capacity: 50Gi                 |  |
|  |  - Defines Access Modes     |                 |  - AccessMode: ReadWriteOnce      |  |
|  |  - Reclaim Policy: Retain   |                 |  - ReclaimPolicy: Retain          |  |
|  +-----------------------------+                 +-----------------+-----------------+  |
|                                                                    |                    |
|====================================================================|====================|
|                          NAMESPACE SCOPE: production               | (1-to-1 Binding)   |
|                                                                    v                    |
|  +-----------------------------+                 +-----------------+-----------------+  |
|  |    APPLICATION DEVELOPER    |                 |   PersistentVolumeClaim (PVC)     |  |
|  |  - Requests: 30Gi RWO       |  ------------>  |  - Request: 30Gi                  |  |
|  |  - References StorageClass  |                 |  - AccessMode: ReadWriteOnce      |  |
|  +-----------------------------+                 +-----------------+-----------------+  |
|                                                                    |                    |
|                                                                    | spec.volumes.pvc   |
|                                                                    v                    |
|                                                  +-----------------+-----------------+  |
|                                                  |          WORKLOAD POD             |  |
|                                                  |  Mounts to /var/lib/postgresql    |  |
|                                                  +-----------------------------------+  |
+-----------------------------------------------------------------------------------------+

Architectural Distinction: PV vs. PVC

AttributePersistentVolume (PV)PersistentVolumeClaim (PVC)
API ScopeCluster-scoped (kubectl get pv)Namespace-scoped (kubectl get pvc -n <ns>)
Target PersonaInfrastructure / Cluster AdministratorApplication Developer / Tenant
Core PurposeRepresents actual physical/virtual storageRepresents an abstract storage resource request
Binding CardinalityBound to exactly one PVC (spec.claimRef)Bound to exactly one PV (spec.volumeName)
Lifecycle DependencyIndependent of any Pod or NamespaceBound to user lifecycle; triggers PV reclamation

2. Complete 4-Phase PV & PVC Lifecycle

The interaction between PersistentVolumes and PersistentVolumeClaims is orchestrated by the control plane's persistentvolume-controller through four sequential phases:

1. Provisioning $\longrightarrow$ 2. Binding $\longrightarrow$ 3. Using $\longrightarrow$ 4. Reclaiming

Phase 1: Provisioning (Static vs. Dynamic)

  • Static Provisioning: A cluster administrator manually provisions physical storage devices (e.g., creating an NFS export or Ceph volume) and submits declarative PersistentVolume manifests to the Kubernetes API server.
  • Dynamic Provisioning: When no pre-existing static PV matches a user's PVC, the cluster automatically triggers a Container Storage Interface (CSI) provisioner via a StorageClass to create the backend storage asset and instantiate a corresponding PV object on the fly.

Phase 2: Binding

The persistentvolume-controller continuously watches for unbound PVCs and executes an evaluation algorithm to find the optimal matching PV.

  • When a match is found, the controller executes an exclusive two-way mutual binding:
    • In the PV: Sets spec.claimRef to the PVC's UID, name, and namespace.
    • In the PVC: Sets spec.volumeName to the PV name and transitions status to Bound.
  • If no matching PV exists and dynamic provisioning is disabled, the PVC remains indefinitely in Pending status.

Phase 3: Using

The application developer references the PVC in a Pod manifest under spec.volumes[*].persistentVolumeClaim.claimName.

  • The scheduler places the Pod on an eligible node.
  • The local kubelet and CSI Node Plugin attach the storage device, format it (if filesystem mode), and bind-mount it into the container's designated mountPath.

Phase 4: Reclaiming

When the application is decommissioned and the user deletes the PVC, the bound PV enters the reclamation phase dictated by its persistentVolumeReclaimPolicy:

  • Retain: PV status transitions to Released. The underlying data on disk is preserved. The PV cannot be claimed by any other PVC until an administrator manually clears spec.claimRef.
  • Delete: The PV object is automatically deleted from Kubernetes, and the CSI driver calls the underlying storage provider API to destroy the physical storage volume.
  • Recycle (Deprecated): Runs a basic scrubbing command (rm -rf /mount/*) and returns the PV to Available.

3. PV Operational Status State Transitions

   [ Admin Manifest / CSI Provisioning ]
                     |
                     v
            +------------------+
            |    AVAILABLE     | <-------------------------+
            +--------+---------+                           |
                     |                                     |
                     | PVC matches criteria                | Admin cleans data
                     v                                     | & patches claimRef
            +------------------+                           |
            |      BOUND       |                           |
            +--------+---------+                           |
                     |                                     |
                     | User deletes PVC                    |
                     v                                     |
            +------------------+   Manual Reclaim          |
            |     RELEASED     | --------------------------+
            +--------+---------+
                     |
                     | Automated deletion error (CSI)
                     v
            +------------------+
            |      FAILED      |
            +------------------+
PV StatusTechnical Definition & System State
AvailableThe PV is free, healthy, and ready to be claimed by any matching PVC in any namespace.
BoundThe PV is exclusively locked and bound to a specific PVC. No other claim can bind to it.
ReleasedThe associated PVC has been deleted, but the physical resource has not yet been reclaimed. Data is intact.
FailedThe automated reclamation or deletion process failed (e.g., cloud API credentials expired or disk locked).

4. The 5-Point PVC-to-PV Binding Evaluation Algorithm

For persistentvolume-controller to bind an incoming PVC to a static PV, all five of the following evaluation criteria must pass simultaneously:

  1. Storage Capacity: The PV capacity must be greater than or equal to the PVC requested storage (pv.spec.capacity.storage >= pvc.spec.resources.requests.storage). (Note: If a PVC requests 10Gi and the smallest available PV is 100Gi, Kubernetes will bind it, resulting in 90Gi of unallocated capacity).
  2. Access Modes: The PV must satisfy all access modes declared in pvc.spec.accessModes (e.g., ReadWriteOnce, ReadWriteMany).
  3. Volume Mode: spec.volumeMode must match identically (Filesystem with Filesystem, or Block with Block).
  4. StorageClass: pvc.spec.storageClassName must match pv.spec.storageClassName. If a PVC specifies storageClassName: "", it will only bind to PVs that explicitly declare storageClassName: "" or omit the field.
  5. Label Selectors: If the PVC specifies spec.selector.matchLabels or matchExpressions, the PV's metadata.labels must satisfy the selector.

5. Declarative Manifests: Filesystem vs. Raw Block Storage

Static PersistentVolume (Filesystem Mode)

apiVersion: v1
kind: PersistentVolume
metadata:
  name: enterprise-nfs-pv
  labels:
    environment: production
    tier: db
spec:
  capacity:
    storage: 50Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: manual
  nfs:
    server: 10.96.15.200
    path: /srv/nfs/pgdata

PersistentVolumeClaim

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: postgres-data-pvc
  namespace: production
spec:
  accessModes:
    - ReadWriteOnce
  volumeMode: Filesystem
  resources:
    requests:
      storage: 50Gi
  storageClassName: manual
  selector:
    matchLabels:
      environment: production
      tier: db

Raw Block Volume (volumeMode: Block)

High-throughput databases (e.g., Cassandra, RocksDB, or custom key-value engines) often bypass the Linux filesystem layer to eliminate filesystem journaling overhead:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: raw-block-pvc
  namespace: production
spec:
  accessModes:
    - ReadWriteOnce
  volumeMode: Block
  resources:
    requests:
      storage: 100Gi
  storageClassName: manual
---
apiVersion: v1
kind: Pod
metadata:
  name: raw-db-pod
  namespace: production
spec:
  containers:
  - name: db-engine
    image: custom-db:v2.4
    volumeDevices:
    - name: raw-storage-device
      devicePath: /dev/xvdf
  volumes:
  - name: raw-storage-device
    persistentVolumeClaim:
      claimName: raw-block-pvc

[!NOTE] When consuming a raw block volume (volumeMode: Block), you must declare volumeDevices with devicePath instead of volumeMounts with mountPath.


6. Verification & Troubleshooting CLI Playbook

# 1. List all PVs cluster-wide and check claim references
kubectl get pv -o wide

# 2. List PVCs in a target namespace
kubectl get pvc -n production

# 3. Diagnose why a PVC is stuck in Pending status
kubectl describe pvc postgres-data-pvc -n production

# 4. Check if PV claimRef is locking a Released volume
kubectl get pv enterprise-nfs-pv -o jsonpath='{.spec.claimRef}'
Loading diagram...
PersistentVolume and PersistentVolumeClaim Binding and Lifecycle Sequence
Test Your Knowledge

A PersistentVolume provisioned with persistentVolumeReclaimPolicy: Retain is bound to a PVC named data-pvc in the finance namespace. A developer deletes data-pvc. What will be the resulting status of the PV, and can another PVC immediately bind to it?

A
B
C
D
Test Your Knowledge

A developer submits a PVC requesting 20Gi of storage with accessModes: [ReadWriteMany] and storageClassName: manual. The cluster has an available static PV with capacity: 100Gi, accessModes: [ReadWriteOnce], and storageClassName: manual. Why does the PVC remain stuck in Pending status?

A
B
C
D
Test Your Knowledge

An administrator is configuring a low-latency Cassandra database that requires raw block storage access (volumeMode: Block). How must the container inside the Pod manifest reference this volume?

A
B
C
D