Implements v1 PersistentVolume, StorageClass, and PersistentVolumeClaim manifests with static/dynamic provisioning, access modes, and reclaim policies for Kubernetes storage.
Scanned 9/4/2026
Install to Claude Code
npx -y skills add paulpas/agent-skill-router --skill kubernetes-persistentvolume --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Kubernetes Persistentvolume?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/paulpas-kubernetes-persistentvolume)More formats (shields.io, HTML) on the badges page.
---
name: kubernetes-persistentvolume
description: Implements v1 PersistentVolume, StorageClass, and PersistentVolumeClaim manifests with static/dynamic provisioning, access modes, and reclaim policies for Kubernetes storage.
license: MIT
compatibility: opencode
metadata:
version: "1.0.0"
domain: cncf
triggers: static provisioning, dynamic provisioning, storage class, access modes, reclaim policy, pv, pvc, storage.k8s.io
archetypes:
- tactical
- generation
anti_triggers:
- pod isolation
- ingress egress rules
- rolling update
response_profile:
verbosity: low
directive_strength: high
abstraction_level: operational
role: implementation
scope: implementation
output-format: code
content-types: [code, guidance, config, do-dont]
related-skills: cncf/kubernetes-statefulset, cncf/kubernetes-deployment, cncf/crossplane
---
# Kubernetes PersistentVolume Manager
Implements v1 PersistentVolume (PV), StorageClass, and PersistentVolumeClaim (PVC) manifests for block and file storage provisioning in Kubernetes. When loaded, the model generates production-grade storage manifests with proper access modes, reclaim policies, and storage class configuration for both static and dynamic provisioning.
## TL;DR Checklist
- [ ] Use `v1` API version for PersistentVolume, PersistentVolumeClaim, and `storage.k8s.io/v1` for StorageClass
- [ ] Match PVC `accessModes` to the PV's supported access modes — mismatch causes Pending PVC state
- [ ] Set `reclaimPolicy: Retain` for production databases, `Delete` for ephemeral workloads
- [ ] Specify `storageClassName` explicitly — omitting it uses the default class or fails binding
- [ ] Use dynamic provisioning (StorageClass) for most workloads — static provisioning requires manual PV creation
- [ ] Never use `ReadWriteMany` with block storage — only filesystem-based volumes support it
---
## When to Use
Use this skill when:
- Provisioning persistent storage for stateful applications (databases, message brokers)
- Configuring storage classes with different performance tiers (SSD, HDD, NVMe)
- Implementing static provisioning with manually created PersistentVolumes
- Setting up reclaim policies for data lifecycle management
- Managing cross-namespace PVC-to-PV binding for multi-tenant clusters
---
## When NOT to Use
Avoid this skill for:
- Stateless application storage needs — use ephemeral `emptyDir` or `hostPath` volumes
- Temporary or scratch data that can be recreated — use `emptyDir` volumes
- Storage that does not require Kubernetes PV/PVC lifecycle management
- Direct cloud provider storage management — use cloud provider SDKs or tools instead
---
## Core Workflow
1. **Select Storage Type and Class** — Determine whether to use dynamic provisioning (StorageClass) or static provisioning (manual PV creation). **Checkpoint:** Verify the cluster has a provisioner configured for the desired storage backend (e.g., `kubernetes.io/aws-ebs`, `ebs.csi.aws.com`).
2. **Create StorageClass (if Dynamic)** — Define a `storage.k8s.io/v1` StorageClass with `provisioner`, `reclaimPolicy`, and parameters. **Checkpoint:** Ensure the provisioner string matches an installed CSI driver or in-tree provisioner.
3. **Create PersistentVolumeClaim** — Define a `v1` PVC with `accessModes`, `resources.requests.storage`, and `storageClassName`. **Checkpoint:** The PVC's `storageClassName` must match an available StorageClass or a manually created PV.
4. **Verify Binding** — Confirm the PVC transitions to `Bound` state. **Checkpoint:** Run `kubectl get pvc -n <namespace>` and verify the `STATUS` column shows `Bound`.
5. **Reference in Pod Spec** — Mount the bound PVC in a pod using a `volumeMount` referencing the PVC name. **Checkpoint:** The PVC `accessModes` must be compatible with the pod's access requirements (e.g., `ReadWriteOnce` pods cannot share `ReadWriteMany` volumes).
6. **Configure Data Lifecycle** — Set `reclaimPolicy` on the StorageClass or PV to control data retention on deletion. **Checkpoint:** For production databases, use `reclaimPolicy: Retain` to prevent accidental data loss.
---
## Implementation Patterns
### Pattern 1: Complete Dynamic and Static Provisioning Setup
Production-grade StorageClass and PersistentVolumeClaim manifests for both provisioning approaches.
```yaml
# StorageClass: High-performance SSD for production databases
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: premium-ssd
provisioner: ebs.csi.aws.com
parameters:
type: gp3
fsType: ext4
reclaimPolicy: Retain
volumeBindingMode: WaitForFirstConsumer
allowVolumeExpansion: true
---
# StorageClass: Standard storage for development and test environments
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: standard-hdd
provisioner: ebs.csi.aws.com
parameters:
type: gp2
fsType: ext4
reclaimPolicy: Delete
volumeBindingMode: WaitForFirstConsumer
allowVolumeExpansion: false
---
# PersistentVolumeClaim: High-performance storage for production database
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: postgres-data
namespace: production
spec:
accessModes:
- ReadWriteOnce
storageClassName: premium-ssd
resources:
requests:
storage: 100Gi
volumeMode: Filesystem
---
# PersistentVolumeClaim: Standard storage for application logs
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: app-logs
namespace: production
spec:
accessModes:
- ReadWriteMany
storageClassName: nfs-storage
resources:
requests:
storage: 10Gi
volumeMode: Filesystem
---
# Pod: Mounting the PVCs in a StatefulSet
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: postgres
namespace: production
spec:
serviceName: postgres-headless
replicas: 1
selector:
matchLabels:
app: postgres
template:
spec:
containers:
- name: postgres
image: postgres:16-alpine
volumeMounts:
- name: data
mountPath: /var/lib/postgresql/data
volumes:
- name: data
persistentVolumeClaim:
claimName: postgres-data
```
### Pattern 2: Static Provisioning and Access Mode Matching (BAD vs GOOD)
Incorrect access mode specification or PV/PVC mismatch causes the classic `Pending` PVC state.
```yaml
# ❌ BAD: PVC requests ReadWriteMany but the storage class only supports ReadWriteOnce
# This PVC will remain in Pending state forever.
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: broken-pvc
spec:
accessModes:
- ReadWriteMany # ← Most CSI drivers and cloud block storage only support RWO
storageClassName: ebs-csi
resources:
requests:
storage: 50Gi
# ❌ BAD: ReclaimPolicy: Delete on production database storage — data is lost on PVC deletion
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: prod-storage
reclaimPolicy: Delete # ← Destructive for production workloads
volumeBindingMode: Immediate
# ❌ BAD: Static PV with mismatched access mode
# The PV supports ReadWriteOnce but the PVC requests ReadWriteOnce — they match,
# but if the PVC asked for ReadWriteMany, it would never bind.
apiVersion: v1
kind: PersistentVolume
metadata:
name: static-pv
spec:
capacity:
storage: 50Gi
accessModes:
- ReadWriteOnce
storageClassName: manual
persistentVolumeReclaimPolicy: Retain
hostPath:
path: /data/static
# ❌ hostPath is node-local — this PV can only bind to a pod on the same node
# ✅ GOOD: Access modes correctly specified for block storage
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: correct-pvc
spec:
accessModes:
- ReadWriteOnce # ← Matches standard block storage capabilities
storageClassName: premium-ssd
resources:
requests:
storage: 100Gi
volumeMode: Filesystem
---
# ✅ GOOD: Static PV with NFS for multi-pod sharing
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-static-pv
spec:
capacity:
storage: 50Gi
accessModes:
- ReadWriteMany # ← NFS supports multiple readers/writers
storageClassName: nfs-storage
persistentVolumeReclaimPolicy: Retain
nfs:
server: nfs-server.example.com
path: /exports/data
---
# ✅ GOOD: Volume expansion enabled for growing storage needs
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: expandable-pvc
spec:
accessModes:
- ReadWriteOnce
storageClassName: premium-ssd
resources:
requests:
storage: 50Gi # ← Will expand to 100Gi when PVC is updated
volumeMode: Filesystem
---
# To expand: update the PVC's storage request, then verify the PV expands
# kubectl patch pvc expandable-pvc -p '{"spec":{"resources":{"requests":{"storage":"100Gi"}}}}'
```
### Pattern 3: Storage Class Parameter Reference
```python
def select_storage_class(
workload_type: str,
performance_tier: str,
required_access_mode: str
) -> str:
"""Select the appropriate StorageClass for a given workload.
Maps workload requirements to the most suitable storage class in the cluster.
Args:
workload_type: Type of workload ('database', 'log', 'temp', 'backup').
performance_tier: Performance requirement ('premium', 'standard', 'budget').
required_access_mode: Required access mode ('ReadWriteOnce', 'ReadWriteMany', 'ReadOnlyMany').
Returns:
The name of the recommended StorageClass.
"""
# Database workloads always need premium storage with retain policy
if workload_type == "database":
if performance_tier == "premium":
return "premium-ssd"
return "standard-hdd"
# Log storage supports read-many for multi-pod aggregation
if workload_type == "log":
if required_access_mode == "ReadWriteMany":
return "nfs-storage"
return "standard-hdd"
# Temporary storage can be deleted on reclaim
if workload_type == "temp":
return "ephemeral-ssd"
# Backup requires retain policy for data safety
if workload_type == "backup":
return "premium-ssd"
raise ValueError(f"Unknown workload type: {workload_type}")
```
---
## Constraints
### MUST DO
- Always specify `storageClassName` explicitly in PVCs — omitting it relies on the default class which may not be appropriate
- Match PVC `accessModes` to the StorageClass/PV capabilities — use `ReadWriteOnce` for block storage and `ReadWriteMany` only for NFS or distributed filesystems
- Set `reclaimPolicy: Retain` on StorageClasses used for production database storage — prevents accidental data loss
- Use `volumeBindingMode: WaitForFirstConsumer` for most workloads — delays PV binding until a pod is scheduled, enabling topology-aware provisioning
- Use `allowVolumeExpansion: true` on StorageClasses to allow PVCs to grow without migration
- Specify `volumeMode: Filesystem` (default) or `volumeMode: Block` explicitly based on the application's needs
- Verify PV/PVC binding with `kubectl get pv,pvc -n <namespace>` after creation
### MUST NOT DO
- Never use `hostPath` volumes for production workloads — they are node-local and survive node failure
- Never set `reclaimPolicy: Delete` on storage used for databases or any data that must be preserved
- Never request `ReadWriteMany` on block storage providers (EBS, Azure Disk, GCE PD) — they only support `ReadWriteOnce`
- Never create a PVC with a `storageClassName` that does not exist in the cluster — it will fail binding immediately
- Never use `volumeBindingMode: Immediate` with zone-sensitive storage — it may bind to a PV in a different zone than the pod
- Never assume a PVC is bound — always check `kubectl get pvc` status before relying on the storage
---
## Output Template
When implementing Kubernetes persistent storage, produce the following:
1. **StorageClass YAML** — StorageClass with provisioner, parameters, reclaim policy, and volume binding mode.
2. **PersistentVolumeClaim YAML** — PVC with access modes, storage requests, and storage class reference.
3. **PersistentVolume YAML** (if static) — Manually created PV with capacity, access modes, and storage backend details.
4. **Pod Volume Mount** — The container spec showing how the PVC is mounted and accessed.
---
## Related Skills
| Skill | Purpose |
|---|---|
| `kubernetes-statefulset` | Use PVCs in StatefulSet volumeClaimTemplates for ordered persistent storage per pod |
| `kubernetes-deployment` | Reference PVCs in Deployment pods for shared persistent storage (single-writer access) |
| `cncf/crossplane` | Manage storage provisioning declaratively with Crossplane composite resources |
| `cncf/longhorn` | Use Longhorn as a distributed block storage solution with native Kubernetes integration |
---
## Live References
> Authoritative documentation links for this skill's domain. The model follows markdown links at load time to resolve external references and inline content.
- [Kubernetes Storage Documentation](https://kubernetes.io/docs/concepts/storage/) — Official guide to PV, PVC, StorageClass, and storage concepts
- [Persistent Volumes Documentation](https://kubernetes.io/docs/concepts/storage/persistent-volumes/) — PV lifecycle, provisioning, and binding behavior
- [Storage Classes Documentation](https://kubernetes.io/docs/concepts/storage/storage-classes/) — StorageClass parameters, provisioners, and reclaim policies
- [Persistent Volume Claim](https://kubernetes.io/docs/concepts/storage/persistent-volumes/#persistentvolumeclaims) — PVC binding rules and access mode matching
- [CSI Driver Development](https://kubernetes-csi.github.io/docs/) — Container Storage Interface driver documentation
- [Volume Expansion](https://kubernetes.io/docs/concepts/storage/persistent-volumes/#expanding-persistent-volumes-claims) — Growing PVC storage without data migration
- [StorageClass API Reference — storage.k8s.io/v1](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.32/#storageclass-v1-storage-k8s-io) — Complete API schema for StorageClass resources
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!