Volumes in Kubernetes
A plain-English guide to how containers keep, share, and protect their data: from scratch space that vanishes with a pod to durable disks that outlive everything.
Imagine you build a small notes application and run it in a container. You write a few notes, then the container crashes and restarts. When it comes back, every note is gone. Nothing is broken. This is simply how containers are designed. They are built to be thrown away and replaced at any moment, and everything inside them goes away with them.
That design is wonderful for stateless web servers, but it is a problem the moment your application needs to remember something: a database, an uploaded photo, a shared cache, a log file, or even a password. Kubernetes answers this problem with volumes. A volume is a place to keep data that lives outside the short life of a single container.
In this guide you will learn what volumes are, why they exist, and how the different kinds behave. You will follow a piece of data from a request all the way down to a real disk. You will also learn the special vocabulary of Kubernetes storage, such as PersistentVolume, PersistentVolumeClaim, and StorageClass, one friendly step at a time. No earlier storage knowledge is needed, and every new word is explained the first time it appears.
1Why Containers Forget Everything
Before volumes make sense, you need to understand why containers lose their data in the first place.
A container is a running copy of a packaged application. The package is called an image. An image is a frozen, read-only bundle that holds your program and everything it needs. When a container starts, the system places a thin, writable layer on top of the image, and your program can create and change files there.
The catch is that this writable layer belongs to that one container only. When the container stops and a new one starts, Kubernetes builds a fresh container from the original image. The new container gets a brand new, empty writable layer. The old layer, along with everything you saved in it, is thrown away.
Think of a hotel room that is fully cleaned and reset after every guest. You may leave your notes on the desk, but the next morning the housekeeper resets the room to look exactly like the brochure photo. Your notes are gone. If you want to keep something, you must put it in a safe in the hotel lobby, which stays the same no matter which room you sleep in. A volume is that lobby safe.
Three problems volumes solve
Data must survive restarts
A database that forgets all its tables each time its container restarts is useless. Volumes keep the data safe across restarts.
Containers need to share files
Two containers in the same pod often work as a team, such as one writing logs and another shipping them away. They need a common folder.
Apps need configuration and secrets
Settings and passwords should not be baked into the image. Kubernetes delivers them as files through special volume types.
Even if you do not need durable storage, volumes are still used in almost every real pod. Service account credentials, configuration files, and temporary scratch folders are all delivered as volumes.
2What Is a Volume?
A volume is a directory, defined at the pod level, that containers can mount and use like a normal folder.
In Kubernetes, a volume is a folder that is declared as part of a pod, and then mounted into one or more containers at a path you choose. To mount means to attach a folder so that it appears at a certain location inside the container. From the application’s point of view, it is an ordinary folder. It reads and writes files the way it always does. The magic is in where those files really live and how long they last.
There are two steps to using a volume. First, the pod declares the volume and says what kind it is. Second, each container that wants to use it mounts it at a path. Different containers in the same pod can mount the same volume at different paths, and both see the same files.
flowchart TD
A["Container restarts"] --> B["Container filesystem is lost"]
A --> C["emptyDir data survives"]
A --> D["Persistent volume data survives"]
E["Pod is deleted"] --> F["Container filesystem is lost"]
E --> G["emptyDir data is lost"]
E --> H["Persistent volume data survives"]
Read the diagram carefully, because it holds the most important idea in this whole guide. Data can live at three different levels. The container’s own filesystem dies with the container. A pod-level scratch volume, called emptyDir, survives container restarts but dies with the pod. A persistent volume survives even when the pod is deleted.
What it is, why it exists, where it is used
What it is: a pod-level folder that containers mount and use.
Why it exists: containers are disposable, but data often is not. Volumes separate the life of the data from the life of the container.
Where it is used: databases, message queues, file uploads, machine learning datasets, shared caches, configuration delivery, secrets, and log collection.
A pod is like a shared apartment, and the containers are the roommates. A volume is a cupboard in the apartment that all roommates can open. If one roommate moves out and another moves in, the cupboard stays. If the whole apartment is emptied and closed, a simple cupboard goes with it, but a rented storage unit down the street keeps everything. That storage unit is a persistent volume.
3A Quick Kubernetes Refresher
A few basic words will make everything that follows easier to read.
Kubernetes is a system that runs containers across many machines and keeps them healthy. You describe what you want, and Kubernetes makes it happen and keeps it that way. Here are the parts that matter for storage.
Cluster
The whole group of machines managed together. Think of it as a large office building.
Node
One machine in the cluster, either physical or virtual. These are the floors of the building where work happens.
Pod
The smallest unit Kubernetes runs. A pod holds one or more containers that share a network address and, as you now know, volumes.
kubelet
The helper program on every node that starts pods and, importantly for this guide, prepares and mounts their volumes.
Scheduler
The part of Kubernetes that decides which node should run each new pod. Storage location can influence its choice.
API server
The front door of Kubernetes. Every request to create, change, or delete something goes through it and is recorded.
Two more ideas: stateless and stateful
A stateless application keeps nothing important between requests. A simple website that shows the same page to everyone is stateless. If a copy disappears, another copy can take over without anyone noticing.
A stateful application remembers things. A database remembers rows. A queue remembers messages that have not been processed. If such an application loses its memory, real damage happens. Stateful applications are the main reason persistent volumes exist.
4Architecture and Components
Storage in Kubernetes is teamwork between the control plane, the node, and the storage system.
The diagram below shows the main players. On the left, the control plane makes decisions and keeps records. In the middle, a worker node runs the pod and prepares the volume. On the right, a real storage system holds the bytes.
flowchart LR
subgraph CP["Control Plane"]
API["API Server"]
PVCtl["Volume controller"]
Sched["Scheduler"]
end
subgraph Node["Worker Node"]
Kubelet["kubelet"]
CSINode["CSI node plugin"]
subgraph Pod["Pod"]
C1["App container"]
C2["Sidecar container"]
end
Vol["Mounted volume folder"]
end
subgraph Storage["Storage System"]
Disk["Network disk or file share"]
end
API --> PVCtl
API --> Sched
Kubelet -.->|watches pod specs| API
Kubelet --> CSINode
CSINode --> Vol
C1 --> Vol
C2 --> Vol
Vol --> Disk
Meet the components
API server and etcd
Store every volume, claim, and storage class as a record. They are the memory and the front door of storage in Kubernetes.
Volume controllers
Match claims to volumes, create new volumes when asked, attach and detach disks, and clean up when a claim is deleted.
Scheduler
Picks a node for each pod and respects storage rules, for example placing a pod in the same zone as its disk.
kubelet
The node’s manager. It waits for volumes to be ready, mounts them, and only then starts the containers that need them.
CSI driver
A translator between Kubernetes and a specific storage system. It knows how to create, attach, and mount disks of that kind.
The real storage
A cloud disk, a network file server, or a local drive. This is where the bytes actually rest.
Kubernetes does not store your data itself. It coordinates other systems that store it. Kubernetes is the manager, and the storage system is the warehouse.
5Ephemeral Volumes: Storage That Lives and Dies With the Pod
Not all volumes are meant to last. Many are simply convenient folders that vanish with the pod.
An ephemeral volume is one whose life is tied to the pod. It appears when the pod starts and disappears when the pod is removed. These are the workhorses of everyday Kubernetes, and beginners meet them first.
emptyDir: the shared scratch folder
The emptyDir volume is the simplest type. It starts as an empty folder on the node when the pod is placed there. Every container in the pod can mount it. If a container crashes and restarts, the folder and its files are still there. If the pod is deleted, the folder is deleted too.
By default an emptyDir uses the node’s ordinary disk. You can instead ask for it to live in the node’s memory, which makes it very fast. Memory-backed folders are counted against the container’s memory limit, so a runaway program can fill memory and get stopped. You can also set a size limit so a single pod cannot swallow the whole disk.
An emptyDir is a whiteboard in a meeting room. Everyone in the meeting can write on it and read it. If one person leaves and comes back, the writing is still there. When the meeting ends and the room is cleaned, the board is wiped.
configMap, secret, downwardAPI, and projected
Some volume types do not store user data at all. They deliver information into files.
| Type | What it delivers | Good to know |
|---|---|---|
| configMap | Non-secret settings, each entry becoming a file | Updates arrive after a short delay, except when a single file is mounted through a sub-path |
| secret | Passwords, keys, and tokens as files | Held in memory on the node, not written to its disk |
| downwardAPI | Facts about the pod itself, such as its name and labels | Lets an app know who it is without asking Kubernetes |
| projected | Several sources combined into one folder | Often used to deliver short-lived service account tokens |
Generic ephemeral volumes
Sometimes you want temporary storage that is bigger or faster than what the node offers, or that comes from a particular storage class. A generic ephemeral volume creates a real claim on a real storage system when the pod is created, and removes it when the pod is deleted. It is the best of both worlds: the scale of network storage with the tidy life of a scratch folder.
Data in an emptyDir counts toward the pod’s local storage usage. If a pod writes too much, Kubernetes can evict it. Always set sensible size limits for scratch folders.
6Node-Local Volumes: hostPath and Local
Sometimes storage is a folder or drive on the node itself. This is fast and simple, and full of sharp edges.
hostPath: borrowing a folder from the node
A hostPath volume mounts a file or folder from the node’s own filesystem straight into the pod. It is easy to understand: the pod sees a folder that really exists on the machine. It is popular for quick experiments and for system-level tools that must look at the node itself, such as agents that read logs from the machine.
But it has serious drawbacks. If the pod moves to a different node, it sees a different folder, so the data seems to vanish. Pods running with a hostPath can read or even change important files on the node, which is a security risk. Because of these dangers, hostPath is discouraged for ordinary application data.
A hostPath is like letting a visitor use a drawer in your desk at home. It is convenient, but if the visitor visits a different house tomorrow, the drawer is different. And a visitor with access to your drawer might open something more private than you wanted.
local volumes: a safer way to use a node’s disk
A local volume also uses a disk attached to a specific node, but it is a proper persistent volume with a built-in rule: it can only be used on the node where the disk lives. Kubernetes knows this and places the pod on that node. Local volumes are prized for their speed, because the data does not cross a network. The trade-off is that if the node dies, the data is trapped on it until the node returns.
Why people choose local disks
- Very low delay and high speed.
- No network storage bill.
- Good for databases that already copy data between replicas.
Why people avoid them
- The pod is tied to one specific node.
- If the node fails, the data is unreachable.
- Disks usually must be prepared by hand or by extra tooling.
7Persistent Volumes and Claims
Persistent storage in Kubernetes uses two objects that beginners often mix up. Once you see the reason for the split, they become easy.
Kubernetes separates the people who provide storage from the people who use storage. Cluster administrators, or automated systems, create PersistentVolumes. Application developers create PersistentVolumeClaims. Kubernetes then matches them.
PersistentVolume (PV)
A piece of real storage that has been made available to the cluster: a cloud disk, a file share, or a local drive. It is a cluster-wide resource, not tied to any namespace.
PersistentVolumeClaim (PVC)
A request for storage, saying how much space is needed and how it will be used. It lives in a namespace, like the app that asks for it.
Imagine a self-storage company. The storage units in the building are the PersistentVolumes. A customer who walks in and says, “I need a medium unit that I can lock” is filing a PersistentVolumeClaim. The manager finds a unit that fits the request and hands over the key. The customer never needs to know which corridor or which shelf was used. The pod, in this story, is the customer’s van visiting the unit.
flowchart LR
Pod["Pod"] -->|mounts| Claim["PersistentVolumeClaim"]
Claim -->|bound to| Vol["PersistentVolume"]
Claim -->|asks for a class| SC["StorageClass"]
SC -->|creates through| Prov["CSI provisioner"]
Prov --> Vol
Vol --> Disk["Real disk in the storage system"]
How binding works
When a claim is created, Kubernetes looks for a volume that satisfies it. The volume must be at least as large as the request, must support the requested access mode, and must belong to the requested storage class. When a match is found, the two are bound together, one to one. No other claim can use that volume while the binding lasts. If no match exists and a storage class allows it, Kubernetes creates a new volume automatically, which is the topic of the next chapter.
Why the pod talks to the claim, not the volume
This indirection is deliberate. A developer’s pod description says only, “I need the claim named data.” It does not mention a cloud, a disk type, or a server address. The same pod description can then run on a laptop cluster with simple local storage, and in a large cloud cluster with fast replicated disks. Only the claim’s resolution changes. This makes applications portable.
Claims are namespaced, volumes are not. A claim in one namespace cannot be used by pods in another. If two teams need the same data, they need a shared file storage design, not a shared claim.
8StorageClasses and Dynamic Provisioning
Instead of hand-making every disk, modern clusters create them on demand.
In the early days, an administrator had to create volumes in advance and hope that they matched what developers later asked for. This is called static provisioning, and it still exists. Today most clusters use dynamic provisioning: when a claim arrives, the system creates a fitting disk on the spot.
The tool that makes this possible is the StorageClass. It is a menu of storage choices, such as “fast”, “cheap”, or “replicated”. Each entry says which driver creates the disk and with what settings. A claim picks a class by name. If the claim names none, the cluster’s default class is used, if one exists.
A StorageClass is like the menu at a print shop: standard paper, glossy paper, poster size. You do not walk into the back and craft the paper yourself. You choose from the menu and the shop prepares it when you order.
What a StorageClass decides
| Setting | What it controls | Why it matters |
|---|---|---|
| Provisioner | Which driver creates the disk | Selects the storage system, for example a specific cloud’s disk service |
| Parameters | Driver-specific options such as disk type or speed | Lets you offer fast and slow classes side by side |
| Reclaim policy | What happens to the disk when the claim is deleted | Delete removes the disk. Retain keeps it for manual recovery |
| Volume expansion | Whether claims may be made bigger later | Growing a disk is often needed as data increases |
| Binding mode | When the volume is created and bound | Immediate acts at once. Wait-for-first-consumer waits until a pod is placed |
Why “wait for first consumer” matters
Many cloud disks live in one specific zone, which is a separate building or area within a region. If a disk is created immediately in zone A, but the scheduler later places the pod in zone B, the pod can never use the disk. The pod is stuck.
The wait-for-first-consumer mode fixes this. Kubernetes waits until a pod that uses the claim has been scheduled. Only then does it create the disk, in the same zone as the chosen node. Disk and pod always end up together. For zone-bound storage this is nearly always the right choice.
sequenceDiagram
participant U as Developer
participant A as API Server
participant S as Scheduler
participant P as Provisioner
participant T as Attacher
participant K as kubelet
participant D as Storage System
U->>A: Submit claim and pod
S->>A: Choose Node A for the pod
P->>D: Create a new disk in the same zone
P->>A: Create volume and bind the claim
T->>D: Attach the disk to Node A
K->>D: Find the disk on Node A
K->>K: Format if new, then mount
K->>K: Place the folder inside the container
K->>A: Report pod running
9Access Modes and Volume Modes
Two settings decide who may use a volume at the same time and what shape the storage takes.
Access modes: who can share it?
An access mode describes how many nodes or pods may use a volume at once and whether they may write. The names look scary, but the ideas are simple.
| Mode | Short name | Meaning | Typical storage |
|---|---|---|---|
| ReadWriteOnce | RWO | Read and write, by pods on a single node | Cloud block disks |
| ReadOnlyMany | ROX | Read only, by pods on many nodes | Shared reference data |
| ReadWriteMany | RWX | Read and write, by pods on many nodes | Network file shares |
| ReadWriteOncePod | RWOP | Read and write, by one single pod only | Drivers that support it |
ReadWriteOnce means one node, not one pod. Several pods on the same node may all use it. Many beginners think it means one pod and are surprised. If you truly need one pod only, use ReadWriteOncePod.
RWO is a meeting room that only one department may book for the day, but anyone from that department may walk in. RWX is a shared office open to everyone. ROX is a library reading room where people may read but not scribble in the books. RWOP is a private phone booth for a single person.
Volume modes: files or raw blocks?
Most volumes use filesystem mode. Kubernetes formats the disk with a filesystem and mounts a folder. The application sees files and directories. Some specialized programs, such as certain databases, prefer to manage the raw disk on their own. For them Kubernetes offers block mode, which hands over the raw device with no filesystem on it. Beginners should stay with filesystem mode.
10The Container Storage Interface
The Container Storage Interface, or CSI, is the plug that lets any storage system work with Kubernetes.
Early versions of Kubernetes had storage code for every supported system built directly into the core. Every new storage vendor had to change Kubernetes itself, and every bug fix had to wait for a new Kubernetes release. This did not scale.
The answer was a standard called the Container Storage Interface. It defines a common set of requests, such as “create a volume”, “attach it to a node”, and “mount it here”. Any storage vendor can write a CSI driver that understands these requests. Kubernetes talks to the driver in the standard language, and the driver translates to its own system. The older built-in storage plugins have largely been moved over to CSI drivers.
CSI is like a universal power socket standard. Once every device maker builds a plug that fits the socket, the building no longer needs a different wall outlet for each brand of appliance. Storage vendors bring the plug. Kubernetes provides the socket.
The two halves of a driver
Controller plugin
Handles cluster-wide jobs: creating and deleting volumes, attaching disks to nodes, resizing, and taking snapshots.
Node plugin
Handles jobs that must happen on the machine itself: preparing the attached disk, formatting it, and mounting it into place for pods.
Helper programs called sidecars
Kubernetes ships a small set of helper programs that sit beside the driver and translate Kubernetes events into CSI requests. Each has one clear job.
- The provisioner watches for new claims and asks the driver to create disks.
- The attacher asks the driver to connect disks to nodes.
- The resizer grows volumes when a claim asks for more space.
- The snapshotter takes point-in-time copies.
- The node registrar tells the kubelet on each node that the driver is present.
When storage misbehaves, look at the driver’s pods first. A stopped provisioner means claims stay pending forever. A stopped node plugin means pods cannot mount their volumes.
11How a Volume Reaches Your Container
Between “the pod is scheduled” and “the app can write a file”, a careful sequence of steps takes place.
A pod cannot start its containers until its volumes are ready. The kubelet on the chosen node waits for each volume to be prepared, and only then lets the containers begin. Here is the journey for a persistent network disk, told in order.
The pod is placed on a node
The scheduler picks a node. If the disk already exists, the scheduler makes sure the node is reachable by that disk, for example in the same zone.
The disk is attached to the node
The storage system connects the disk to the machine, much like plugging in an external drive. To the operating system, a new device appears.
The node plugin prepares the device
If the disk is brand new and empty, the node plugin puts a filesystem on it. If it already holds a filesystem, it leaves the contents alone. The device is then mounted at a staging place on the node, shared by anything on this node that uses the disk.
The volume is published for the pod
The staged folder is linked into a private folder that belongs to this pod alone. The technique is called a bind mount. It makes the same folder appear in a second place without copying anything.
Ownership and permissions are adjusted
If the pod asks for a particular group to own the files, the kubelet makes that change so the application can read and write without special powers.
The container runtime maps it into the container
When the container starts, its runtime places the pod’s folder at the path the container asked for. The application sees an ordinary directory.
The application reads and writes
Every file written goes through the mounted folder into the filesystem on the disk, and from there to the real storage.
It is like setting up a visiting lecturer. First the room is booked, which is scheduling. Then the projector is wheeled in and connected to the room’s power, which is attaching. The technician tests it and loads the right software, which is preparing and mounting. Finally the lecturer’s own laptop is plugged in and the lecture starts, which is the container running. The lecturer never sees the wires, only a screen that works.
Cleaning up in reverse
When the pod ends, the steps happen in reverse. The container stops, the pod’s private folder is unmounted, the staging mount is removed if no other pod on the node needs it, and the disk is detached from the node. Only then can another node attach the same disk. If the node dies unexpectedly, this reverse process cannot happen cleanly, and the disk may remain attached to a dead machine for a while. This is a classic source of stuck pods, covered in the troubleshooting chapter.
A single-node disk cannot be attached to two machines at once. When a pod moves to a new node, the system must first detach from the old one. Until that finishes, the new pod waits, and users may notice a pause.
12The Life of a Volume and a Claim
Volumes and claims move through named states, and knowing them makes error messages readable.
stateDiagram-v2
[*] --> Available
Available --> Bound: Claim matches
Bound --> Released: Claim deleted
Released --> Available: Admin clears it for reuse
Released --> Deleted: Reclaim policy Delete
Released --> Failed: Cleanup problem
Deleted --> [*]
| Object | State | What it means |
|---|---|---|
| PersistentVolume | Available | Free and waiting for a claim |
| PersistentVolume | Bound | Currently belongs to a claim |
| PersistentVolume | Released | Its claim is gone, but the volume has not been cleaned or reused yet |
| PersistentVolume | Failed | Automatic cleanup did not work |
| Claim | Pending | Waiting for a matching volume to appear or be created |
| Claim | Bound | Successfully matched to a volume |
| Claim | Lost | Its volume has disappeared, so the data may be unreachable |
What happens when you delete a claim?
This is the most important safety question in Kubernetes storage, and the answer is decided by the reclaim policy.
Retain
- The volume and its data are kept.
- The volume moves to Released and waits for a human.
- Safest for valuable data.
- Requires manual cleanup.
Delete
- The volume and the real disk are removed.
- Data is gone for good, unless you have backups.
- Tidy and cheap for temporary data.
- The usual default for dynamically created volumes.
With the Delete policy, removing a claim deletes the disk. Many teams have lost databases by tidying a namespace. For anything you cannot afford to lose, choose Retain and keep snapshots.
Protection against accidental deletion
Kubernetes adds a safety net called storage object in use protection. If you delete a claim that a running pod is still using, the deletion is postponed until the pod stops. The same guard protects volumes that are still bound. This prevents the ugly case of pulling a disk out from under a running application.
13StatefulSets: One Disk for Each Replica
When you run several copies of a stateful application, each copy needs its own private, stable storage.
A normal Deployment gives every pod identical everything, and pods are interchangeable. That is perfect for web servers. But consider a database cluster with three members. Each member holds its own data and must keep its identity across restarts. Member number two must come back as member number two, with member number two’s data.
The StatefulSet was designed for this. It gives each pod a stable name, such as db-0, db-1, and db-2, and a stable network identity. It also lets you define a volume claim template: a recipe for a claim. Kubernetes uses the recipe to make one separate claim per pod. Pod db-0 always reattaches to db-0’s claim, no matter which node it lands on.
A Deployment is like a pool of taxis where any driver can take any car. A StatefulSet is like a set of assigned lockers at a gym, each with a member’s name on it. When member two returns after a week, she opens her own locker and finds her own things.
What happens when you scale down or delete
By default, Kubernetes does not delete the claims when a StatefulSet is scaled down or removed. This is deliberate: your data is precious, and a cautious default protects you. The claims stay behind until you delete them yourself. Newer Kubernetes versions add a retention policy setting, so you can choose to have claims cleaned up automatically when you are sure that is what you want.
Leftover claims from an old StatefulSet keep costing money. Review them after scaling down or deleting, but only delete them after confirming the data is not needed.
14Growing, Snapshotting, and Cloning Volumes
Data grows and mistakes happen. Kubernetes has tools for both.
Expanding a volume
If a disk fills up, you do not need to create a bigger one and copy everything. When the storage class allows expansion, you simply edit the claim and request a larger size. The driver grows the disk, and the filesystem is enlarged to match. Many drivers can do this while the pod keeps running. There is one firm rule: volumes can grow but they cannot shrink.
Snapshots
A snapshot is a frozen picture of a volume at one moment. It works like a photograph of a document: later changes to the document do not alter the photo. Kubernetes models snapshots with three objects. A snapshot class describes how to take them. A snapshot request asks for one. A snapshot content object records the real snapshot in the storage system. The storage driver must support snapshots for this to work.
Snapshots are quick and usually space-efficient because they record only changes. They are excellent for protecting against mistakes, such as a bad software update that corrupts data. They are not a full backup on their own, because many snapshots live inside the same storage system as the original disk. If that system is lost, both are lost.
Cloning
A clone makes a new volume that starts with a copy of an existing one. You create a new claim and point it at the source. Clones are handy for testing an upgrade on a copy of production data, or for spinning up a developer environment that starts with realistic contents.
| Feature | What you get | Best used for | Not a replacement for |
|---|---|---|---|
| Expansion | A larger disk in place | Growing databases | Cleaning up unneeded data |
| Snapshot | A restorable picture in time | Quick recovery from mistakes | Off-site backups |
| Clone | A new volume with copied data | Testing and development | Ongoing replication |
15Performance and Scalability
Storage speed is measured in three ways, and choosing the wrong one to worry about is a common error.
A database doing many tiny lookups cares mostly about IOPS and latency. A program copying huge video files cares mostly about throughput. A disk that is excellent at one may be mediocre at another, so first understand what your application really does.
Local versus network storage
Network disks, such as those offered by cloud providers, are convenient and can move between machines, but every read and write crosses a network. That adds delay. Local disks attached directly to the machine are much faster, but they tie the pod to the machine. Many production databases accept the network delay in return for easier recovery, while others use local disks and rely on replication between members for safety.
Limits to watch
Disks per node
A machine can only have so many disks attached at once, and the number depends on the machine type. Packing many stateful pods onto one node can hit this ceiling.
Speed tied to size
On some cloud disk types, speed grows with size. A tiny disk may be slow even if you only store a little data.
Shared file storage delay
Network file shares handle many writers well, but each operation carries extra overhead. Tiny file operations can feel slow.
Noisy neighbors
Pods sharing a node or a storage system can compete for speed. One busy pod may slow another.
Attach and mount time
Starting a pod with a large disk on a new node takes longer than starting a pod with no disk.
Inodes
A filesystem can run out of file slots before it runs out of space. A volume with millions of tiny files can be “full” while showing free space.
Test with a workload that resembles your real one before choosing a storage class. Speed claims on a price list rarely match what your application experiences.
16High Availability, Backup, and Disaster Recovery
A volume that cannot be reached, or that has been lost, is worse than no volume at all.
Zones and the trapped disk
Most cloud block disks live in a single zone. If that zone has an outage, the disk is unreachable, and any pod that needs it cannot start elsewhere. This surprises many teams who thought “Kubernetes will move my pod to another zone.” It will try, but the disk cannot follow.
There are three common ways to deal with this. You can replicate data at the application level, so that each database member in a different zone holds its own full copy. You can use storage that spans zones, such as certain regional disks or managed file services. Or you can accept a period of downtime and restore from a backup into a healthy zone.
Application-level replication
The database itself copies data between members in different zones. Storage can stay simple. Recovery is fast because another member already holds current data.
Storage-level replication
The storage system keeps copies across zones. The app stays simple, but the storage can cost more and may add delay.
Backup and restore
Copies of data are stored elsewhere and restored after a disaster. Cheapest, but recovery takes time and some recent data may be lost.
Two numbers every team should know
The recovery point objective is how much recent data you can afford to lose, measured in time. If it is fifteen minutes, your backups or replicas must never be older than that. The recovery time objective is how long you can afford to be down. If it is one hour, your restore process must reliably finish within the hour. These two numbers, not technology preferences, should drive your storage design.
Think of an important document. Keeping one photocopy in the same drawer protects you against spilled coffee but not against a fire. Keeping another copy in a different building protects you against fire too. Snapshots are the copy in the drawer. Off-site backups are the copy in the other building.
Backups that actually work
Tools built for Kubernetes can back up both the cluster’s descriptions and the contents of volumes, and store them in a separate place, such as object storage in another region. Whatever tool you use, remember the golden rule: a backup you have never restored is only a hope. Schedule regular test restores into a separate environment and check that the application starts and the data looks right.
17Security Considerations
Volumes can hold your most sensitive data, and they can also be a doorway into the node itself.
Run as a normal user
Set the pod to run as a non-administrator user, and ask Kubernetes to give that user’s group ownership of the volume. The app then works without extra powers.
Read-only where possible
Mount volumes as read-only for any container that only needs to read. This limits the damage of a bug or a break-in.
Restrict hostPath
Allow hostPath only for trusted system components. Use cluster policies to block ordinary applications from mounting node folders.
Encrypt at rest
Choose storage classes that encrypt disks. Cloud providers usually offer this with a simple setting, often using keys you control.
Protect secret records
Secrets are stored in the cluster’s database. Turn on encryption for that database and limit who can read secrets.
Control who can create claims
Use role-based access rules and quotas so that no team can create unlimited storage or read another team’s claims.
A pod that can mount an arbitrary hostPath can often read the credentials of other pods on the same node, or even take over the machine. Treat hostPath permission like a master key.
Secrets in volumes
Secret volumes are held in memory on the node, so they never touch the disk, which reduces the chance of leaks. Still, any container that mounts a secret can read it. Mount secrets only into containers that need them, and prefer short-lived credentials that rotate. For service identity, Kubernetes delivers time-limited tokens through projected volumes, which are far safer than long-lived passwords sitting in files.
Data lifecycle and privacy
When a disk is deleted or reused, the storage system should ensure old data cannot be read by the next user. Reputable cloud disks do this for you. For local disks and retained volumes that an administrator reuses, cleaning the disk is a step you must not skip, especially when the data was personal or regulated.
18Monitoring, Logging, and Metrics
Full disks and stuck mounts are among the most common causes of night-time alerts. Watch for them early.
Space used and free
The kubelet reports how much space each claim uses, how much is free, and the total size. Alert when a volume passes about eighty percent full, and again at ninety.
Inode usage
The same reports include file-slot usage. Alert on this too if your workload creates huge numbers of small files.
Storage operation timing
Kubernetes measures how long attach, mount, and provisioning steps take. Rising times point to a struggling storage system.
Mount and attach failures
Cluster events with names like failed mount or failed attach are usually the first clue when a pod is stuck starting.
Pending claims
A claim that stays pending for more than a few minutes means nothing can satisfy it. Alert on this.
Provider disk metrics
The storage system reports its own speed, queue length, and throttling. These reveal whether the disk itself is the bottleneck.
Alerts worth setting up
- A claim more than eighty percent full, with a stronger alert above ninety percent.
- A claim pending longer than a few minutes.
- Repeated mount or attach failures for the same pod.
- Volumes in a Released or Failed state that nobody has handled.
- Sudden growth in disk usage, which often signals a runaway log or a bug.
- Backup jobs that have not succeeded within their expected window.
19Advantages, Disadvantages, and Trade-offs
Volumes give you power over your data. That power comes with responsibilities.
Advantages
- Data outlives containers. Restarts and updates no longer erase state.
- Sharing is easy. Containers in a pod share folders with no extra network code.
- Portability. Claims let the same app description run on very different clusters.
- Automation. Dynamic provisioning creates disks on demand.
- Rich features. Expansion, snapshots, and clones come from a common interface.
- Clean separation of roles. Providers manage storage, developers only ask for it.
Disadvantages
- State makes everything harder. Stateful pods cannot simply be replaced at will.
- Zone limits. Many disks are stuck in one zone.
- Single-node access. The most common disk type cannot be shared across nodes.
- Hidden costs. Forgotten claims and snapshots keep billing.
- Vocabulary overload. Volumes, claims, classes, drivers, and modes confuse newcomers.
- Recovery is your job. Kubernetes does not back up your data by default.
Block, file, and object storage compared
| Kind | How it feels | Sharing | Good for | Watch out for |
|---|---|---|---|---|
| Block storage | A private hard drive | Usually one node at a time | Databases, queues | Zone limits, attach delay |
| File storage | A shared network folder | Many nodes at once | Shared content, home folders | Higher delay, small-file overhead |
| Object storage | A giant bucket reached by web calls | Unlimited readers | Backups, media, data lakes | Not a mounted folder for ordinary programs |
20Choosing the Right Kind of Volume
A short set of questions leads you to the right choice in nearly every case.
flowchart TD
Start["Need storage for a pod"] --> Q1{"Must data survive pod deletion?"}
Q1 -->|No| Q2{"Scratch space or configuration?"}
Q2 -->|Scratch| ED["Use emptyDir"]
Q2 -->|Config or secret| CFG["Use configMap or secret volume"]
Q1 -->|Yes| Q3{"Many pods write at once?"}
Q3 -->|Yes| RWX["Use shared file storage with ReadWriteMany"]
Q3 -->|No| Q4{"Speed on one node matters most?"}
Q4 -->|Yes| LOC["Consider a local volume with care"]
Q4 -->|No| BLK["Use a network block volume with ReadWriteOnce"]
Notice that most durable, single-writer cases end at a network block volume. That is why it is the everyday choice for databases in Kubernetes. Shared file storage is the answer when several pods on different nodes must write to the same place, such as an upload folder for a website. Scratch space and configuration have their own simple types, which you should always use in preference to durable disks for temporary needs.
21Design Patterns and Anti-patterns
Some volume habits age well. Others cause data loss.
Patterns that work
Sidecar sharing
An application writes logs to an emptyDir, and a second container in the same pod reads them and ships them elsewhere. No network hop is needed between the two.
Init container preparation
A short-lived container downloads or prepares data into a shared volume before the main container starts, so the main program finds everything ready.
Config as files
Settings are delivered by configMap volumes, so changing configuration does not require rebuilding the image.
Claim per replica
A StatefulSet with a claim template gives each member its own disk, which suits databases and queues.
Snapshot before change
Take a snapshot before risky upgrades, so a bad change can be undone in minutes.
Storage class tiers
Offer classes named for purpose, such as fast, standard, and archive, so teams pick by need rather than by vendor jargon.
Anti-patterns to avoid
What people do
They run a database and store its files in an emptyDir, because it works instantly and needs no extra setup.
Why it hurts
The data survives container crashes but disappears the moment the pod is rescheduled, evicted, or updated. It looks fine for weeks, then vanishes on a routine node upgrade.
What to do instead
Use a persistent volume claim, ideally through a StatefulSet, and test that data survives deleting the pod.
What people do
They mount a folder from the node and treat it as permanent storage for a real application.
Why it hurts
When the pod lands on another node it finds an empty folder. Worse, the pod may be able to touch sensitive parts of the node.
What to do instead
Use a proper persistent volume, or a local volume with a clear rule about which node holds the data.
What people do
They try to let many replicas on different nodes write to a single single-node block disk.
Why it hurts
Only one node can attach the disk, so the other pods wait forever, or, if forced, corrupt the data because ordinary filesystems are not built for simultaneous writers on separate machines.
What to do instead
Use shared file storage, or give each replica its own disk, or move shared state into a database or object store.
22Best Practices and Common Mistakes
A handful of habits prevents most storage disasters.
Best practices
Choose the reclaim policy on purpose
Use Retain for valuable data and Delete only for data you can recreate.
Use wait-for-first-consumer
For zone-bound disks, let the pod’s location decide where the disk is made.
Allow expansion
Enable growth on your storage classes so you can respond to full disks without downtime.
Test restores
Restore backups regularly into a scratch environment and confirm the data is usable.
Set sizes and limits
Give scratch volumes size limits and set quotas per team for claims.
Name things clearly
Use meaningful claim and class names so people know what each one holds.
Common mistakes
Assuming a restart keeps container files
Writing important files to the container’s own folders. They vanish on restart. Always write to a mounted volume.
Confusing one node with one pod
Expecting ReadWriteOnce to allow only one pod. It allows one node, with any number of pods on it.
Deleting a claim without checking the reclaim policy
Removing a claim under the Delete policy erases the disk. Always check before cleaning up.
Ignoring the zone
Creating a disk in one zone and scheduling the pod in another, leaving the pod pending forever.
Trusting snapshots as the only backup
Keeping all snapshots in the same storage system as the original data. A system-wide failure takes both.
Forgetting permissions
The volume mounts fine, but the application cannot write because the folder is owned by another user. Set the right group ownership for the pod.
23Real-World and Industry Examples
The same ideas appear on every major platform, under different product names.
Amazon Web Services: block and file storage
On Amazon’s managed Kubernetes service, the EBS CSI driver creates block disks that behave as single-node volumes bound to one zone, which is why the wait-for-first-consumer mode is so common there. The EFS CSI driver connects pods to a shared, regional file system that supports many nodes writing at once. Teams often use block disks for databases and the file system for shared content.
Google Cloud and Microsoft Azure
Google’s Kubernetes service offers persistent disks and shared file options through its own CSI drivers, and Azure provides disk and file drivers in the same way. The names change, but the concepts of claim, class, access mode, and zone-bound disk stay the same. Learning the model once carries you across all three clouds.
Local test clusters
Popular tools for running Kubernetes on a laptop, such as minikube, kind, and k3s, include a simple built-in provisioner that creates volumes from folders on the machine. It lets developers practice with claims and classes without any cloud account. It is meant for learning, not for protecting valuable data.
Databases and queues
Many teams run databases and message queues on Kubernetes using StatefulSets and operators. An operator is a helper program that knows how to run a specific database, including creating claims, taking backups, and replacing failed members. The volume design underneath, one disk per member spread across zones, follows the patterns in this guide.
Logging and monitoring agents
Node-level agents that collect logs commonly mount folders from the node so they can read what all the pods write. This is one of the few good uses of hostPath, and it is why such agents are tightly controlled.
Machine learning and data processing
Training jobs often mount a shared file volume holding large datasets, so that many worker pods on different nodes can read the same files. Fast local scratch volumes hold temporary results during the run.
In every setting, the same three questions decide the design: how long must the data live, who needs to touch it at the same time, and what happens if the zone or node disappears?
24When It Does Not Work: A Troubleshooting Path
Most storage problems fall into a few well-known shapes. Work from the claim outward.
Is the claim bound?
A pending claim means no volume matches or none can be created. Read the claim’s events. Common causes are a missing storage class, no default class, or a driver that is not running.
Is the storage class correct?
A typo in the class name leaves the claim waiting forever. Also check whether the class supports the access mode and size you asked for.
Is the pod stuck in container creating?
This often means the volume cannot be attached or mounted. Look at the pod’s events for failed attach or failed mount messages.
Is the disk in the wrong zone?
A pod scheduled in a different zone from its disk will wait. The events often mention a node affinity conflict.
Is the disk still attached elsewhere?
A message about a multi-attach error means a single-node disk is still connected to another machine, often one that crashed. Wait for the detach to finish, or resolve the problem on the old node.
Does the app get permission denied?
The volume is mounted but owned by a different user or group. Adjust the pod’s user and group settings so the app can write.
Is the volume actually full?
Check both space and file slots. A full volume makes applications fail in odd ways, such as a database refusing writes.
Is a claim stuck terminating?
The in-use protection keeps it until every pod using it is gone. Find and stop the remaining pod, and the deletion completes on its own.
25Frequently Asked Questions
Quick answers to the questions beginners ask most often.
26Summary and Key Takeaways
What to remember about Kubernetes volumes
- Containers forget. Anything written to a container’s own filesystem is lost on restart, so important data belongs in a volume.
- Three lifetimes exist: the container, the pod, and beyond the pod. Choose the volume type that matches how long the data must live.
- Claims separate users from providers. Pods ask for a claim, the claim binds to a volume, and a storage class can create that volume on demand.
- Access modes matter. ReadWriteOnce means one node, not one pod. Use shared file storage or one disk per replica when several writers exist.
- Zones and reclaim policies are the classic traps. Use wait-for-first-consumer for zone-bound disks and Retain for data you cannot recreate.
- CSI drivers do the real work. Kubernetes coordinates, and the driver talks to the storage system to create, attach, mount, resize, and snapshot.
- Protect your data yourself. Monitor usage, encrypt disks, limit hostPath, and test restores. Kubernetes will not back up your data for you.