Managing Data Persistence in Kubernetes: From Volumes to StorageClasses

Data Classification in Containerized Environments

Container filesystems are inherently ephemeral. When a container crashes or is deleted, any changes made to its local storage are lost. To manage data effectively, we generally categorize container data into three types:

  • Configuration Data: Initial settings or files required at startup.
  • Transient Shared Data: Temporary information shared between containers within the same Pod (e.g., a local cache).
  • Persistent Data: Information that must survive the Pod lifecycle, such as database files or user uploads.

Kubernetes Volumes

A Volume is an abstractoin that allows containers to access storage. Unlike the container's internal filesystem, a Volume's lifetime is tied to the Pod, ensuring data persists even if individual containers within that Pod restart.

emptyDir

The emptyDir volume is created when a Pod is assigned to a Node and exists as long as that Pod is running on that node. It starts empty and is primari used for temporary scratch space or as a communication bridge between containers in the same Pod.

apiVersion: v1
kind: Pod
metadata:
  name: shared-data-pod
spec:
  containers:
  - name: writer-app
    image: busybox
    command: ["/bin/sh", "-c", "echo 'Hello from writer' > /mnt/data/msg; sleep 3600"]
    volumeMounts:
    - name: scratch-pad
      mountPath: /mnt/data
  - name: reader-app
    image: busybox
    command: ["/bin/sh", "-c", "cat /mnt/data/msg; sleep 3600"]
    volumeMounts:
    - name: scratch-pad
      mountPath: /mnt/data
  volumes:
  - name: scratch-pad
    emptyDir:
      sizeLimit: 256Mi

hostPath

A hostPath volume mounts a file or directory from the host node's filesystem into you're Pod. This is often used for system-level monitoring or logging tools that need access to the underlying node.

apiVersion: v1
kind: Pod
metadata:
  name: node-log-viewer
spec:
  containers:
  - name: log-tailer
    image: alpine
    command: ["tail", "-f", "/var/log/system.log"]
    volumeMounts:
    - name: system-logs
      mountPath: /var/log/system.log
      readOnly: true
  volumes:
  - name: system-logs
    hostPath:
      path: /var/log/syslog
      type: File

NFS (Network File System)

NFS volumes allow multiple Pods to mount the same share simultaneously. Since the data resides on a remote server, it persists even after the Pod is deleted.

apiVersion: v1
kind: Pod
metadata:
  name: nfs-web-pod
spec:
  containers:
  - name: nginx-server
    image: nginx
    volumeMounts:
    - name: remote-assets
      mountPath: /usr/share/nginx/html
  volumes:
  - name: remote-assets
    nfs:
      server: 192.168.1.100
      path: /exports/web-data

PersistentVolumes and PersistentVolumeClaims

To decouple storage infrastructure from application logic, Kubernetes provides the PersistentVolume (PV) and PersistentVolumeClaim (PVC) system.

  • PersistentVolume (PV): A piece of storage in the cluster provisioned by an administrator or dynamically provisioned using Storage Classes. It is a cluster-level resource.
  • PersistentVolumeClaim (PVC): A request for storage by a user. It defines specific requirements like size and access modes.

PV Reclaim Policies

When a PVC is deleted, the Reclaim Policy determines what happens to the PV:

  • Retain: The PV remains, allowing for manual recovery.
  • Recycle: Performs a basic scrub (rm -rf) to make the volume available again (deprecated).
  • Delete: The PV and the associated storage asset in the external infrastructure are removed.

Access Modes

  • ReadWriteOnce (RWO): Mounted as read-write by a single node.
  • ReadOnlyMany (ROX): Mounted as read-only by many nodes.
  • ReadWriteMany (RWX): Mounted as read-write by many nodes.

Static Provisioning Example

First, create the PersistentVolume:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: static-nfs-pv
spec:
  capacity:
    storage: 10Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteMany
  persistentVolumeReclaimPolicy: Retain
  storageClassName: manual-nfs
  nfs:
    path: /srv/nfs/shared
    server: 10.10.20.50

Next, request the storage via a PVC:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: app-storage-pvc
spec:
  storageClassName: manual-nfs
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 5Gi

Dynamic Provisioning with StorageClass

Manually creating PVs becomes unscalable in large clusters. A StorageClass allows administrators to define "templates" for storage. When a user creates a PVC referencing a StorageClass, the cluster automatically provisions the PV.

Configuring an NFS Provisioner

In this scenario, an external provisioner (like nfs-subdir-external-provisioner) monitors the cluster for PVCs requesting a specific StorageClass.

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: fast-nfs-storage
provisioner: k8s-sigs.io/nfs-subdir-external-provisioner
parameters:
  archiveOnDelete: "false"
reclaimPolicy: Delete
mountOptions:
  - hard
  - nfsvers=4.1

Using Dynamic Storage in a Deployment

When a PVC is created using the fast-nfs-storage class, the PV is automatically generated and bound.

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: dynamic-web-pvc
spec:
  storageClassName: fast-nfs-storage
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 2Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
      - name: nginx
        image: nginx
        volumeMounts:
        - name: html-dir
          mountPath: /usr/share/nginx/html
      volumes:
      - name: html-dir
        persistentVolumeClaim:
          claimName: dynamic-web-pvc

In the dynamic model, Kubernetes handles the lifecycle of the underlying storage assets automatically, significantly reducing administrative overhead while providing developers with self-service storage capabilities.

Tags: kubernetes PersistentVolume StorageClass NFS ContainerStorage

Posted on Thu, 06 Aug 2026 17:01:01 +0000 by k9underdog