Kubernetes
Intermediate 14 min read Kubernetes

Storage: Volumes, PVCs & CSI

Disks that follow, not forget

Kubernetes abstracts storage with CSI: StorageClasses provision PVs on demand via PVCs; pods mount PVs by claim. emptyDir/hostPath cover first-party ephemeral needs; persistent classes map to EBS/gcePersistentDisk/azureDisk or network filesystems for shared reads.

PVCPVStorageClassCSIemptyDirhostPathRWORWX
Prerequisites: Config & Secrets
Before we start

What you will learn

  • Explain StorageClass → PV provisioning → PVC → pod mount
  • Differentiate access modes: RWO, RWX, ReadOnlyMany
  • Choose block vs file vs object reach from the cluster
In 60 seconds

You declare a PVC (size + class + access mode). The provisioner creates a PV (an EBS/PD/disk volume), claim binds, pod mounts. CSI makes storage backends pluggable: EBS, EFS, GCE PD, azureDisk and more.

Introduction

What is this?

StorageClass: parameters (provisioner, type/encryption/IOPS), reclaimPolicy (Delete/Retain), volumeBindingMode (WaitForFirstConsumer), allowVolumeExpansion. PVC: spec(size, accessModes[], storageClassName). Access modes: RWO (single node R/W), RWM (multinode R/W), ROM/ReadOnlyMany. PV types: local (no provisioning), hostPath (node FS), generic CSI, CSI storage drivers (aws-ebs, efs, gce-pd, azure-disk, csi-driver-nfs). Persistent volume claims also used by StatefulSets per-replica. Ephemeral: emptyDir (pod-scoped), volumeFrom + projected. SubPath/MountOptions/volumeAttributes define depth of mapping.

Motivation

Why do you need it?

  • PVC/CSI decouple 'I need storage' from 'which storage vendor' — portability across clouds.
  • WaitForFirstConsumer + topology matches disk to where the pod lands (latency).
  • StorageClasses encode environment policy (fast SSD prod vs cheap staging) centrally.
  • Stateful storage following a rescheduled pod is the DB-on-K8s superpower.
Think about it

Mental model

Imagine

A restaurant ordering 'one prep room this stall' from the mall maintenance

Think of

PVC → PV

The kitchen says 'I need a prep room, 12m², on our floor' (PVC). The maintenance office (provisioner) assigns an actual room (PV) that matches — and claws it back when we leave (reclaim).

Mechanics

How it works

  • Pod references PVC in volumes/volumeMounts.
  • Controller sees unbound PVC → matches a storage class → invokes provisioner → PV created.
  • Claim binds (PVC ↔ PV 1:1); scheduler pins to a node respecting topology (WaitForFirstConsumer).
  • kubelet + CSI mount driver attach + mount; container FS sees the volume.
  • On pod deletion, PVC remains; on PVC deletion, reclaimPolicy Delete tears down the cloud disk.

Storage provisioning flow.

Pod
PVC
StorageClass
PV / EBS
Mount
Hands-on

Examples

Claim + deploy a stateful WP-style pod

Claim + deploy a stateful WP-style pod
kind: PersistentVolumeClaim
apiVersion: v1
metadata: { name: www-data }
spec:
accessModes: [ReadWriteOnce]
storageClassName: standard
resources: { requests: { storage: 10Gi } }
# pod: volumes: [{name: data, persistentVolumeClaim: { claimName: www-data }}]

The pod just names the claim; the platform resolves capacity, type and node affinity.

Real world

In production

  • PostgreSQL/Prometheus on per-pod PVCs with snapshots scheduled via CSI.
  • EFS/NFS RWX class for shared uploads behind multiple replicas.
  • Temporary build/job scratch on emptyDir with sizeLimit to stop disk hogging.
Guidelines

Best practices

  • Prefer WaitForFirstConsumer classes for low-latency disks.
  • Set reclaimPolicy=Retain for anything you might need to salvage (pre-prod fashion was surprise).
  • Use PVC-based state even in v1 workloads → swap to larger classes without surgical yaml.
  • Snapshot DB volumes using CSI between upgrades; test restore into a scratch cluster.
  • Keep StorageClass parameters versioned alongside IaC.
Watch out

Common mistakes

  • RWX backing Postgres data → corruption (needs RWO).
  • emptyDir used as DB persistence then lost on pod recreate.
  • hostPath leaks node state into pod assumptions; prefer PV/CSI.
  • Delete-scoped PVCs: an rm of a namespace nukes production data without Retain.
When things break

Debugging tips

  • PVC stays Pending → storage class missing or volumeBindingMode+node affinity mismatch; describe pvc/pv.
  • Pod stuck MountVolume → CSI driver pods healthy? disk attach quota? driver log.
  • RWO contention → second node can't mount; decide multi-writer carefully.
  • Capacity full on PV → expand claim in-place only if allowVolumeExpansion + filesystem supports grow.
Interviews

Interview checkpoint

Test yourself

Quick quiz

0/2
1

ReadWriteOnce means:

2

reclaimPolicy=Delete on the StorageClass destroys:

Go deeper

Official documentation