Containers are ephemeral. Databases, uploads, queues, and backups cannot be. Kubernetes separates who uses storage (pod) from who provides it (infrastructure) with three objects: PV, PVC, and StorageClass.
Course badge: tested on Kubernetes 1.35, NFS, and local-path.
The model
| Object | Role |
|---|---|
| Volume | mount inside the pod |
| PV (PersistentVolume) | storage resource in the cluster |
| PVC (PersistentVolumeClaim) | storage request by the user |
| StorageClass | “class” that dynamically provisions PVs |
| CSI | storage driver (modern standard) |
Flow:
PVC (pedido) → StorageClass (provisiona) → PV (disco) → Pod (monta)
Ephemeral vs persistent volume
emptyDir: lives as long as the pod lives. Good for cache/tmp.hostPath: mounts a directory from the node. Avoid in production; pins the pod to the node.PVC: persists beyond the pod.
volumes:
- name: cache
emptyDir: {}
- name: data
persistentVolumeClaim:
claimName: app-data
PV and PVC manually
PV:
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-nfs-5gi
spec:
capacity:
storage: 5Gi
accessModes: ["ReadWriteMany"]
persistentVolumeReclaimPolicy: Retain
nfs:
server: 192.168.56.50
path: /srv/nfs/app
PVC:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: app-data
spec:
accessModes: ["ReadWriteMany"]
resources:
requests:
storage: 5Gi
The PVC only binds if size, access mode, and class match. If it remains Pending, check the events:
kubectl describe pvc app-data
kubectl get pv
StorageClass and dynamic provisioning
With StorageClass, you do not create PVs manually:
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: portal-nfs
provisioner: nfs.csi.k8s.io
parameters:
server: 192.168.56.50
share: /srv/nfs/portal
reclaimPolicy: Retain
volumeBindingMode: Immediate
In the PVC:
spec:
storageClassName: portal-nfs
volumeBindingMode: WaitForFirstConsumer is useful for local storage: the PV is only created when the pod is scheduled, avoiding a PVC bound to the wrong node.
Access modes
| Mode | Meaning |
|---|---|
| RWO | ReadWriteOnce — one node at a time |
| ROX | ReadOnlyMany — multiple nodes, read-only |
| RWX | ReadWriteMany — multiple nodes, read-write |
| RWOP | ReadWriteOncePod — one pod at a time |
NFS usually supports RWX. Block disks are typically RWO. local-path is RWO and bound to the node — if the pod changes nodes, the volume does not follow.
The local-path case
The local-path-provisioner creates PVs pointing to a directory on the node. It is great for labs and for workloads that do not migrate (cache, local monitoring).
Problem: the PV has nodeAffinity to the node where it was created. If the pod is rescheduled to another node, the PVC remains Pending.
Symptom:
pod has unbound immediate PersistentVolumeClaims
or the pod remains Pending with a node affinity event. Solution: use shared storage (NFS/Ceph) or accept that the workload is pinned to the node.
StatefulSet and PVC
StatefulSet creates one PVC per replica:
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: portal-nfs
resources:
requests:
storage: 5Gi
The PVC is named <template>-<statefulset>-<ordinal>. Deleting the StatefulSet does not delete the PVC by default. This is good for recovery and bad for cleanup; manage it intentionally.
Resizing and snapshots
- Resizing a PVC depends on the driver and on
allowVolumeExpansionin the StorageClass. - Snapshots depend on CSI (
VolumeSnapshotClass). - Application backup is not just about volumes: databases need a consistent dump. Velero helps with PVs, but logical dumps are irreplaceable.
Lab
- Create an NFS PVC and mount it in a pod:
kubectl apply -f pvc-nfs.yaml
kubectl run app --image=nginx:1.27 --overrides='
{"spec":{"containers":[{"name":"app","image":"nginx:1.27",
"volumeMounts":[{"name":"data","mountPath":"/data"}]}],
"volumes":[{"name":"data","persistentVolumeClaim":{"claimName":"app-data"}}]}}'
kubectl exec app -- sh -c 'echo hello > /data/teste && cat /data/teste'
- Delete the pod and recreate it; the file should remain.
- Create a PVC with
local-pathand simulate rescheduling to another node — see the PVC become stuck. - Inspect
kubectl get pv,pvcand the events.
Common errors
| Symptom | Cause |
|---|---|
PVC Pending |
no PV/StorageClass, incompatible size or access mode |
Pod Pending with PVC |
node affinity of the local PV |
Permission denied |
UID/GID or permission on NFS |
| Data disappeared | pod mounted emptyDir instead of the PVC |
| PVC does not expand | StorageClass without allowVolumeExpansion |
| RWX does not work | driver does not support multiple nodes |
Checklist
- [ ] I know the difference between emptyDir, hostPath and PVC.
- [ ] Default StorageClass defined.
- [ ] Correct access mode for the workload.
- [ ] I know if the storage is pinned to the node (local-path).
- [ ] StatefulSet has
volumeClaimTemplates. - [ ] Volume backup and logical dump tested.
Glossary
- PV: storage resource.
- PVC: storage request.
- StorageClass: dynamic provisioner.
- CSI: Container Storage Interface.
- RWX/RWO: access modes.
- Reclaim policy: what happens to the PV when the PVC is deleted.
Next
Now that data persists, let's configure the application without rebuilding the image: ConfigMap, Secret, and the guard that already took down one of our deployments.
Next: Kubernetes Course 12 — ConfigMap, Secret, and the credentials guard
Keep reading
Read also

StorCLI - Complete Cheat Sheet
StorCLI is the official and modern tool for managing Broadcom/LSI RAID controllers. This guide covers essential commands, syntax and use cases.
12 min de leitura
Portal ITSMBusiness Services in Nyverra Portal: Translating IT into Business
The business doesn't feel a server go down — it feels email stop. The Business Services (Service Mapping) module of Nyverra ITSM Portal connects services like Email, ERP or PACS to CMDB assets, revealing the real impact of each failure.
5 min de leitura
SegurançaRPO vs RTO: How to Define Before Buying Backup (and Why Most Companies Get It Wrong)
Most companies buy backup asking the wrong question: "how much does it cost?". The right question is: how much data can I lose (RPO) and how long can I be down (RTO). Discover how to define these numbers per system and avoid purchasing protection based on price, not on real need.
9 min de leitura
Comments
No comments yet
Be the first to share your thoughts on this article.

Leave a comment