Docs
/
Docker Kubernetes
Chapter 13

13 — Kubernetes Storage

The Problem

Containers lose data on restart. Kubernetes provides PersistentVolumes for durable storage.


Key Concepts

PersistentVolume (PV)        → The actual storage (disk, NFS, cloud volume)
PersistentVolumeClaim (PVC)  → A request for storage by a pod
StorageClass                 → Defines how PVs are dynamically provisioned

Pod → PVC → PV → Physical Storage

PersistentVolume & PersistentVolumeClaim

# PV (admin creates)
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pg-pv
spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: /data/postgres
---
# PVC (developer creates)
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pg-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi
---
# Pod uses PVC
apiVersion: apps/v1
kind: Deployment
metadata:
  name: postgres
spec:
  replicas: 1
  selector:
    matchLabels:
      app: postgres
  template:
    metadata:
      labels:
        app: postgres
    spec:
      containers:
        - name: postgres
          image: postgres:16-alpine
          volumeMounts:
            - name: data
              mountPath: /var/lib/postgresql/data
      volumes:
        - name: data
          persistentVolumeClaim:
            claimName: pg-pvc

Access Modes

ModeAbbreviationDescription
ReadWriteOnceRWOSingle node read/write
ReadOnlyManyROXMultiple nodes read-only
ReadWriteManyRWXMultiple nodes read/write

StorageClass (Dynamic Provisioning)

No need to pre-create PVs — the StorageClass provisions them on demand.

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: fast-ssd
provisioner: ebs.csi.aws.com    # AWS EBS
parameters:
  type: gp3
reclaimPolicy: Retain            # Keep data after PVC deleted
volumeBindingMode: WaitForFirstConsumer
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: db-pvc
spec:
  storageClassName: fast-ssd     # Uses StorageClass
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 20Gi
Reclaim PolicyBehavior
RetainPV kept after PVC deleted (manual cleanup)
DeletePV and storage deleted with PVC

StatefulSet Volume Claims

Each pod gets its own PVC automatically.

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: postgres
spec:
  replicas: 3
  serviceName: postgres
  selector:
    matchLabels:
      app: postgres
  template:
    metadata:
      labels:
        app: postgres
    spec:
      containers:
        - name: postgres
          image: postgres:16-alpine
          volumeMounts:
            - name: data
              mountPath: /var/lib/postgresql/data
  volumeClaimTemplates:
    - metadata:
        name: data
      spec:
        accessModes: ["ReadWriteOnce"]
        storageClassName: fast-ssd
        resources:
          requests:
            storage: 10Gi
# Creates: data-postgres-0, data-postgres-1, data-postgres-2

Key Takeaways

  • PVC = request for storage; PV = the actual storage; StorageClass = dynamic provisioner
  • Use StorageClass for dynamic provisioning (no manual PV creation)
  • Use Retain reclaim policy for databases — prevents accidental data loss
  • StatefulSet + volumeClaimTemplates gives each pod its own persistent volume
  • Use RWO for databases (single writer), RWX for shared file storage