Kubernetes - Volumes - Part-2
Understanding PVs, PVCs, and Kubernetes Storage Classes

👋 The "Node-Lock" Problem
That "node-lock" is the biggest weakness of hostPath. If the node goes down or the Pod moves, the data is essentially "trapped" on the old node.
To solve this, Kubernetes uses a system that decouples the storage from the node entirely, often using network storage (like a cloud disk). This brings us to the "Gold Standard" of Kubernetes storage: PersistentVolumes (PV) and PersistentVolumeClaims (PVC).
Persistent Volumes(PV) and Persistent Volumes Claim (PVC)
The What ?
Persistent Volumes (PV):
A Persistent Volume (PV) represents a piece of storage provisioned in the cluster often backed by network or cloud storage that continues to exist even if Pods are deleted or moved.
You can think of a PV as block storage or file storage attached to the Kubernetes cluster, where the cluster has full control to allocate this storage to incoming requests.
Since this storage lives outside the Kubernetes cluster environment (for example, cloud disks or network-attached storage), it is not affected by Pod restarts, node failures, or most Kubernetes-level failures.
Persistent Volumes Claim (PVC):
A Persistent Volume Claim (PVC) is a request for storage made by an application running inside the Kubernetes cluster.
Instead of directly attaching a storage disk, a Pod asks for storage by specifying:
How much space it needs
The type of access required (read/write)
The storage characteristics it expects
Kubernetes then looks for a suitable Persistent Volume (PV) that matches this request and binds it to the PVC.
You can think of a PVC as an interface between your application and the actual storage, allowing Pods to use persistent storage without needing to know where or how it is physically provisioned.
❓ Why PVC request is needed ?
PVCs introduce a clean separation between applications and storage.
Different applications have very different storage needs:
Databases need high I/O and low latency
Logs or backups can work with lower-performance storage
Instead of hard-coding storage details into applications, a PVC allows the app to simply say: “I need this much storage, with this access pattern.” Kubernetes then fulfills that request by binding the PVC to an appropriate PV.
This approach keeps applications portable, flexible, and storage-agnostic, while allowing storage performance to be controlled through PVC requests.
Here is a quick look at how they connect:
Pod points to → PVC
PVC binds to → PV
PV points to → Actual Disk
Each layer has a clear responsibility, and none of them need to know the internal details of the others.
🔐 Access Modes
Both Persistent Volumes (PV) and Persistent Volume Claims (PVC) define something called access modes. Access modes describe how a volume can be accessed by Pods for example, whether it can be mounted as read-only, read-write, or shared across multiple nodes. The available access modes are explained below
ReadWriteOnce (RWO): The volume can be mounted as read-write by a single node. (Like a USB drive plugged into one laptop).
ReadOnlyMany (ROX): The volume can be mounted read-only by many nodes. (Like a shared CD-ROM).
ReadWriteMany (RWX): The volume can be mounted as read-write by many nodes. (Like a shared network folder/Dropbox).
When you provision PV and PVC for a highly available application that runs across multiple nodes, choosing the right access mode becomes critical. For example, If the volume is read-only and shared across Pods across nodes, you can use ReadOnlyMany (ROX), If the volume needs to be read and written by multiple Pods across nodes, you must use ReadWriteMany (RWX)
What does “Many” mean here?
“Many” refers to the number of nodes, not Pods.
RWO → Only one node can read/write to the volume at a time. i.e all the pods in the node can access this volume
RWX → Multiple nodes can read/write to the same volume simultaneously. i.e pods across nodes can access the volume
An important detail to note here is a Persistent Volume (PV) can be configured with multiple access modes, indicating what it supports. A Persistent Volume Claim (PVC), on the other hand, requests a specific access mode based on the application’s requirement. If the requested access mode in the PVC is supported by the PV, Kubernetes approves the claim and binds them together.
🧠 Key Takeaway
PV advertises what it can support, and PVC asks for what it needs. Binding happens only when both agree on the access mode.
Example Kubernetes Resource Definition File
Persistent Volume (PV)
apiVersion: v1
kind: PersistentVolume
metadata:
name: app-pv # Name of the PV
spec:
capacity:
storage: 10Gi # Size of the volume
accessModes:
- ReadWriteOnce # Supported access mode
- ReadWriteMany
persistentVolumeReclaimPolicy: Retain
# Retain data even if PVC is deleted
storageClassName: ebs-sc # Must match PVC
csi:
driver: ebs.csi.aws.com # AWS EBS CSI driver
volumeHandle: vol-0abcd1234efgh5678
# Actual EBS volume ID from AWS
volumeMode: Filesystem # Mount as a filesystem
Persistent Volume (PV)
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: app-pvc # Name of the PVC
spec:
accessModes:
- ReadWriteOnce # Only one node can read/write
resources:
requests:
storage: 10Gi # Amount of storage requested
storageClassName: ebs-sc # Use this StorageClass
Consuming a PVC Inside a Pod
apiVersion: v1
kind: Pod
metadata:
name: app-pod # Name of the Pod
spec:
containers:
- name: app-container
image: nginx # Sample container image
volumeMounts:
- name: app-storage
mountPath: /data # Path inside the container
# The PVC will be mounted here
volumes:
- name: app-storage
persistentVolumeClaim:
claimName: app-pvc # Name of the PVC to use
StorageClasses: Leveling Up to Dynamic Provisioning
In the real world the admin don’t want to worry about creating 100’s of PV’s(Persistent Volumes) with different types and sizes. Here is where StorageClasses (SC) comes in
How it works
The administrator creates a StorageClass in the cluster
The StorageClass is granted permission to create cloud provider disks (such as AWS EBS or Azure Disk) by installing the appropriate CSI driver in the cluster.
- For example, in an Amazon EKS cluster, you install the EBS CSI driver, which enables Kubernetes to dynamically provision EBS volumes on demand whenever a PVC is created.
The PVC specifies which StorageClass to use
When the PVC is created, Kubernetes checks:
- Is there an existing PV that matches this request?
If no matching PV exists, Kubernetes uses the StorageClass to dynamically create a new PV.
The newly created PV is bound to the PVC.
When a Pod references the PVC, the volume is attached and mounted into the Pod.
For example:
A Pod requests 50Gi
No existing PV matches
The StorageClass dynamically creates a new disk (EBS etc.)
The disk is attached to the Pod as a volume
No manual PV creation needed 🎉
Reclaim Policies
Now comes an important question. Your application stores data in a PV via a PVC and that data can live forever.
But what if:
You delete the application?
You no longer need the data?
You recreate the app with fresh data?
Continuously creating new volumes is not sustainable, especially when storage costs add up. This is where Reclaim Policies come into play.
Reclaim policies define what happens to a Persistent Volume after the PVC is deleted whether the data should be:
Retained: The PV is not deleted. It stays in "Released” state and will not be assigned to any new PVC request. An admin must manually clean up the data. This is the safest for production databases.
Deleted: The PV and the actual physical disk (AWS EBS, GCE PD) are deleted immediately. Should be choosen with extra caution as the data will be wiped once PVC is deleted
Recycle(Deprecated): It performs a basic
rm -rf /thevolume/*and makes the PV available again. (Rarely used now).
You control this with the persistentVolumeReclaimPolicy
The Binding Process
Kubernetes matches a PVC to a PV using these criteria:
Capacity: Does the PV have at least the amount requested?
Access Mode: Does the PV support the mode (RWO, RWX, etc.)?
StorageClass: Do they have the same StorageClass name?
Selectors: (Optional) Do the labels match?
Example Kubernetes Resource Definition File
StorageClass (Dynamic Provisioning)
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: ebs-sc # Name of the StorageClass
provisioner: ebs.csi.aws.com # CSI driver that talks to AWS EBS
parameters:
type: gp3 # EBS volume type (gp2 / gp3 / io1, etc.)
reclaimPolicy: Delete # What happens to the disk when PVC is deleted
volumeBindingMode: WaitForFirstConsumer
# Volume is created only when a Pod actually uses the PVC
Common Scenarios
The “Same Name” Scenario (ReclaimPolicy: Retain)
Assume you have an application using a Persistent Volume (PV) named pv-x, and the reclaim policy is set to Retain. You deploy the app, it creates a PVC, and everything works fine. After some experimentation, you delete the application (which deletes the PVC).
Later, you:
- Create a new application with a different PVC name, but want to use the same data
- Or simply rename the PVC for the same application
So… what happens?
When the PVC is deleted and the reclaim policy is Retain:
The PV is NOT deleted. The underlying disk is preserved
The PV moves into a Released state. The PV still remembers the old PVC it was bound to
This is the important part 👇
A PV in the Released state cannot be automatically reused by a new PVC—even if:
The storage size matches
The access modes match
The StorageClass matches
Kubernetes intentionally blocks this to prevent accidental data leaks between workloads.
❓ Why Can’t a New PVC Reuse the Same PV Automatically?
Because the PV still contains Old application data and Metadata pointing to the previous PVC. Kubernetes assumes this data belongs to someone else. I won’t reattach it unless a human explicitly says so. That’s a safety feature, not a limitation.
So How Can You Recover the Data?
There are two correct and safe ways to recover data from a retained PV.
✅ Option 1: Manually Rebind the Existing PV (Most Common)
If you want the same data to be used by a new or renamed PVC:
Manually edit the PV and remove the old
claimRefSet the PV back to
Available- Create a new PVC that matches: StorageSize, AccessMode, and Storage class
Once this is done, Kubernetes will bind the new PVC to the old PV—and your data is recovered intact.
This is the intended recovery flow for Retain.
✅ Option 2: Create a New PV Pointing to the Same Disk
This is useful when you don’t want to touch the old PV object and you want more control over the new binding.
Identify the underlying disk (EBS volume, Azure Disk, etc.)
Create a new PV definition
Point it to the same physical disk
Create a new PVC that binds to this new PV
The data remains untouched because the disk never changed—only the Kubernetes objects did.
Do you know AWS EBS Does NOT Support RWX
AWS Elastic Block Storage (EBS) does not support ReadWriteMany (RWX) access mode. why ?
Because an EBS volume behaves like a physical hard drive. Once you attach a hard drive to one machine, you cannot plug that same drive into multiple machines at the same time and expect it to work safely. This is exactly how EBS works:
One EBS volume → one node
Read/write access → single node only
That’s why EBS supports ReadWriteOnce (RWO).This limitation is not a Kubernetes issue — it’s a block storage limitation.
So What If You Need RWX Across Multiple Nodes?
If your application needs to run on multiple nodes and read and write the same data simultaneously, then block storage is the wrong tool. This is where file-based network storage comes in.
EFS: The RWX-Friendly Storage
Amazon Elastic File System (EFS) is designed to solve exactly this problem. EFS behaves like a shared network drive. Multiple nodes can mount it and all nodes see the same file and Read/Write operations happens concurrently
This wraps up our deep dive into PV, PVC, and StorageClasses — what they are, why they exist, and how Pods actually consume them.
From here, you can start mapping these concepts to real-world scenarios and production use cases, not just lab setups.



