Skip to content
Commitpedia
Log in Join & edit

Persistent storage in Kubernetes: PersistentVolumes, claims and StorageClasses

How to give a Pod storage that survives restarts: request it with a PersistentVolumeClaim, let a StorageClass provision it, and mount it. Covers access modes and reclaim policies.

Not checked by a trusted editor yet Last edited Outdated?

Edit history of Persistent storage in Kubernetes: PersistentVolumes, claims and StorageClasses: 1 recorded edit
Edit history · 1 edit
Type
Article
Edits
1
Editors
1
First issued
15 Oct 2026
Last edit
15 Oct 2026
Reading
3 min

A container’s own filesystem disappears when the container is replaced. For data that must survive, such as database files and uploads, Kubernetes separates asking for storage from providing it:

  • PersistentVolume (PV): a piece of real storage (a cloud disk, an NFS export, a Ceph volume) represented as a cluster object.
  • PersistentVolumeClaim (PVC): a request by a user: “10 GiB, read-write, of this class”. Pods reference claims, never PVs directly.
  • StorageClass: a recipe that tells a provisioner how to create PVs on demand. With dynamic provisioning you never write PVs by hand.

Step 1: see what storage the cluster offers

kubectl get storageclass
kubectl describe storageclass standard

A class marked (default) carries the annotation storageclass.kubernetes.io/is-default-class: "true" and is used when a claim does not name a class. If no class exists, an administrator has to install a CSI driver or create PVs manually.

Step 2: create a claim

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: data
  namespace: shop
spec:
  accessModes:
  - ReadWriteOnce
  storageClassName: standard
  resources:
    requests:
      storage: 10Gi
kubectl apply -f pvc.yaml
kubectl get pvc -n shop

The claim shows Pending until a matching volume exists and Bound once it is attached to one. With a class that uses volumeBindingMode: WaitForFirstConsumer, it stays Pending until a Pod uses it; that is expected, and it lets the volume be created in the same zone as the Pod.

Step 3: mount it in a Pod

apiVersion: v1
kind: Pod
metadata:
  name: data-test
  namespace: shop
spec:
  containers:
  - name: app
    image: busybox:1.36
    command: ["sh", "-c", "date >> /data/log.txt && sleep 3600"]
    volumeMounts:
    - name: data
      mountPath: /data
  volumes:
  - name: data
    persistentVolumeClaim:
      claimName: data

Delete and recreate the Pod, then run kubectl exec -n shop data-test -- cat /data/log.txt: the earlier lines are still there. For replicated stateful apps, use a StatefulSet with volumeClaimTemplates so that each replica gets its own claim.

Access modes

  • ReadWriteOnce (RWO): read-write by a single node. Several Pods on that same node can still share it.
  • ReadOnlyMany (ROX): read-only by many nodes.
  • ReadWriteMany (RWX): read-write by many nodes; needs shared storage such as NFS or CephFS.
  • ReadWriteOncePod (RWOP): read-write by exactly one Pod in the whole cluster; supported only for CSI volumes.

Access modes are used for matching claims to volumes. They do not enforce write protection once the storage is mounted, and a block-storage driver usually supports only RWO.

Reclaim policy: what happens on delete

  • Delete: deleting the claim also deletes the PV and the underlying storage. This is the default for dynamically provisioned volumes when the StorageClass does not say otherwise.
  • Retain: the PV and its data stay behind for manual cleanup or reuse.
  • Recycle: deprecated; use dynamic provisioning instead.

Warning: with the Delete policy, kubectl delete pvc destroys the data. Before deleting, check the policy with kubectl get pv (column RECLAIM POLICY) and back up anything you need. To protect an existing volume, switch it to Retain first:

kubectl patch pv <pv-name> -p '{"spec":{"persistentVolumeReclaimPolicy":"Retain"}}'

Kubernetes also protects claims that are in use: a PVC that a Pod is still using is not removed until that Pod is gone, so a delete may appear to hang with the claim in Terminating.

Growing a volume

If the StorageClass has allowVolumeExpansion: true, edit the claim’s resources.requests.storage to a larger value and apply it. Shrinking is not supported.

Official documentation

See also

  • 0132 Pods, ReplicaSets and Deployments explained A Pod runs one or more containers together, a ReplicaSet keeps a fixed number of identical Pods alive, and a Deployment manages… Beginner · Concept · Linux Article Concepts · Workloads & services 15 Oct 2026
  • 0134 ConfigMaps and Secrets: configuration outside the image ConfigMaps hold plain settings and Secrets hold sensitive values, injected into Pods as environment variables or files. Secrets are only base64-encoded, not… Intermediate · Concept · Linux Article Config, secrets & storage 15 Oct 2026
  • 0135 Deploy your first app on Kubernetes A step-by-step tutorial: write a Deployment and a Service in YAML, apply them, reach the app, add health probes, roll out a… Beginner · How-to · Linux Article Ingress & networking · Workloads & services 15 Oct 2026
  • 0138 Kubernetes RBAC basics: least-privilege access for a service account RBAC controls who may do what in a cluster with Roles, ClusterRoles and bindings. This guide grants a CI service account deploy… Advanced · How-to · Linux Article Concepts · Config, secrets & storage 15 Oct 2026
  • 0144 Fix: Pod stuck in Pending with “0/3 nodes are available: Insufficient cpu” The scheduler cannot find a node with enough unreserved CPU for the pod's request. Compare the request with node allocatable resources, then… Advanced · Fix · Linux Article Troubleshooting · Workloads & services 15 Oct 2026
  • 0145 Fix: OOMKilled (exit code 137) in Kubernetes A container used more memory than its limit and the kernel killed it. Confirm the reason, measure real usage, then raise the… Advanced · Fix · Linux Article Troubleshooting · Workloads & services 15 Oct 2026

History

Every saved edit is kept. The plot on the sleeve draws one line per edit. Open any edit to see exactly what changed.

  1. Commitpedia +3,850 chars

Report a problem

Something wrong, unsafe or copied? Tell the editors.
What is wrong?