8.1 Storage Concepts (PVs, PVCs, StorageClasses & CSI)
Key Takeaways
- Kubernetes separates temporary container storage (emptyDir, hostPath) from persistent storage that outlives Pod lifecycles.
- PersistentVolumes (PVs) and PersistentVolumeClaims (PVCs) decouple cluster storage administration from application storage consumption.
- StorageClasses enable dynamic volume provisioning, automatically creating cloud or SAN storage volumes on demand without manual administrator intervention.
- Container Storage Interface (CSI) provides a standardized, out-of-tree API specification allowing third-party storage vendors to write plugins independently of core Kubernetes code.
- Access modes (ReadWriteOnce, ReadOnlyMany, ReadWriteMany, ReadWriteOncePod) and reclaim policies (Retain, Delete) govern how volumes are mounted and recycled across the cluster.
8.1 Storage Concepts (PVs, PVCs, StorageClasses & CSI)
Quick Answer: Kubernetes separates transient container storage from persistent data through PersistentVolume (PV) and PersistentVolumeClaim (PVC) abstractions. StorageClasses enable dynamic volume provisioning via Container Storage Interface (CSI) drivers, freeing operators from manual storage allocation. PV access modes (RWO, ROX, RWX, RWOP) determine node mounting capabilities, while reclaim policies (Retain, Delete) define storage lifecycle behavior when claims are deleted.
Managing state in containerized environments presents unique challenges. Containers are designed to be disposable and stateless, meaning data stored directly inside a container's root filesystem disappears when the container crashes or restarts. To run stateful applications—such as databases, key-value stores, and file management systems—Kubernetes provides a robust suite of storage abstractions that separate data persistence from container lifecycles.
Ephemeral vs. Persistent Storage
In Kubernetes, storage resources fall into two fundamental categories based on their lifecycle behavior:
| Storage Type | Characteristics & Drivers | Best Used For |
|---|---|---|
| Ephemeral Storage | Tied directly to the lifecycle of a Pod. Data is created when the Pod starts and completely erased when the Pod is deleted or rescheduled. Implemented using emptyDir or hostPath. | Temporary scratch space, caching layers, log buffering, or sharing temporary data between containers in a single Pod. |
| Persistent Storage | Independent of Pod lifecycles. Data persists across Pod restarts, container crashes, and node migrations. Implemented via cloud block storage (AWS EBS, GCP Persistent Disk), SAN/NAS, or distributed filesystems (Ceph). | Relational databases (PostgreSQL, MySQL), stateful stores (Kafka, Elasticsearch), and persistent user file uploads. |
PV & PVC Decoupling Architecture
To maintain clear organizational boundaries, Kubernetes decouples storage infrastructure details from application storage requests using two complementary API resources: PersistentVolumes (PVs) and PersistentVolumeClaims (PVCs).
This separation follows a role-based operational model:
| Resource | Responsibility & Scope | Description |
|---|---|---|
| PersistentVolume (PV) | Cluster Administrator (Cluster-Scoped) | A piece of storage in the cluster that has been provisioned manually by an admin or dynamically by a StorageClass. Contains infrastructure details such as disk capacity, driver type, NFS endpoints, or cloud volume IDs. |
| PersistentVolumeClaim (PVC) | Application Developer (Namespace-Scoped) | A request for storage by a user or workload. Specifies storage size requirements, access modes, and optional StorageClass filters without referencing underlying storage hardware. |
+-------------------------------------------------------------+
| Storage Lifecycle |
| |
| +-------------------+ +------------------+ |
| | Developer (PVC) | ---Binds---> | Admin/CSI (PV) | |
| | (Size, Access) | | (Capacity, Disk) | |
| +-------------------+ +------------------+ |
| | | |
| +------------ Mounts ------------+ |
| v |
| +--------------+ |
| | Stateful Pod | |
| +--------------+ |
+-------------------------------------------------------------+
The PV-PVC Binding Lifecycle
- Provisioning: Storage is provisioned either statically (admin creates PVs in advance) or dynamically (StorageClass creates PVs on demand).
- Binding: The Kubernetes control plane matches a user's PVC to a suitable PV based on capacity and access mode, establishing a strict 1-to-1 binding.
- Using: The Pod specifies the PVC in its volume definitions, and the container runtime mounts the volume into the container filesystem path.
- Reclaiming: When the user deletes the PVC, the PV's Reclaim Policy dictates what happens to the underlying storage volume.
StorageClasses & Dynamic Provisioning
Before StorageClasses were introduced, cluster administrators had to manually pre-provision dozens of PersistentVolumes (Static Provisioning). If no pre-provisioned PV matched a developer's PVC request, the PVC remained stuck in a Pending state indefinitely.
A StorageClass provides a blueprint for Dynamic Provisioning. It defines which volume plugin (provisioner) should be invoked and what parameters (e.g., disk type, IOPS, replication factors) should be passed to the underlying storage provider when a PVC is submitted.
StorageClass and PVC Example
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: fast-ebs
provisioner: ebs.csi.aws.com
volumeBindingMode: WaitForFirstConsumer
reclaimPolicy: Delete
parameters:
type: gp3
iops: "3000"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: db-data-pvc
namespace: database
spec:
accessModes:
- ReadWriteOnce
storageClassName: fast-ebs
resources:
requests:
storage: 50Gi
When the db-data-pvc manifest is created, the AWS EBS CSI provisioner automatically allocates a 50Gi gp3 volume in AWS and creates a corresponding PersistentVolume object bound to the claim.
Container Storage Interface (CSI)
Historically, Kubernetes included storage driver code directly inside the core Kubernetes codebase (known as in-tree drivers). This architecture posed major drawbacks: storage vendors had to wait for official Kubernetes release cycles to release bug fixes or new features, and third-party storage code running in the core API server created security and stability risks.
The Container Storage Interface (CSI) is an industry-wide specification developed jointly by the container-orchestrator communities — Kubernetes, Mesos, Cloud Foundry, and Nomad — that standardizes how storage vendors build out-of-tree storage plugins. It is a cross-project specification rather than a CNCF-hosted project, which is precisely why a single driver works across several orchestrators.
Architecture of a CSI Driver
CSI separates storage management into two decoupled components:
- CSI Controller Plugin (Cluster-Scoped): Operates as a deployment in the control plane. Handles high-level volume lifecycle operations such as volume creation, deletion, cloud attachment, detachment, and volume snapshotting (
CreateVolume,DeleteVolume,ControllerPublishVolume). - CSI Node Plugin (Node-Scoped): Runs as a
DaemonSeton every worker node. Handles node-level mounting operations, formatting block devices, and mounting directories into Pod containers (NodeStageVolume,NodePublishVolume).
CSI plugins enable features like volume resizing, volume snapshotting, inline ephemeral volumes, and volume cloning without modifying Kubernetes core source code.
Volume Access Modes & Reclaim Policies
Understanding how volumes are mounted and cleaned up is critical for designing fault-tolerant storage systems.
PersistentVolume Access Modes
| Access Mode | Abbreviation | Operational Capability | Typical Drivers |
|---|---|---|---|
| ReadWriteOnce | RWO | Volume can be mounted as read-write by a single node at a time. Multiple Pods on the same node can read/write. | Cloud Block Storage (AWS EBS, GCP PD, Azure Disk). |
| ReadOnlyMany | ROX | Volume can be mounted as read-only by many nodes concurrently. | Network File Systems (NFS), read-only media assets. |
| ReadWriteMany | RWX | Volume can be mounted as read-write by many nodes simultaneously. | Distributed File Systems (NFS, AWS EFS, CephFS). |
| ReadWriteOncePod | RWOP | Volume can be mounted as read-write by a single Pod across the entire cluster. (Introduced in K8s v1.22+). | Single-instance databases requiring strict single-writer lockouts. |
PersistentVolume Reclaim Policies
When an application developer deletes a PersistentVolumeClaim, the PV's Reclaim Policy instructs Kubernetes how to handle the released storage resource:
| Reclaim Policy | Behavior Upon PVC Deletion | Best Used For |
|---|---|---|
| Retain | The PersistentVolume remains in the cluster in a Released state. The data on the underlying physical storage is preserved. No other PVC can bind to it until an admin manually cleans it up. | Critical production databases where data loss prevention is paramount. |
| Delete | The PersistentVolume object and the actual underlying physical infrastructure storage (e.g., AWS EBS volume) are automatically deleted. | Dynamic workloads, stateless test environments, and standard cloud-native deployments. |
| Recycle (Deprecated) | Performs a basic data wipe (rm -rf /volume/*) on the volume to make it available for binding by a new claim. | Deprecated in favor of dynamic provisioning via CSI. |
Complete Manifest Example: Mounting Persistent Storage to a Pod
The following example demonstrates how a Pod consumes storage from a PVC bound to a dynamic StorageClass.
apiVersion: v1
kind: Pod
metadata:
name: postgres-db
namespace: database
spec:
containers:
- name: postgresql
image: postgres:15
ports:
- containerPort: 5432
volumeMounts:
- name: pgdata-volume
mountPath: /var/lib/postgresql/data
volumes:
- name: pgdata-volume
persistentVolumeClaim:
claimName: db-data-pvc
Key Takeaways
- Ephemeral vs. Persistent: Ephemeral storage (
emptyDir) dies with the Pod; persistent storage outlives Pod container lifecycles. - PV / PVC Separation: PVs define infrastructure storage resources (Admin); PVCs express storage requests (Developer).
- StorageClasses: Enable dynamic provisioning of underlying cloud or SAN storage volumes on demand.
- CSI Standard: Out-of-tree storage interface allowing third-party vendors to add volume functionality without editing core Kubernetes code.
- Access & Reclaim: Access modes (
RWO,ROX,RWX,RWOP) control node mounting limits, while reclaim policies (Retain,Delete) define post-deletion volume lifecycles.
Which Kubernetes storage abstraction allows application developers to request storage capacity without knowing the underlying cloud provider or hardware implementation details?
What is the primary advantage of the Container Storage Interface (CSI) over legacy in-tree volume plugins in Kubernetes?
What occurs when a PersistentVolumeClaim is deleted if the associated PersistentVolume has a reclaim policy set to Retain?