CSI, the Container Storage Interface, in Kubernetes
Learn how one standard plug lets Kubernetes use almost any storage system, from a cloud disk to a shared file server, how a volume is created, attached, and mounted step by step, and how to run persistent storage safely in production.
Think about how you plug a USB drive into a computer. You never ask whether the drive was made by the same company as the computer, or whether the computer knows that particular brand. Both sides follow the USB standard, so any drive works with any computer. The standard hides all the differences behind one shape of plug and one set of agreed rules.
The Container Storage Interface, usually called CSI, is the USB standard for storage in Kubernetes. It defines a common set of rules that lets Kubernetes create, attach, and use storage from any vendor, without Kubernetes needing to know how each vendor’s system works inside. This tutorial explains CSI from the ground up, follows a volume through its whole life, and shows the patterns, dangers, and habits that real teams depend on.
1Why Containers Need Storage Help
Containers are built to be disposable, but many applications need to remember things. That mismatch is the problem CSI helps to solve.
Containers forget everything
A container is a sealed package that holds a program and everything it needs to run. When Kubernetes starts a container, it gets a fresh, private file area. When the container stops or crashes, that file area is thrown away, together with everything written into it. This is by design, because it makes containers easy to replace, copy, and move.
For a simple web page that only shows information, this is fine. But a database, a message queue, or an application that stores uploaded photos must keep its data safe even if its container is replaced. The data must live somewhere outside the container, and it must be able to follow the application wherever Kubernetes moves it.
Storage comes in many shapes
Real organisations use very different kinds of storage. Public clouds offer virtual disks that attach to one machine. Data centres offer shared file servers that many machines can use at once. Some teams run their own storage software across a set of servers. Others use expensive vendor storage arrays. Each of these has its own commands, its own way of creating a volume, and its own way of attaching it.
Without a common rule book, Kubernetes would have to learn every one of these systems separately, and every storage vendor would have to modify Kubernetes itself to be supported. That would make Kubernetes huge, slow to update, and fragile. CSI solves this by defining one agreed interface between Kubernetes and any storage system.
Imagine a hotel that lets guests store their luggage. Some guests bring suitcases, some bring boxes, some bring huge trunks, and each wants it kept in a different kind of room. Without a system, the receptionist would need to learn how to operate every room type personally. With a standard luggage ticket system, the receptionist just hands out a ticket, and the storage staff of each room type know how to follow the ticket’s rules.
What applications need from storage
Persistence
Data must survive when a container or pod is restarted, replaced, or moved to another machine.
On-Demand Creation
A team should be able to ask for storage and get it automatically, without opening a ticket with an administrator.
Portability
The same application description should work whether it runs on a laptop, in one cloud, or in a data centre.
Protection
Teams need snapshots and copies so they can recover from mistakes and create test environments.
Growth
When a volume fills up, it should be possible to enlarge it without losing data or restarting everything.
Location Awareness
A volume should be created in the same zone or region as the machine that will use it.
Kubernetes should know what it wants from storage, such as “give me ten gigabytes” or “make a copy of this volume”, but should not need to know how each storage system does it. CSI is the translation layer that makes this possible.
2CSI: The Core Idea
CSI is a published standard that describes how an orchestrator and a storage system talk to each other. A driver is a program that speaks this standard on behalf of one storage system.
The idea in plain words
The Container Storage Interface is a specification, which means a written set of rules. It says which requests a storage plugin must understand, such as “create a volume”, “delete a volume”, “attach this volume to that machine”, and “make a snapshot”. It also says what answers the plugin must give. The requests and answers use a common communication method called gRPC.
Anyone can write a program that follows these rules. That program is called a CSI driver. A storage vendor or a community project writes one driver for their storage system, and the same driver can work with any orchestrator that supports CSI. Kubernetes is the best known, but other systems use the same standard.
CSI is like a universal travel adapter. The laptop, which is Kubernetes, has one kind of plug. The wall sockets around the world, which are the storage systems, come in many shapes. A small adapter, which is the CSI driver, sits in between and converts one shape into the other. The laptop never needs redesigning, and each country’s socket only needs one adapter.
Why this design is powerful
Because drivers live outside Kubernetes, storage vendors can release updates on their own schedule, without waiting for a new Kubernetes version. Because the interface is standard, a team that moves from one cloud to another only needs to change which driver its storage class uses, and the application description stays the same. And because the code for each storage system no longer sits inside Kubernetes, the core project becomes smaller, safer, and easier to maintain.
The vocabulary you will use
CSI Driver
A program that translates the standard CSI requests into the actions of one specific storage system.
Volume
A piece of storage that a pod can use, such as a cloud disk or a folder on a shared file server.
Provisioning
Creating a volume in the storage system, either ahead of time by an administrator or automatically when requested.
Attach
Connecting a volume to a particular machine, as if plugging a disk into a computer.
Mount
Making the contents of an attached volume appear as a folder that programs can read and write.
Snapshot
A saved point-in-time picture of a volume that can be used to restore or copy it.
Topology
Where a volume physically lives, such as which zone or rack, and which machines can reach it.
Sidecar
A helper container, run beside the driver, that watches Kubernetes and turns its events into CSI requests.
CSI was designed by several communities together, so the same driver can serve more than one orchestrator. This tutorial focuses on Kubernetes, but the ideas apply to the standard as a whole.
3Kubernetes Storage Building Blocks
CSI plugs into a set of Kubernetes objects that describe storage from the application’s point of view. Let us meet them before looking inside the driver.
Pod
The smallest unit Kubernetes runs. A pod lists the volumes it needs and where each should appear inside its containers.
PersistentVolumeClaim
A request for storage, written from the application’s side: how much, what access, and which class of storage.
PersistentVolume
The Kubernetes record of an actual piece of storage in the backend. A claim is matched, or bound, to one.
StorageClass
A named recipe that says which driver to use and with which settings, such as fast disk, cheap disk, or encrypted disk.
StatefulSet
A workload type for applications that need stable identity and their own storage, creating one claim for each replica.
Kubelet
The agent on each node that starts containers and, for storage, asks the driver to make volumes ready on its machine.
Scheduler
The component that picks a node for each pod. For storage, it also considers where the volume can be reached.
VolumeAttachment
A record that says a volume should be attached to a particular node, used to coordinate the attach step.
VolumeSnapshot
A request to save a point-in-time copy of a volume, with matching content and class objects behind it.
CSIDriver and CSINode
Records that describe an installed driver’s abilities and which drivers are ready on each node.
Claims and volumes: the request and the reality
The most important pair to understand is the claim and the volume. A developer writes a claim, which says “I need twenty gigabytes of storage that one pod can write to”. The claim describes the need, not the source. The actual storage that satisfies it is described by a persistent volume. Kubernetes matches each claim to a suitable volume, and once matched, they are said to be bound.
This separation is deliberate. The developer never needs to know whether the storage is a cloud disk or a file server. The person managing the cluster decides which storage classes exist, and the developer simply picks one by name.
Think of booking a table at a restaurant. The claim is your reservation request: a table for four, by the window if possible. The persistent volume is the actual table that gets assigned to you. You do not need to know which waiter manages which table, or how the kitchen is arranged. The restaurant matches your request to a real table and hands you the keys.
Storage classes: named recipes
A storage class is a recipe for making volumes. It names the driver that will do the work, and it carries settings such as the disk type, whether the data is encrypted, and what happens to the volume when it is no longer needed. A cluster often has several classes, for example one for fast solid-state disks and one for cheaper, slower storage.
Many beginners think a persistent volume claim contains the data. It does not. It is only a request. The data lives in the storage backend, and the claim and volume objects are just Kubernetes records that point to it.
4Before CSI: In-Tree Plugins and FlexVolume
Understanding what came before CSI explains why it was needed, and why so many clusters have gone through a migration.
In-tree plugins: storage code inside Kubernetes
In the early days, support for each storage system was written directly into the Kubernetes source code. These were called in-tree plugins, because they lived inside the main tree of code. There were plugins for the big cloud disks and for several file and block storage systems, all compiled into the same programs that made up Kubernetes.
This approach was simple at first, but it grew painful. A bug in one storage plugin could affect the whole system. Vendors had to wait for a Kubernetes release to ship a fix or a new feature. The project had to maintain code for dozens of systems it did not control. Security issues in any of it became security issues for Kubernetes itself.
FlexVolume: a first step outside
FlexVolume was an early attempt to move storage code out of the core. A vendor provided an executable file placed on every node, and the kubelet ran it to attach and mount volumes. This let vendors ship drivers independently, but it had real limits. The executable had to be installed on each host, it could not easily use the cluster’s own features, and it lacked support for many operations such as snapshots and resizing.
CSI: the lasting answer
CSI was created to give a proper, complete, and stable answer. It reached general availability in Kubernetes in late 2018. It runs drivers as ordinary containers, so they can be deployed, upgraded, and monitored the same way as any other application. It also defines a rich set of operations, so features like snapshots, cloning, expansion, and topology awareness became possible for every driver.
In-tree plugins
Storage support written into Kubernetes itself. Simple at first, but tightly coupled, slow to change, and a burden on the project.
FlexVolume
Out-of-tree executables run by the kubelet. An improvement, but limited in features and awkward to install.
CSI
A standard interface with drivers running as containers, rich features, and independent release cycles.
Migration
Older in-tree volume types are redirected to their matching CSI drivers, and in-tree code has been removed in recent versions.
In-tree plugins were like a company that hired a specialist for every supplier and put them all on the permanent staff. FlexVolume was like giving each supplier a phone number to call. CSI is like a proper standard contract that every supplier signs, so suppliers can join, improve, and leave without changing the company’s own staff.
What the migration means for you
If you have older clusters that use the built-in cloud disk types, Kubernetes has been quietly translating those requests to the matching CSI driver. In recent versions, the old in-tree code is gone, and you must install the CSI driver yourself, or use a managed service that installs it for you. Existing volumes keep working, but you should learn which driver serves them and keep it up to date.
Before upgrading a cluster across the versions where in-tree plugins were removed, confirm that the matching CSI driver is installed and working. A missing driver means new volumes cannot be created and existing ones may fail to attach.
5Architecture: The Parts of a CSI Driver
A CSI driver is not one program. It is a small team of containers, some running centrally and some on every node, each with a clear job.
Every CSI driver is made of two halves plus a simple identity check. The controller half handles jobs that concern the whole cluster, such as creating and deleting volumes and attaching them to machines. The node half runs on each machine and handles jobs that must happen locally, such as mounting a volume into a pod’s directory. Both halves are described in the diagram below.
flowchart LR
K["Kubernetes control plane and kubelet"] --> S["Sidecars turn Kubernetes events into CSI calls"]
S -->|"gRPC over a local socket"| D["CSI driver with controller and node plugins"]
D --> B["Storage backend: cloud disk, file share, or storage array"]
Read the figure from left to right. Kubernetes does not talk to the driver directly. Small helper containers called sidecars watch Kubernetes for events, such as a new claim or a new attachment, and turn each event into a CSI request. They send the request to the driver over a local connection. The driver then talks to the real storage system, using whatever method that system understands.
The three services in every driver
Identity Service
Tells Kubernetes the driver’s name, version, and abilities, and answers health checks. Every driver has it.
Controller Service
Creates and deletes volumes, attaches and detaches them, and manages snapshots and resizing, working at the storage system level.
Node Service
Runs on every node and prepares volumes there: formatting, mounting, and unmounting them for pods on that machine.
The sidecar helpers
The Kubernetes community maintains a set of ready-made sidecar containers so that each driver author does not have to reinvent the watching logic. The driver author writes only the storage-specific part, and the sidecars do the rest. Each sidecar has a single responsibility.
flowchart TD
subgraph CS["Controller side, run as a Deployment"]
P["external-provisioner"] --> CP["Controller plugin"]
A["external-attacher"] --> CP
R["external-resizer"] --> CP
SN["external-snapshotter"] --> CP
end
subgraph NS["Node side, run as a DaemonSet on every node"]
N["node-driver-registrar"] --> NP["Node plugin"]
end
external-provisioner
Watches for new claims and asks the driver to create matching volumes, then creates the volume records in Kubernetes.
external-attacher
Watches attachment records and asks the driver to connect or disconnect volumes from machines.
external-resizer
Watches for claims whose requested size has grown and asks the driver to enlarge the volume.
external-snapshotter
Watches snapshot requests and asks the driver to create or delete snapshots in the storage system.
node-driver-registrar
Runs on every node and tells the kubelet that a driver is available there, and how to reach it.
livenessprobe
Checks that the driver is alive and reports its health, so Kubernetes can restart it if it gets stuck.
Think of a shipping company. The head office, which is the controller side, books shipments, reserves containers, and cancels orders for the whole company. The local depots, which are the node side, load and unload trucks on the ground. The sidecars are the clerks who read incoming orders and hand the right paperwork to whoever does the actual work.
Controller jobs can run anywhere in the cluster and need permission to call the storage system’s interface. Node jobs must run on the exact machine where the pod is, and need deep access to that machine’s file system. Keeping them apart limits how much power each part needs.
6Internal Working: Dynamic Provisioning
Dynamic provisioning is what makes storage feel like a cloud service: you ask, and a volume appears. Here is what happens behind the scenes.
Static versus dynamic
In the older, static way, an administrator creates volumes by hand ahead of time and registers each one in Kubernetes. Developers then claim from that fixed pool. This works, but it needs a person for every volume and often wastes space, since the pre-made volumes rarely match what teams truly need.
In dynamic provisioning, nobody creates volumes in advance. A developer creates a claim that names a storage class. The system notices the claim, asks the driver to create a matching volume on demand, and binds the two together. The volume exists exactly when it is needed, and with exactly the size that was requested.
sequenceDiagram
participant U as User
participant A as API Server
participant P as external-provisioner
participant D as CSI Controller Plugin
participant B as Storage Backend
U->>A: Create a claim that names a storage class
P->>A: Watch sees the new claim
P->>D: CreateVolume request
D->>B: Create the disk or share
B-->>D: Volume identifier
D-->>P: Volume created
P->>A: Create the volume record and bind it to the claim
A claim is created
A developer or a StatefulSet template creates a claim that states the size, access mode, and storage class.
The provisioner notices it
The external-provisioner sidecar sees a claim whose class names its own driver, and decides it is responsible.
The driver creates the volume
The provisioner calls the driver’s create operation, passing the size and the class settings. The driver creates the volume in the storage system and returns its identifier.
The volume record is created
The provisioner writes a persistent volume object into Kubernetes, containing the driver name and the volume identifier.
The claim is bound
Kubernetes links the claim to the new volume. The claim now shows as bound, and pods that use it can proceed.
Static provisioning is like a car rental company that parks every car it might ever need on the lot in advance. Dynamic provisioning is like a ride service. You request a car with certain requirements, and one is produced for you at that moment, sized for your trip, and released when you are done.
Waiting for the pod: the binding mode
A storage class has a setting called the volume binding mode. With the immediate mode, the volume is created as soon as the claim appears. The problem is that the system has not yet decided where the pod will run, so the volume may be created in a zone where the pod cannot use it.
With the wait-for-first-consumer mode, the system waits until a pod that uses the claim is scheduled to a machine. Only then does it create the volume, in a location that suits that machine. For any storage tied to a zone, such as a cloud disk, this is almost always the right choice.
With wait-for-first-consumer, a claim stays in a pending state until some pod uses it. Beginners often think it is broken. It is not. Create a pod that uses the claim, and the volume will be provisioned.
7Internal Working: Attach, Stage, Publish, and Teardown
Creating a volume is only the beginning. Before a container can read a single byte, the volume must travel through several more steps.
Three steps to get a volume ready
Once a pod that uses a bound claim is scheduled to a machine, three things must happen. First the volume must be attached, meaning connected to that machine, like plugging a disk into a computer. Second it must be staged, meaning prepared once on the machine: formatted if it is brand new, and mounted at a shared staging folder. Third it must be published, meaning made visible inside the specific pod’s own folder.
Staging and publishing are separate because several pods on the same machine may share one volume. The volume is staged once per machine, and then published once for each pod that uses it, usually with a lightweight bind mount, which is a way of showing the same folder in a second place.
sequenceDiagram
participant K as Kubelet
participant AC as external-attacher
participant CD as Controller Plugin
participant ND as Node Plugin
participant B as Storage Backend
Note over AC,CD: A pod is scheduled to a node
AC->>CD: ControllerPublishVolume
CD->>B: Attach the volume to the node
K->>ND: NodeStageVolume
ND->>ND: Format if new, mount at the staging path
K->>ND: NodePublishVolume
ND->>ND: Bind mount into the pod folder
K->>K: Start the containers with the volume
The attachment is requested
A Kubernetes controller creates an attachment record that says “this volume should be on that node”. The external-attacher sidecar sees it and calls the driver’s controller-publish operation.
The backend connects the volume
The driver asks the storage system to attach the disk to the machine, for example by calling the cloud provider. The attachment record is marked as attached.
The kubelet stages the volume
The kubelet on that machine calls the node plugin’s stage operation. The plugin finds the new disk, formats it with a file system if it is empty, and mounts it at a staging path.
The kubelet publishes it to the pod
The kubelet calls the node plugin’s publish operation, which bind mounts the staged volume into the pod’s own directory, with the requested permissions.
The containers start
With the folder in place, the kubelet starts the containers, and the application sees the volume as an ordinary directory.
Imagine moving a filing cabinet into an office. Attaching is wheeling the cabinet into the building. Staging is placing it in the corridor and unlocking it once. Publishing is giving each team a labelled key to the drawer they are allowed to use. Only then can people start filing documents.
Tearing it down again
When a pod stops, the steps run in reverse. The volume is unpublished from that pod, then unstaged from the machine if no other pod there still uses it, and finally detached from the machine by the driver. Only after detaching can the volume be attached elsewhere, if the pod is being moved.
When machines fail
The teardown order creates a well-known trap. Many volumes can be attached to only one machine at a time. If a machine dies suddenly, it cannot unstage or unpublish anything, so the volume may remain attached to the dead machine. A replacement pod on another machine is then stuck waiting, because the backend still believes the volume is in use elsewhere.
Kubernetes handles this with a timeout. After a period of several minutes, it forces the detach on machines that are unreachable, and the replacement pod can proceed. This delay is a real part of failure recovery, and it is why databases on single-attach disks do not fail over instantly.
If a pod is rescheduled while its volume is still attached elsewhere, you may see an error saying the volume is already used by another node. This is normal for a short time. If it lasts long, look for a stuck old pod, a dead machine, or an attachment record that never got cleaned up.
Some storage systems, such as network file shares, need no attach step, because any machine can reach them over the network. A driver declares this in its description, and Kubernetes skips the attach phase for it.
8Storage Types and Access Modes
Not all storage is alike. The type of storage decides who can use a volume, how many at once, and how the data looks to the application.
Block, file, and object storage
Block storage
A raw disk that one machine formats and uses like its own hard drive. It is fast and suits databases. Cloud virtual disks are the most common example. Usually a block volume can be used by one machine at a time.
File storage
A shared folder served over the network, where many machines can read and write the same files at once. It suits shared content and applications that need several writers. It is often slower and more variable in speed than a local disk.
Object storage
A store of whole objects, such as images or backups, reached through a web interface instead of a normal folder. Some CSI drivers make a bucket look like a folder, but it behaves differently from a real file system, and is best used for reading large files.
Access modes: who may use the volume
When a claim is created, it states an access mode. This describes how many machines or pods may use the volume, and whether they may write. The driver and the storage system decide which modes they can honestly support.
| Access mode | Meaning | Typical backends |
|---|---|---|
| ReadWriteOnce | Read and write by pods on a single node | Cloud block disks |
| ReadOnlyMany | Read only by pods on many nodes | Shared file systems, read-only images |
| ReadWriteMany | Read and write by pods on many nodes | Network file systems, distributed file systems |
| ReadWriteOncePod | Read and write by exactly one pod in the whole cluster | Drivers that support the stricter single-pod rule |
Access modes are like rules for a shared notebook. One rule says only one person at a time in a room may write in it. Another lets many people read it but nobody write. Another lets many people write together, which needs a very special notebook designed to handle that. The strictest rule says only a single named person may ever touch it.
Volume modes: files or raw blocks
Most volumes are presented as a file system, meaning a folder tree that the application uses normally. Some specialised applications, such as certain databases, prefer to receive the raw block device directly and manage the layout themselves. Kubernetes supports both, called filesystem mode and block mode, and the driver must support the one requested.
The name is misleading. It allows several pods on the same node to use the volume together. If you truly need to guarantee a single writer, use the stricter single-pod mode where your driver supports it, and design your application to cope with that limit.
A claim can ask for a mode that the storage cannot deliver, and the request will simply fail or hang. Read your driver’s documentation, and match your claim to what the storage system really supports.
9StorageClasses, Topology, and Policies
A storage class is where a cluster’s storage decisions live. Understanding its settings lets you shape cost, speed, safety, and behaviour.
What a storage class contains
Provisioner
The name of the CSI driver that will create the volumes. It is the link between the class and the driver.
Parameters
Driver-specific options such as disk type, speed, encryption, or file system. Each driver defines its own list.
Reclaim Policy
What happens to the volume when its claim is deleted: delete it with its data, or retain it for manual recovery.
Volume Binding Mode
Whether the volume is created at once or only when a pod needs it. Wait-for-first-consumer respects placement.
Allow Volume Expansion
Whether claims of this class may be enlarged later by editing their requested size.
Mount Options
Extra options used when mounting the volume, such as tuning for network file systems.
Allowed Topologies
A limit on which zones or locations volumes of this class may be created in.
Default Marker
An annotation that makes a class the one used when a claim does not name any class.
A storage class is like a menu of set meals at a restaurant. One meal is small and cheap, one is large and fast, and one comes with extra safety features. Customers choose a meal by name, and the kitchen knows which ingredients and methods to use. The customer does not need to write the recipe.
Reclaim policy: what happens to your data
The reclaim policy is one of the most important safety settings. With the delete policy, removing the claim removes the volume and its data from the storage system. This is convenient and clean, but it means an accidental deletion of a claim is an accidental deletion of data. With the retain policy, the volume and data are kept after the claim is gone, and an administrator must clean up or reuse it by hand.
Dynamically created volumes usually inherit the delete policy by default. For data that matters, many teams create a separate class with retain, and use it for production databases.
Topology: keeping volume and pod together
Many storage systems are tied to a location. A cloud disk in one zone cannot be attached to a machine in another zone. CSI drivers report the topology of each machine and each volume, and the scheduler uses this to keep pods and their volumes together. With wait-for-first-consumer binding, the volume is created in the zone where the pod was placed, so the two always match.
| Goal | Class setting to use | Why |
|---|---|---|
| Avoid zone mismatches | Wait-for-first-consumer binding | Volume is created where the pod runs |
| Protect important data from accidental deletion | Retain reclaim policy | Data survives the removal of the claim |
| Let volumes grow later | Allow volume expansion | Avoid rebuilding when a disk fills up |
| Offer cheap and fast options | Several classes with different parameters | Teams choose by name |
| Limit where data may live | Allowed topologies | Supports data residency and cost rules |
If a claim names no class, the default class is used. Teams sometimes forget which class is the default, and important data ends up on cheap or unsafe storage with the delete policy. Check your default class deliberately, and consider whether you want one at all.
10Advanced Features: Snapshots, Clones, Expansion, and Ephemeral Volumes
Because CSI defines a rich set of operations, drivers can offer much more than plain volumes. Here are the features that matter most in practice.
Volume snapshots
A snapshot is a saved, point-in-time picture of a volume. You create one by requesting a snapshot object that refers to a claim. Kubernetes asks the driver to make the snapshot, and you can later create a new volume from it. Snapshots are quick to take, and are useful before risky changes like upgrades.
Volume cloning
A clone is a new volume created directly from an existing one. You make a new claim that names the source claim as its data source. Clones are handy for creating test environments from real data, without touching the original.
Volume expansion
When a volume fills up, you edit the claim to request a larger size. The resizer asks the driver to enlarge the volume, and the node plugin then grows the file system. Volumes can grow, but they cannot shrink, so growth is a one-way step.
Ephemeral volumes
Some volumes are meant to live only as long as a pod. Generic ephemeral volumes create a claim automatically for the pod, and delete it when the pod ends. This gives short-lived scratch space with the full power of any storage class, such as very large or very fast temporary disks.
Raw block volumes
A volume can be given to a container as a raw block device instead of a file system. Applications that manage their own storage layout can then work directly with the disk.
Storage capacity tracking
Some drivers report how much free space remains in each location. The scheduler then avoids placing pods where their new volume could not be created, which reduces confusing pending states.
Volume health monitoring
Drivers that support it can report when a volume has become unhealthy, and Kubernetes records this as an event, so problems are noticed before applications fail.
| Feature | What it gives you | What to watch for |
|---|---|---|
| Snapshot | Quick point-in-time copy for rollback or restore | Usually stored with the same system, so not a full backup |
| Clone | Fast copy for tests or new environments | Copies data, including any sensitive content |
| Expansion | Grow a volume without recreating it | Cannot shrink, and some drivers need a pod restart |
| Ephemeral volume | Scratch space tied to the pod’s life | Data is lost when the pod is removed |
| Raw block | Direct device access for specialised applications | Application must manage its own layout |
A snapshot is like photographing a whiteboard before erasing it: you can always reconstruct what was written. A clone is like photocopying the whole notebook so someone else can scribble in it. Expansion is like adding extra pages to a notebook that is full, though you can never remove pages once added.
Most snapshots live in the same storage system as the original volume. If that system fails, or the account is compromised, both the volume and its snapshots may disappear together. Real backups are copied to a separate place. Also note that snapshots of running databases may be crash-consistent only, unless the application is paused first.
11Data Flow and the Lifecycle of a Volume
A volume has a whole life: it is requested, created, bound, used, released, and finally kept or deleted. Each stage has its own traps.
flowchart TD
A["Claim created"] --> B{"Binding mode?"}
B -->|"Immediate"| C["Volume created at once"]
B -->|"WaitForFirstConsumer"| D["Wait until a pod is scheduled"]
D --> C
C --> E["Volume bound to claim"]
E --> F["Pod uses the volume"]
F --> G["Pod and claim deleted"]
G --> H{"Reclaim policy?"}
H -->|"Delete"| I["Volume and data removed"]
H -->|"Retain"| J["Volume kept for manual recovery"]
The states a volume passes through
Pending
A claim exists but has no volume yet. This is normal for a short moment, or for a long time if the binding mode waits for a pod.
Bound
The claim and a volume are linked. Pods that use the claim can now be scheduled and can get their volume attached and mounted.
In use
Pods read and write data. While a pod uses the claim, Kubernetes protects it from being removed by accident.
Released
The claim has been deleted, but the volume still exists. With the retain policy, it stays in this state until an administrator handles it.
Deleted or failed
With the delete policy, the driver removes the volume from the storage system. If cleanup fails, the volume record shows a failed state and needs attention.
Think of renting a storage unit. You ask for a unit and wait until one is ready, which is the pending stage. You receive a key, which is binding. You keep your belongings inside, which is use. When you stop renting, the owner either empties the unit for the next tenant, which is the delete policy, or locks it and holds your belongings until you collect them, which is the retain policy.
Protection against accidents
Kubernetes adds special markers called finalizers to volumes and claims that are in use. A finalizer blocks deletion until Kubernetes has finished its cleanup work. This prevents you from removing a claim while a pod still uses it. It also explains why a claim can appear stuck in a terminating state: something is still using it, or a cleanup step has not completed.
Deleting the finalizer from a stuck claim or volume makes the object disappear, but it may leave the real volume behind in the storage system, still costing money, or worse, still attached. Find out why it is stuck first.
Deleting Kubernetes objects and deleting the actual data are two different things. Always check the storage system itself, such as the cloud console, after cleanup, to make sure leftover volumes are not silently accumulating.
12Security in CSI
Storage holds your most valuable data, and CSI drivers run with powerful access. Security has to be designed in from the start.
A CSI driver has two sources of power. The controller side can create, delete, and attach volumes in your storage system, often using cloud permissions. The node side must mount file systems on the machine, so it runs with high privileges and deep access to the machine’s file layout. Both deserve careful control.
Least-Privilege Cloud Access
Give the controller only the storage permissions it needs, using workload identity features rather than long-lived keys.
Encryption at Rest
Use storage class options to encrypt volumes, ideally with keys you manage yourself for sensitive data.
Encryption in Transit
For network file systems and remote storage, use options that encrypt data as it crosses the network.
Secrets for Storage Systems
Store storage credentials in Kubernetes secrets, protect them with access control, and reference them from the class rather than hard-coding them.
Restrict Who Can Claim
Use access control and quotas so teams can only create claims in their own namespaces and within their storage budgets.
Protect Snapshots
Treat snapshot and clone permissions as seriously as access to the data, because they can copy everything the volume holds.
Trusted Driver Images
Use images from trusted sources, check them for known weaknesses, and keep drivers up to date with security fixes.
File Permissions
Use the pod’s group settings so that only the intended processes can read and write the mounted data.
A storage driver is like the warehouse manager who holds the master keys to every locker. The company must be careful about who becomes manager, which keys they carry, how their actions are recorded, and how the keys are protected if the manager’s office is broken into.
Leftover data is a risk
Volumes are reused and deleted, and old data may remain. When a volume is released with the retain policy and later reused, the previous owner’s data may still be there. When a volume is deleted, the backend may or may not wipe the underlying storage before reusing it. For sensitive data, know how your storage system handles deletion, and use encryption so that discarded data is unreadable.
Sharing volumes across tenants
Shared volumes used by several teams create a shared blast radius. A bug or compromise in one application can corrupt or expose data used by others. Where isolation matters, give each tenant its own volumes, and use quotas to keep one tenant from filling the whole storage system.
The node plugin runs with elevated rights on every machine and often has access to the whole file layout of the machine. A vulnerable or malicious driver can therefore reach much more than storage. Install drivers only from sources you trust, keep them patched, and limit who can change their configuration.
13Monitoring, Logging, Metrics, and Troubleshooting
Storage problems are quiet until they are catastrophic. A full disk or a stuck attachment can halt an application with no warning, unless you are watching.
Watching storage is like watching the fuel gauge and warning lights in a car. You do not wait for the engine to stop. You look at how full the tank is, and you notice the warning light early enough to act. The signals below are the fuel gauge and warning lights for your volumes.
What to watch
Space Used
The kubelet reports how much of each volume is used. Alert well before a volume becomes full, because full disks crash databases.
Inodes Used
A file system can run out of file entries while free bytes remain. Applications creating many small files hit this first.
Pending Claims
Claims that stay pending for long point to a missing class, a wrong topology, or a driver that is not working.
Attach and Mount Errors
Events that report failed attaches or mounts show that a pod cannot get its volume, and usually name the reason.
Provisioning Time and Failures
How long it takes for a volume to appear, and how often creation fails. Sudden slowness often means the backend is struggling.
Backend and Cloud Limits
Errors from the storage system, including throttling and quota limits, and the maximum number of volumes per machine.
Kubernetes and its add-ons publish many of these as metrics that monitoring tools can collect, including volume usage figures from the kubelet and the state of claims and volumes from the cluster’s state exporters. The sidecars also expose their own metrics about how many operations they performed and how long they took. Events on pods and claims give the human-readable story, and they are usually the first place to look.
Logs that help
When something goes wrong, three log sources tell the story. The logs of the driver and its sidecars show what requests were made and how the storage system answered. The kubelet log on the affected machine shows the mount and unmount steps. The storage provider’s own audit log shows what was actually done to the disks. Sending all three to a central store makes investigations much faster.
Untangling a stuck pod or claim
Look at the pod and claim events
Events usually name the failing step, such as a failed attach, a failed mount, or a failed provisioning, and often include the storage system’s error text.
Check the claim’s state
Is it pending, bound, or terminating? If pending, check the class name, the binding mode, and whether any pod is using it.
Check the driver
Confirm that the controller and node pods are running, that the driver is registered on the affected machine, and read their logs for errors.
Check the attachment
Look at the attachment record for the volume. If it points to a different machine, the volume may still be attached to an old one.
Check the backend
Look in the storage system or cloud console for quotas, limits, zone mismatches, or errors that Kubernetes cannot see directly.
Alerts worth setting up
Alert when a volume passes a chosen fullness, such as eighty percent, and again at ninety. Alert on claims pending beyond a set time, on volumes stuck in attach or detach, on failed snapshots, and on a driver pod that keeps restarting. Also review, periodically, volumes that exist in the storage system but no longer have a matching claim.
Trend the growth of each important volume. If a disk grows by a fixed amount each week, you can predict the date it fills and expand it in calm working hours, rather than at night during an outage.
14Advantages, Disadvantages, and Trade-offs
CSI solves a big problem, but running stateful applications on Kubernetes always comes with trade-offs worth understanding.
Advantages
- One standard interface works with many storage systems and vendors.
- Drivers are released and upgraded independently of Kubernetes itself.
- Applications describe storage in a portable way, without naming a vendor.
- Rich features such as snapshots, clones, expansion, and topology awareness are available across drivers.
- Storage can be requested on demand, without waiting for an administrator.
- Storage code no longer sits inside Kubernetes, which makes the core safer and smaller.
Disadvantages / Trade-offs
- You must install, upgrade, and monitor drivers yourself, unless a managed service does it for you.
- Features vary by driver, so the standard does not guarantee every capability everywhere.
- Single-attach volumes make failover slower after a machine failure.
- Performance depends heavily on the backend, and network storage adds latency.
- Node plugins run with high privileges, which increases the security responsibility.
- Portability of the application does not mean portability of the data, which still has to be moved.
Thinking about cost honestly
Storage costs come from several places. There is the price of the disks or shares themselves, which is often charged for the size you ask for, not the size you use. There is the price of snapshots, which grow as data changes. There is the cost of performance, since faster storage classes cost more. And there is the cost of forgotten volumes, which continue to be billed even after the application that used them is gone.
The best defence is visibility. Track which volumes exist, who owns them, and how full they are. Use quotas to limit runaway requests, and choose storage classes deliberately, so cheap storage is used for cheap needs.
Choosing the right kind of storage
| Need | Good fit | Why |
|---|---|---|
| Temporary scratch space that can be lost | Pod-local temporary storage | Simple and fast, and discarded with the pod |
| A database that needs speed and durability | Block volume through a CSI driver | Low latency and one writer |
| Files shared by many pods | Shared file storage through a CSI driver | Many machines can read and write together |
| Very large read-mostly datasets | Object storage, sometimes mounted | Cheap and scalable, with different behaviour from a file system |
| Very high performance on one machine | Local disks with careful placement | Fast, but tied to that machine and lost if it fails |
| You do not want to operate storage software | A managed database or storage service | The provider handles backups, upgrades, and failover |
Kubernetes can run databases well, but it is not always the best home for them. If a managed service meets your needs, it may save your team a great deal of operational work. Choose stateful workloads on Kubernetes when you truly need the control they give.
15Design Patterns and Anti-patterns
A few reliable designs cover most storage needs. A few tempting shortcuts cause most of the lost data.
Patterns that work well
Tiered Storage Classes
Offer named classes for fast, standard, and archive needs, so teams pick by purpose and cost.
Wait-for-First-Consumer
Create volumes only when a pod is placed, so zone-bound storage always lands where the pod runs.
StatefulSet with Claim Templates
Give each replica of a stateful application its own volume, created and remembered automatically.
Retain Class for Critical Data
Keep a separate class with the retain policy for irreplaceable data, so a deleted claim never removes it.
Snapshot Before Change
Take a snapshot before upgrades or migrations, so you have a quick way back if something goes wrong.
Backups Outside the Cluster
Copy important data to a separate place with its own protection, in addition to any snapshots.
Anti-patterns to avoid
Problem
Production data is stored using a folder on the machine’s own disk, mounted directly into the pod.
Why It’s Harmful
The data is tied to one machine. If the pod moves or the machine fails, the data is gone or unreachable, and the folder gives the pod broad access to the machine’s files.
Correct Approach
Use persistent volumes provided by a CSI driver, and use local disks only when you understand and accept their limits.
Problem
Irreplaceable data lives on volumes whose class uses the delete reclaim policy.
Why It’s Harmful
Deleting the claim, by mistake or through a careless cleanup of a namespace, deletes the volume and its data with no way back.
Correct Approach
Use a retain class for critical data, and protect namespaces and claims with careful access rules.
Problem
Snapshots are treated as the only backup.
Why It’s Harmful
Snapshots usually live in the same storage system as the volume. A failure of that system, a deleted account, or a compromise can destroy the data and its snapshots together.
Correct Approach
Keep separate backups in another location, and test restoring from them regularly.
Problem
Volumes are created with immediate binding in a cluster that spans several zones.
Why It’s Harmful
The volume may be created in a zone where the pod cannot run, so the pod stays pending, and the mismatch is confusing to diagnose.
Correct Approach
Use wait-for-first-consumer binding for zone-bound storage, so the volume follows the scheduling decision.
16Best Practices and Common Mistakes
A short field guide collected from teams that run stateful applications on Kubernetes, and from mistakes that repeat.
Best practices
- Know your driver — read its documentation for supported access modes, features, limits, and upgrade notes.
- Keep drivers updated — treat them like any critical component, with a plan for security and compatibility updates.
- Use wait-for-first-consumer binding — especially for zone-bound storage in multi-zone clusters.
- Enable expansion — allow volumes to grow, and practise the expansion before you need it in an emergency.
- Choose reclaim policies deliberately — use retain for data you cannot recreate.
- Set the default class on purpose — know what a claim gets when it names no class.
- Apply storage quotas — limit how much storage and how many claims each namespace can use.
- Encrypt sensitive data — use encrypted classes and manage keys with care.
- Back up outside the cluster — and test restores, because an untested backup is only a hope.
- Alert on fullness and pending claims — catch problems while there is still time to act calmly.
- Handle graceful shutdown — make sure applications flush data and close files when pods stop.
- Review orphaned volumes — periodically compare the storage system with the cluster to find forgotten volumes.
Common mistakes
Teams monitor disk size but not inodes, and an application that creates millions of small files runs out of entries while gigabytes remain free. Watch both.
A team scales an application to several replicas on different machines and finds that only one can use the disk. Match the access mode to the storage type, and use shared file storage if many machines must write.
Removing a namespace removes its claims. With the delete policy, the volumes and data go with them. Check reclaim policies and take backups before large cleanups.
At least once, take a real backup, restore it into a fresh volume, and start the application from it. You learn how long it takes, what is missing, and whether the data is truly usable, while nothing is at stake.
17Real-World and Industry Examples
CSI drivers exist for nearly every kind of storage, and organisations use them in very different ways.
Cloud provider disks and file shares
Every major public cloud offers a CSI driver for its block disks and its shared file services. Managed Kubernetes services usually install the disk driver for you, so teams get working persistent storage from the first day, and add others as needs grow.
Databases on Kubernetes
Many teams run relational databases, search engines, and message brokers in the cluster, often through operators that manage claims, snapshots, and failover. The CSI driver provides the volumes, and the operator provides the database knowledge.
Self-managed storage in data centres
Organisations running their own hardware often use software-defined storage systems, such as Ceph, Longhorn, or OpenEBS, which run inside or beside the cluster and expose their volumes through CSI drivers. This gives cloud-like storage on private machines.
Enterprise storage arrays
Vendors of traditional storage arrays provide CSI drivers, so companies with existing investments can offer their arrays to Kubernetes users through the same storage class mechanism, and use features such as array-side snapshots.
Shared data for machine learning
Training jobs often read the same large datasets from many pods at once. Teams use shared file storage or mounted object storage through CSI, so data scientists see one dataset regardless of which machine their job lands on.
Test environments from production copies
Teams use snapshots and clones to create realistic test databases quickly. A snapshot of a production volume is turned into a fresh volume for each test run, after sensitive data has been handled according to policy.
Migrating from old built-in volume types
Many organisations have spent recent years moving from the older built-in volume types to CSI drivers, testing upgrades on non-critical clusters first, and confirming that snapshots, expansion, and monitoring keep working after the change.
18Frequently Asked Questions
Quick answers to the questions that come up most often when teams first work with CSI.
No. The driver is a separate program, usually run as containers in your cluster. Kubernetes only defines how to talk to it. Managed services often install common drivers for you.
A claim is a request for storage written by the application owner. A volume is the record of the actual storage. Kubernetes binds each claim to a matching volume.
Common reasons are a missing or misspelled class, a binding mode that waits for a pod, no capacity or wrong location in the backend, or a driver that is not running. The claim’s events usually say which.
No. Kubernetes supports growing volumes, not shrinking them. To reduce size, create a smaller volume and copy the data across.
The data stays, because it lives in the volume, not the pod. A new pod that uses the same claim sees the same data. The data is only removed when the claim and volume are deleted under a delete policy.
It depends on the access mode and the storage. Shared file storage supports many pods across many machines. Single-attach block disks allow sharing only among pods on the same machine, or only one pod with the strict mode.
No. Snapshots are usually kept in the same storage system and can be lost with it. Backups are stored elsewhere and should be tested by restoring them.
The volume may still be attached to the dead machine. Kubernetes waits for a timeout before forcing a detach, which can take several minutes. This is normal for single-attach storage.
Often the main disk driver is installed for you, but drivers for shared file storage or other systems may need to be added. Check your provider’s documentation.
It delays creating the volume until a pod that uses the claim has been scheduled, so the volume is created in the right location for that pod.
Not directly through Kubernetes objects. You usually copy the data by using backups, snapshots that the storage system can share, or a data copy tool, and then create a new claim in the target cluster.
Yes, many teams do, with proper volumes, backups, monitoring, and often a database operator. It needs care about failover time, performance, and recovery, so weigh it against managed database services.
19Summary and Key Takeaways
The Container Storage Interface gives Kubernetes a single, standard way to work with almost any storage system. Developers describe what they need through claims and storage classes, and drivers translate those requests into the actions of a specific system. Each volume moves through provisioning, attaching, staging, publishing, use, and eventual release, and the sidecar helpers turn Kubernetes events into the requests the driver understands.
The standard is powerful but not magic. Features depend on the driver, single-attach volumes slow failover, snapshots are not backups, and the driver itself runs with high privileges. Teams that choose storage classes with care, watch capacity, protect their data outside the cluster, and keep drivers updated find that persistent storage on Kubernetes becomes dependable and routine.
Key Takeaways
- CSI is the standard plug for storage — drivers translate Kubernetes requests into actions of a specific storage system, and they live outside Kubernetes itself.
- Claims describe needs, volumes describe reality — storage classes provide the recipes, and dynamic provisioning creates volumes on demand.
- A driver has a controller side and a node side — sidecars watch Kubernetes and call the driver, and each volume is created, attached, staged, and published in order.
- Choose modes and bindings deliberately — match access modes to the storage type, and use wait-for-first-consumer binding for zone-bound storage.
- Protect the data itself — choose reclaim policies with care, treat snapshots as a convenience and not a backup, and keep tested backups elsewhere.
- Secure the driver and the data — use least-privilege cloud access, encryption, quotas, and trusted, updated drivers, because node plugins are highly privileged.
- Watch space, inodes, and stuck attachments — alert early, plan growth, and read events and driver logs to unravel problems quickly.