Kubernetes Storage Volumes: From Temporary to Persistent Solutions

Kubernetes containers are ephemeral by design; any data written to the container's filesystem disappears when the container terminates. While Docker introduced volumes for basic persistence, Kubernetes provides a more sophisticated storage architecture with diverse plugins and explicit lifecycle management tied to Pods rather than individual containers.

A key innovation is the separation between PersistentVolume (PV) and PersistentVolumeClaim (PVC). This abstraction mirrors the Pod-Node relationship: administrators provision PVs representing actual storage assets, while developers create PVCs to request storage resources without concerning themselves with backend implementation details.

PV and PVC Fundamentals

Lifecycle Stages

  1. Provisioning: Cluster administrators create PVs with predefined capacity and access characteristics.
  2. Binding: When a PVC is created, the control plane matches it to an appropriate PV. The PVC remains unbound until a suitable PV becomes available.
  3. Utilization: Pods reference PVCs in their specifications, mounting them as standard volumes.
  4. Release: Deleting a PVC triggers the release phase, marking the PV as "Released" while retaining existing data.
  5. Reclamation: PVs support three reclamation policies:
    • Retain: Manual intervention required to manage leftover data
    • Delete: Automatically removes PV and associated storage asset (supported by cloud providers)
    • Recycle: Performs basic scrubbing to make storage reusable (deprecated in modern Kubernetes)

Key Attributes

PersistentVolume:

  • Capacity: Currently storage size only; future versions may include IOPS and throughput
  • Acces Modes:
    • ReadWriteOnce (RWO) - single node read/write
    • ReadOnlyMany (ROX) - multiple nodes read-only
    • ReadWriteMany (RWX) - multiple nodes read/write
  • Phase States: Available, Bound, Released, Failed

PersistentVolumeClaim:

  • Access Modes: Must match supported PV modes
  • Resource Rqeuests: Desired storage quantity

Practical Volume Implementations

emptyDir: Pod-Scoped Temporary Storage

An emptyDir volume exists only for the Pod's lifetime. It's created when a Pod is scheduled to a node and persists through container restarts, but disappears permanently when the Pod is deleted or rescheduled.

Use Case: Sharing transient data between containers in the same Pod.


</div>Deploy and verify:

kubectl apply -f shared-cache-pod.yaml kubectl get pod shared-cache-pod -o wide

Access the service

curl /content.txt


### hostPath: Node-Anchored Storage

`hostPath` mounts a file or directory from the host node's filesystem into the Pod. This creates a dependency on specific node filesystems, making it unsuitable for multi-node clusters but useful for single-node development or daemonset scenarios.

<div class="code-block">```
apiVersion: v1
kind: Pod
metadata:
  name: node-data-pod
  namespace: default
spec:
  containers:
  - name: file-viewer
    image: nginx:alpine
    volumeMounts:
    - name: node-storage
      mountPath: /usr/share/nginx/html
  volumes:
  - name: node-storage
    hostPath:
      path: /var/local/pod-data
      type: DirectoryOrCreate

kubectl apply -f node-data-pod.yaml
# On the host node:
sudo mkdir -p /var/local/pod-data
echo "Node-specific content" | sudo tee /var/local/pod-data/index.html
# Access from any client:
kubectl get pod node-data-pod -o wide
curl <pod-ip>

NFS: Network-Attached Persistent Storage

NFS volumes provide true persistence independent of Pod lifecycle. Data survives Pod deletion and remains accessible across cluster nodes, enabling stateful applications.

Server Setup (Ubuntu/Debian):

sudo apt-get update
sudo apt-get install -y nfs-kernel-server
sudo mkdir -p /exports/webdata
sudo chown nobody:nogroup /exports/webdata
# Configure exports
echo "/exports/webdata 10.0.0.0/24(rw,sync,no_subtree_check,no_root_squash)" | sudo tee -a /etc/exports
sudo exportfs -ra
sudo systemctl restart nfs-kernel-server

Client Pod Configuration:


</div>Deploy and validate persistence:

kubectl apply -f nfs-web-pod.yaml

Write content on NFS server:

echo "Persistent Data" | sudo tee /exports/webdata/index.html

Access the Pod:

kubectl get pod nfs-web-pod -o wide curl

Delete and recreate to verify persistence:

kubectl delete -f nfs-web-pod.yaml kubectl apply -f nfs-web-pod.yaml

Data remains accessible regardless of node placement

curl

Tags: kubernetes persistent-volume persistent-volume-claim emptydir hostpath

Posted on Tue, 21 Jul 2026 16:16:32 +0000 by Lumio