Do I have to explicitly create Persistent Volume when I am using Persistent Volume Claim?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
In Kubernetes, a PersistentVolume (PV) is a piece of provisioned storage, and a PersistentVolumeClaim (PVC) is a request for that storage. Whether you need to manually create a PV depends on whether your cluster supports dynamic provisioning. In most cloud environments, the answer is no — Kubernetes creates the PV automatically when you create a PVC.
Short Answer
- If dynamic provisioning is configured using a StorageClass, you do not need to create a PV. When a PVC is created, Kubernetes automatically provisions a new PV that matches the PVC's requirements.
- If there is no StorageClass configured or dynamic provisioning is not enabled, you must manually create a PV that meets the requirements of the PVC (size, access mode, etc.).
Dynamic Provisioning (Automatic)
Most cloud Kubernetes services (EKS, GKE, AKS) come with a default StorageClass that enables dynamic provisioning:
When you apply this, Kubernetes:
- Finds the default StorageClass (or the one you specified)
- Calls the storage provisioner to create a volume (e.g., an EBS volume on AWS)
- Creates a PV that binds to your PVC
Check your cluster's default StorageClass:
Output:
The (default) marker indicates this StorageClass is used when no storageClassName is specified.
Static Provisioning (Manual)
If your cluster does not support dynamic provisioning (bare-metal, on-premises, or you need specific storage), create the PV first:
Setting storageClassName: "" tells Kubernetes to only look for pre-existing PVs, not to dynamically provision one.
Using a PVC in a Pod
Regardless of how the PV was created, the pod references the PVC:
Access Modes
PVs and PVCs must have matching access modes:
| Access Mode | Abbreviation | Meaning |
| ReadWriteOnce | RWO | Read-write by a single node |
| ReadOnlyMany | ROX | Read-only by multiple nodes |
| ReadWriteMany | RWX | Read-write by multiple nodes |
Not all storage types support all modes:
| Storage Type | RWO | ROX | RWX |
| AWS EBS | Yes | No | No |
| GCE PD | Yes | Yes | No |
| NFS | Yes | Yes | Yes |
| Azure Disk | Yes | No | No |
| Azure Files | Yes | Yes | Yes |
Reclaim Policies
When a PVC is deleted, the reclaim policy determines what happens to the PV:
- Delete: The PV and its underlying storage are deleted (default for dynamic provisioning)
- Retain: The PV remains with its data intact; must be manually cleaned up
Checking PV/PVC Status
Common Pitfalls
- No default StorageClass: If
kubectl get scshows no(default)StorageClass, PVCs without astorageClassNamewill stay in Pending state indefinitely. Either create a default StorageClass or specify one explicitly. - Size mismatch: A PVC requesting 10Gi will not bind to a PV with only 5Gi. The PV must be at least as large as the PVC request.
- Access mode mismatch: A PVC requesting
ReadWriteManywill not bind to a PV that only supportsReadWriteOnce. Check your storage provider's supported modes. - WaitForFirstConsumer binding: Some StorageClasses use
WaitForFirstConsumervolume binding mode, meaning the PV is not created until a pod actually uses the PVC. The PVC will showPendinguntil then — this is normal. - hostPath in production:
hostPathvolumes are for testing only. Data is tied to a specific node and is lost if the pod is rescheduled. Use cloud storage or NFS for production.
Summary
| Scenario | Create PV Manually? |
| Cloud Kubernetes (EKS, GKE, AKS) | No — dynamic provisioning handles it |
| On-premises with StorageClass | No — if a provisioner is configured |
| On-premises without StorageClass | Yes — create PV before PVC |
| Specific storage requirements | Sometimes — depends on the provisioner |
- In most cloud environments, just create a PVC and let dynamic provisioning handle the rest
- Set
storageClassName: ""to force static binding (no dynamic provisioning) - Check
kubectl get scto see available StorageClasses and their default status

