Kubernetes Persistent Volumes
How applications that live and die in seconds can still keep their data safe for years, explained step by step from zero.
Imagine you write a long, important letter on a whiteboard. The whiteboard is wiped clean every night by the cleaners. No matter how careful you are, tomorrow morning your letter is gone. Now imagine you had a locked filing cabinet next to the whiteboard. You could write on the whiteboard all day, and whatever matters goes into the cabinet. The cleaners never touch the cabinet.
Containers in Kubernetes are like that whiteboard. They are quick to create, quick to destroy, and they forget everything when they go. Databases, uploaded photos, message queues and shopping-cart histories cannot afford to forget. Kubernetes solves this with a filing cabinet system called Persistent Volumes.
In this guide you will learn what a Persistent Volume is, why it exists, how it connects to your application, how it is created and cleaned up, how it behaves in the big clouds, and how professionals keep it fast, safe and affordable. Every new word will be explained the first time it appears.
1The Problem: Containers Forget Everything
Before we meet the solution, let us feel the pain it removes. Storage only makes sense once you see what goes wrong without it.
A quick look at containers and Kubernetes
A container is a small, sealed box holding a program and everything it needs to run. Kubernetes is the free, open-source system that starts, stops, moves and repairs thousands of these boxes across many computers. A group of computers managed together is a cluster, and each computer in it is a node. Containers run inside small wrappers called Pods, the smallest thing Kubernetes manages.
Why data disappears
Every container gets a private, temporary writing area when it starts. It lives and dies with the container. Kubernetes is designed to replace containers freely. A Pod may be restarted after a crash, moved to a healthier node, or rebuilt during an update. Each time, the fresh container starts with a clean, empty area, exactly like the whiteboard after cleaning night.
- A container crashes: its writing area is wiped when it restarts.
- A Pod is deleted or updated: the new Pod knows nothing about the old one.
- A node fails: everything stored on that node’s temporary space may be lost.
For a static website this is fine. For a database, it would be a disaster.
Think of a hotel room. Guests come and go, and housekeeping resets the room after every stay. Anything a guest leaves on the desk is thrown away. If a guest wants to keep something safe for their next visit, they use the hotel’s storage locker in the basement. The locker belongs to the guest, not to the room. A Persistent Volume is that locker, and the Pod is the hotel room.
Pods are short-lived. Data is long-lived. A Persistent Volume separates the two so that the data can outlive any Pod that uses it.
2Building Blocks You Need First
Eight small ideas carry this whole topic. Learn them once and the rest will feel natural.
Volume
A folder that is attached to a Pod. Containers in the Pod can read and write it. Some volumes vanish with the Pod, and some survive.
Mount
The act of making a volume appear as a folder inside a container, at a path you choose. Like plugging a USB stick into a computer.
Storage backend
The real place where bytes live: a cloud disk, a network file server, or a disk inside your own data center.
Namespace
A named room inside a cluster that keeps one team’s things apart from another’s. Some Kubernetes objects live in a namespace and some are shared by the whole cluster.
Control plane
The brain of the cluster. It stores your requests, watches what exists, and keeps working until reality matches what you asked for.
Kubelet
A helper program running on every node. It starts the Pods assigned to its node and mounts their volumes.
CSI driver
A plug-in that teaches Kubernetes how to talk to one kind of storage. CSI stands for Container Storage Interface, a common plug shape so any storage maker can connect.
Controller
A caretaker program that keeps comparing what was asked with what exists and fixes any gap, again and again.
A CSI driver is like the travel adapter you carry abroad. Wall sockets differ from country to country, but one adapter design lets your phone charger work anywhere. Storage makers differ too, and CSI is the adapter that lets Kubernetes plug into any of them.
3The Storage Trio: PV, PVC and StorageClass
Kubernetes storage uses three objects that work together. Each has one clear job, like the roles in a restaurant.
PersistentVolume (PV)
A piece of real storage that has been made available to the cluster. It records how big it is, where it lives and how it can be used. A PV belongs to the whole cluster, not to one namespace.
PersistentVolumeClaim (PVC)
An application’s request for storage: “I need 20 gigabytes that one node can write to.” It lives in a namespace, next to the Pod that uses it.
StorageClass
A named menu item describing a kind of storage, such as “fast SSD” or “cheap and slow”. It tells Kubernetes how to create a PV automatically when someone asks for it.
Pod
The application that needs the storage. It never talks to the real disk directly. It only mentions its claim by name.
Think of a car-rental company. The parked cars are the PVs. A customer filling in an order form (“one small car for a week”) is the PVC. The price list with categories such as economy, luxury and van is the StorageClass. The driver who finally uses the car is the Pod. The customer never picks a specific car by license plate; the company matches the order to a suitable car.
Why split it into supply and request?
The split keeps two groups of people from stepping on each other. The platform team knows about disks, speeds and prices, so they define the supply and the menu. The application developers only know how much space they need and how it should behave. Developers ask, the platform delivers, and neither needs to learn the other’s whole job.
A PV is cluster-wide, but a PVC is namespaced. A Pod can only use claims from its own namespace. This is a helpful safety wall between teams.
4What a Persistent Volume Really Is
Let us define it in plain words, and then compare it with the other places a Pod could keep data.
A Persistent Volume is a Kubernetes object that represents a chunk of storage with its own life, separate from any Pod. It has a size, a set of allowed ways to use it, a note about what happens when it is no longer needed, and a pointer to the real storage behind it. Even if every Pod using it vanishes, the PV and the bytes inside continue to exist.
The word “persistent” simply means “keeps existing”. A regular volume is tied to a Pod’s life. A persistent one is tied to its own life, managed separately.
Comparing the ways to store data
| Option | Where data lives | Survives Pod restart? | Survives node loss? | Good for |
|---|---|---|---|---|
| Container writing area | Inside the container | No | No | Nothing important |
| emptyDir volume | Temporary folder on the node | Survives container restarts, lost when the Pod is removed | No | Scratch space, caches |
| hostPath volume | A folder on one specific node | Yes, if the Pod returns to that node | No | Single-node tests only |
| Persistent Volume | Real external or dedicated storage | Yes | Yes, when the backend is outside the node | Databases, uploads, queues |
The container writing area is a sticky note that falls off the fridge. The emptyDir is a notepad on the kitchen table that stays until the meal is over. The hostPath is a drawer in one particular house, useless if you move. A Persistent Volume is a bank safe-deposit box: it is in its own secure building, and you can visit it from wherever you live.
5Architecture and Components
Here is the whole picture in one drawing. Read it from the Pod on the left to the real storage on the right.
flowchart LR
subgraph NS["Namespace: shop"]
POD["Pod: Database"] --> PVC["PersistentVolumeClaim"]
end
PVC -->|bound to| PV["PersistentVolume"]
PV --> CSI["CSI Driver"]
CSI --> BACK["Storage Backend: Cloud Disk or File Server"]
SC["StorageClass"] -. defines how to create .-> PV
CTRL["PV Controller"] -. matches claims and volumes .-> PVC
KUB["Kubelet on the Node"] -. mounts the volume into .-> POD
Reading the diagram
The solid arrows show the path that data takes: the Pod writes to a folder, the folder belongs to a claim, the claim is bound to a volume, the volume is served by a driver, and the driver reaches the real storage. The dotted arrows show the helpers that make this possible behind the scenes.
Meet each component
Pod and PVC
The Pod names a claim. The claim describes size, access style and menu choice. Nothing here mentions a specific disk.
PersistentVolume
The cluster-wide record of one piece of storage: capacity, access rules, cleanup rule and how to reach the real disk.
StorageClass
The menu entry that names the storage maker’s driver and its options, such as disk speed or encryption.
PV Controller
The matchmaker. It looks at every waiting claim and every available volume, and pairs them up when they fit.
CSI Driver
Two parts: a controller part that creates, deletes, attaches and resizes storage, and a node part that mounts it on each machine. Helper programs called sidecars connect the driver to Kubernetes.
Kubelet
The node helper that makes the storage appear inside the container’s folder just before the container starts.
6How a Volume Comes to Life: Static and Dynamic Provisioning
There are two ways a PV can come into being. One is like buying furniture in advance. The other is like ordering it made to fit.
Static provisioning: prepared in advance
An administrator creates the real disk by hand, then writes a PV object describing it. The PV sits in the cluster with the state “Available”, waiting. When a matching claim arrives, the two are paired. This gives tight control but takes manual effort for every disk.
Dynamic provisioning: made when asked
Here nobody prepares disks in advance. A developer writes a claim that names a StorageClass. The CSI driver automatically creates a new disk in the storage system, then creates a PV to represent it, and Kubernetes binds the two. This is how almost all modern clusters work, because it is fast, repeatable and hands-off.
sequenceDiagram
participant Dev as Developer
participant API as API Server
participant CSI as CSI Provisioner
participant Store as Storage Backend
participant Kub as Kubelet
Dev->>API: Create a claim that names a StorageClass
API-->>CSI: New claim is waiting
CSI->>Store: Please create a disk of this size
Store-->>CSI: Disk created
CSI->>API: Create a PersistentVolume for that disk
API-->>API: Bind the claim and the volume together
Dev->>API: Create a Pod that uses the claim
API-->>Kub: Start the Pod on a node
Kub->>Store: Attach and mount the disk
Kub-->>Dev: Pod is running with its data
You write a claim
You state the size, the access style and the StorageClass you want. The claim is saved and sits in a state called Pending.
The driver notices
A helper program of the CSI driver, called the external provisioner, sees the waiting claim and reads the matching StorageClass to learn what to build.
Real storage is created
The driver calls the storage system’s own ordering interface and creates the disk. This may take a few seconds or a minute.
A PV record appears
The driver writes a PersistentVolume object that points to the new disk. Its size and rules match the claim.
The claim and volume are bound
The PV controller pairs them. The claim’s state changes from Pending to Bound. From now on this claim and this volume belong only to each other.
A Pod arrives and uses it
When a Pod that mentions the claim is scheduled to a node, the disk is attached to that node and mounted for the container. Your app sees an ordinary folder.
Static provisioning is like a shop that stocks fixed-size lockers and hands out whichever one fits. Dynamic provisioning is like a workshop that builds a custom locker the moment you place an order. The second is more flexible, and it removes the need to guess how many lockers of each size to prepare in advance.
Most clusters have a default StorageClass. If your claim does not name one, it quietly gets the default. This is handy but can surprise you, so know which one your cluster picks.
7The Life Story of a PV: Phases
Every PV moves through a small number of states. Reading them is the fastest way to understand what is going on.
stateDiagram-v2
[*] --> Available
Available --> Bound : a matching claim arrives
Bound --> Released : the claim is deleted
Released --> Available : admin cleans and reuses it
Released --> Failed : automatic cleanup did not work
Released --> [*] : deleted under the Delete rule
Available
The volume is free and not yet paired with any claim. It is waiting for someone to ask for storage that fits it.
Bound
The volume is paired with exactly one claim. Nobody else can use it now, even if it has spare room.
Released
The claim was deleted, but the volume still holds the old data and is not yet ready for a new owner. Kubernetes keeps it here until the reclaim rule is carried out.
Failed
Automatic cleanup or reclaim did not work. A human needs to look at it.
How a claim finds its volume
When a claim looks for a volume, the matchmaker checks a few things. The volume must be big enough, and it must offer the access style the claim asked for. If the claim names a StorageClass, the volume must belong to the same one. Labels can narrow the choice further. Among matches, the smallest one that fits is usually chosen so bigger volumes are not wasted. A claim can also name a specific volume directly.
A claim that stays Pending forever means nothing matched. Common causes are a StorageClass name typo, no default class, a missing driver, or a request for an access style that the storage does not support.
Protection from accidents
Kubernetes has a safety net called storage object in-use protection. If a Pod is still using a claim, and someone deletes the claim, Kubernetes holds off on the removal until the Pod is gone. A volume that is still bound to a claim is also protected. This prevents the nightmare of pulling a disk out from under a running database.
8Access Modes and Volume Modes
Two settings decide who may use the storage at the same time and in what form.
Access modes: who may share it
| Mode | Short name | Meaning | Typical storage |
|---|---|---|---|
| ReadWriteOnce | RWO | Read and write, by Pods on one node at a time | Cloud block disks |
| ReadOnlyMany | ROX | Read only, by many nodes at once | Shared reference data |
| ReadWriteMany | RWX | Read and write, by many nodes at once | Network file systems |
| ReadWriteOncePod | RWOP | Read and write, by exactly one Pod in the whole cluster | Drivers that support it |
Notice that the word “once” in ReadWriteOnce refers to a node, not a Pod. Several Pods on the same node can share such a volume. If you need a strict guarantee of a single Pod, use the ReadWriteOncePod mode.
A block disk is like a private notebook: only one person at a time can write in it. A network file system is like a shared whiteboard in a meeting room: many people can write at once, as long as they do not scribble over each other. A read-only reference book can be read by everyone but edited by no one.
Volume modes: what shape it takes
In Filesystem mode, which is the default, the storage is formatted and shown to the container as a normal folder. In Block mode, the container receives the raw, unformatted disk. Some specialized databases prefer this because they manage the disk’s layout themselves. Most applications should use the ordinary Filesystem mode.
The access mode is a promise about what the volume can support. It is not a lock that Kubernetes enforces on the data itself. If two writers share a volume, your application must still avoid corrupting the data.
9Reclaim Policy: What Happens When You Are Done
When a claim is deleted, what should happen to the storage and the data inside? The reclaim policy answers that question.
Retain
- The PV and the real disk are kept after the claim is deleted.
- The PV moves to the Released state and is not given to anyone else automatically.
- An administrator decides whether to copy the data out, clean it, or reuse it.
- Safest choice for precious data, but needs manual tidying.
Delete
- The PV and the real disk are both removed when the claim goes away.
- No leftover cost and no forgotten disks.
- Data is gone for good unless a backup exists.
- The usual default for dynamically created volumes.
There was once a third option called Recycle, which wiped the data and made the volume available again. It is deprecated, and dynamic provisioning is recommended instead.
Renting a storage unit: with the Retain rule, when you cancel your rental, the company leaves your belongings inside and calls you before doing anything. With the Delete rule, the company empties the unit and throws everything away the moment you cancel. Both are reasonable, but you must know which one you signed up for.
A dynamically created volume usually inherits the reclaim policy from its StorageClass, and the default there is Delete. Teams have lost important test data by deleting a claim and discovering the disk had gone with it. For anything precious, choose Retain, or keep backups.
Timing matters too: binding mode
A StorageClass also has a binding mode. With Immediate, the disk is created the moment the claim is written. With WaitForFirstConsumer, Kubernetes waits until a Pod that uses the claim is placed on a node, and only then creates the disk in a location that node can reach. This second choice is very important on clouds where disks belong to a single zone, which the next chapter explains.
10Persistent Volumes on the Big Clouds
The objects look the same everywhere, but what sits behind them depends on where your cluster runs.
EBS and EFS
Amazon EBS gives fast block disks, normally used as ReadWriteOnce and tied to one availability zone. Amazon EFS offers a shared file system that many nodes can use at once, which suits ReadWriteMany. Each has its own CSI driver.
Persistent Disk and Filestore
Persistent Disk provides block storage, including a regional flavor that copies data across two zones. Filestore provides a shared network file system for many readers and writers.
Azure Disk and Azure Files
Azure Disk is block storage for one node at a time. Azure Files is a shared file service that can serve many nodes.
NFS, Ceph, local disks
In a data center you might use a network file server, a distributed system such as Ceph through the Rook project, or disks inside the nodes themselves as local volumes.
The zone trap
Many cloud disks live in one availability zone, which is a separate building within a cloud region. A disk in Zone A cannot be attached to a machine in Zone B. If a Pod using that disk gets rescheduled to a node in another zone, it will be stuck waiting, unable to reach its data.
flowchart LR
subgraph ZA["Zone A"]
DISK["Cloud Disk in Zone A"]
NA["Node in Zone A"]
end
subgraph ZB["Zone B"]
NB["Node in Zone B"]
end
DISK ==>|can attach| NA
DISK -. cannot attach .-> NB
Kubernetes handles this by writing a location rule, called node affinity, onto the PV. The scheduler reads it and only places the Pod on nodes that can reach the disk. Using the WaitForFirstConsumer binding mode makes the disk appear in the same zone as the chosen node from the start.
A zonal disk is like a suitcase left at a hotel in one city. You can only pick it up by going to that city. If your travel plans suddenly move you to another city, you are separated from your suitcase. Good planning keeps your travel and your suitcase in the same place.
If your application must survive the loss of an entire zone, do not rely on one zonal disk. Use a replicated database with copies in several zones, a regional disk type, or shared file storage that spans zones.
11Internal Working: From Claim to Folder
What actually happens on the machine when your Pod starts and needs its data? Let us follow one write, from the moment the Pod is scheduled to the moment bytes land on disk.
The scheduler picks a node
Kubernetes chooses a node for the Pod. It checks the location rules on the PV so that it never chooses a node that cannot reach the disk.
The disk is attached
For block storage, the controller part of the CSI driver asks the storage system to connect the disk to the chosen machine, much like plugging a hard drive into a computer. Kubernetes records this in an object so it always knows which disk is connected to which node.
The node prepares the disk
The node part of the CSI driver checks whether the disk already has a file system. A brand new disk is formatted once. An existing one is left alone, so old data is never wiped.
The disk is mounted
The disk is made visible in a special folder for that Pod on the node. Then the kubelet passes that folder into the container at the path you chose, such as the place where a database keeps its files.
The container starts
The application opens its files as usual. It has no idea that its folder is really a cloud disk far away. From its point of view, this is an ordinary directory.
The Pod ends, the data stays
When the Pod is removed, the folder is unmounted and the disk is detached from the node. The disk and its bytes remain safe in the storage system, ready for the next Pod that uses the same claim.
Think of a school locker. When the school day starts, the student gets the key and the locker door is opened in the hallway near their classroom. When the day ends, the student hands the key back and goes home. The books stay in the locker overnight. The next morning the student gets access again, maybe from a different hallway.
Why moving a Pod can take a while
Detaching a disk from an old node and attaching it to a new one takes time. The storage system must finish the detach before it allows the attach. If the old node has crashed, the system may wait to be sure that node is truly gone before letting anyone else use the disk. This safety wait protects your data from being written by two machines at once, which could corrupt it. So during node failures, a stateful Pod may take a minute or more to recover, and you may see a warning about the disk still being in use elsewhere.
A “multi-attach” or “volume already in use” warning does not mean something is broken. It often just means Kubernetes is waiting for the old node to let go. Only investigate if it lasts far longer than expected.
12StatefulSets: One Volume for Each Replica
What if you run three copies of a database and each needs its own private storage? Kubernetes has a tool made exactly for this.
A normal Deployment treats all its Pods as identical and interchangeable, like paper cups at a party. A StatefulSet treats each Pod as an individual with a name, a number and an identity, like named guests at a dinner table. Pod number 0 is always called by its own name, and it always gets its own storage back after a restart.
The StatefulSet contains a template for claims. When it creates Pod 0, Pod 1 and Pod 2, it also creates three separate claims, one for each. If Pod 1 is killed and replaced, the new Pod 1 reconnects to exactly the same volume as before, with all its data intact.
Predictable identity
Pods are numbered in order, so other systems can find “database-0” every time, even after it restarts.
A claim per replica
Each replica has its own volume. No two replicas write to the same files by accident.
Careful start and stop
Pods start one by one in order and stop in reverse order, which many databases need to form a healthy group.
Volumes outlive the set
By default, if you delete a StatefulSet or shrink it, its claims are kept, so you do not lose data by accident. Newer versions let you choose different behavior on purpose.
A Deployment is a taxi fleet: any driver can take any car and nobody minds. A StatefulSet is a family of people who each have their own bedroom. If one person goes out for the day, their bedroom is left exactly as it was, waiting for them to come back.
Storage does not replicate itself. If you run three database Pods with three volumes, it is the database software that must copy data between them. Persistent Volumes keep data alive; they do not make copies of it for you.
13Growing, Snapshots, Clones and Backups
Data changes and grows. These features help you resize and protect it without downtime nightmares.
Expanding a volume
If a StorageClass allows expansion, you can raise the size in your claim and the storage grows to match. Depending on the driver, the file system is stretched while the Pod keeps running, or after a restart. You can grow a volume but you cannot shrink it, so it is wise to start modestly and grow when needed rather than start huge.
Snapshots
A VolumeSnapshot is a frozen picture of a volume at one moment. It is like taking a photo of a whiteboard before you erase it. The storage system records the state efficiently, often without copying every byte at once. You can use a snapshot to restore data after a mistake, or to create a new volume that starts with the same contents. Snapshots need a CSI driver that supports them.
Cloning
A clone creates a new volume that begins as a copy of an existing claim. It is handy for testing new database versions on real-looking data without touching the original.
| Feature | What it does | Good for | Not a substitute for |
|---|---|---|---|
| Expansion | Makes a volume bigger | Growing databases | Shrinking or cleaning up |
| Snapshot | Freezes a point in time | Quick rollback | Backup in a separate place |
| Clone | Copies a claim into a new one | Testing and staging | Live replication |
| Backup | Copies data to a different, safe location | Disaster recovery | Instant recovery |
A snapshot usually lives beside the original disk in the same storage system. If the whole system or account is lost, both are lost together. Real protection needs a backup copy stored in a different place, and a recovery test that proves the copy really works.
14Advantages, Disadvantages and Trade-offs
Every design has strengths and costs. Knowing both helps you decide well.
Advantages
- Data survives Pod restarts, updates and node failures.
- Developers ask for storage without learning cloud details.
- The same claim works on many clouds and data centers.
- Dynamic provisioning removes manual disk work.
- Built-in features for growing, snapshots and cloning.
- Protection against deleting storage that is still in use.
Disadvantages
- Stateful workloads are harder to move and scale than stateless ones.
- Zonal disks can pin a Pod to one zone.
- Detach and attach steps slow down recovery.
- Cloud disks add cost even when they are nearly empty.
- Performance depends heavily on the storage type chosen.
- No automatic backup: you must design that yourself.
The trade-offs behind the choices
Speed versus sharing. Block disks are fast and simple but usually serve one node. Shared file systems serve many nodes but often have higher delay and cost more per gigabyte.
Safety versus tidiness. The Retain policy protects data but leaves orphaned disks to clean up. The Delete policy is tidy but unforgiving.
Own it versus rent it. Running a database yourself on Persistent Volumes gives control and portability. A managed database service removes chores such as backups and upgrades but ties you to a provider and often costs more.
Local speed versus resilience. Disks that sit inside the node are very fast, but they die with the node. Network disks are a little slower but survive machine failures.
15Security: Locking the Filing Cabinet
Stored data is often the most valuable thing you own. Guard it in layers.
Control who can ask
Use role-based permissions so only trusted people and pipelines can create, change or delete claims, volumes and StorageClasses. Deleting a claim can destroy data, so treat it like a powerful button.
Encrypt at rest
Most storage systems can encrypt disks with keys from a key management service. Enable it in the StorageClass so every new volume is encrypted automatically.
Encrypt in transit
Network storage sends data across the network. Use protocols and settings that encrypt that path, especially for shared file systems.
File permissions
Pods run as users, and files have owners. Setting the right group for a volume lets the app read and write without running as the all-powerful root user.
Avoid hostPath
A hostPath volume opens a door from the container into the node’s own file system. Attackers love that door. Security policies commonly forbid it, and you should too.
Protect backups and snapshots
A backup is a full copy of your secrets and customer data. Encrypt it, restrict who can read it, and keep it in a separate account or location.
Cleaning up after yourself
When a volume is retired, the old data must not leak to the next user. Dynamic deletion normally removes the disk entirely. With reused volumes, make sure old contents are wiped. Dropping in a new claim on a dirty volume is like handing over a hotel room with the previous guest’s belongings still in the wardrobe.
Because a PV is cluster-wide, an overly generous permission can let someone in one team bind to storage meant for another. Keep permission rules tight and review who can create volumes.
16Monitoring, Logging and Metrics
A full disk at three in the morning is a classic emergency. A few alarms make it a non-event.
Think of the fuel gauge in a car. You do not wait for the engine to stop before you look at it. Storage deserves the same care.
What to watch
Space and file counts
The kubelet reports how much of each volume is used, how much is free, and how many files are used out of the maximum. A disk can be “full” because it ran out of file slots even when bytes remain.
Speed
Cloud storage publishes numbers for reads and writes per second, data moved per second, and the delay of each operation. If your database feels slow, these show whether the disk is the bottleneck or has hit its speed limit.
Claim and volume health
Watch for claims stuck in Pending, volumes in Failed, and Pods that cannot start because a mount or attach step has failed. Kubernetes writes events explaining these failures.
Cost and leftovers
Look for disks that exist in the cloud but no longer belong to any claim. They quietly keep charging you.
Alarms worth setting
- A volume passing about 80 percent full, with a stronger alarm near 90 percent.
- A claim that stays Pending longer than a few minutes.
- A Pod stuck in container creation because of a volume problem.
- Disk delay climbing above what your application tolerates.
- Any snapshot or backup job that fails or misses its schedule.
Prometheus with Grafana is a common pair for cluster numbers, and cloud numbers can join the same dashboards. Central logging lets you see database messages and Kubernetes events together when you investigate an incident.
17Design Patterns and Anti-patterns
Patterns are solutions that many teams found reliable. Anti-patterns are traps many teams fell into.
Patterns that work
Pattern: Dynamic provisioning with clear classes
Offer a few well-named StorageClasses such as “fast”, “standard” and “shared”. Developers pick one by name and never touch raw disks.
Pattern: One volume per database replica
Use a StatefulSet so every replica has its own volume, and let the database software copy data between replicas.
Pattern: Snapshot before risky changes
Take a snapshot before an upgrade or a big data migration. If something goes wrong, you can go back in minutes.
Pattern: Shared storage for shared files
Use a ReadWriteMany file system for user uploads or media that several web Pods must both read and write.
Pattern: Object storage for big files
Store photos, videos and documents in an object storage service, and keep only small, fast, structured data on Persistent Volumes. This is cheaper and scales far better.
Pattern: Spread replicas across zones
Place database replicas, each with its own zonal disk, in different zones. Losing one zone then loses only one replica, not the whole database.
Traps to avoid
What it looks like
Using hostPath to keep a production database’s files on a node’s local folder.
Why it hurts
The data is tied to one machine. If the Pod moves or the node dies, the data is stranded or lost, and the folder opens a security hole.
Better approach
Use a claim backed by network storage, or a properly managed local volume with a replicated database.
What it looks like
Leaving the default Delete policy on volumes that hold customer data and having no backups.
Why it hurts
One wrong deletion of a claim, or a whole namespace, erases the disk and the data forever.
Better approach
Use Retain for precious data, protect deletion permissions, and keep off-site backups that are tested.
What it looks like
Making every application stateful, with a volume for each, even when a small config file or an external database would do.
Why it hurts
Stateful Pods are harder to move, update and scale. Every volume also adds cost and something else that can fail.
Better approach
Keep applications stateless where possible. Push state into a small number of well-managed places.
What it looks like
Believing snapshots are the same as backups.
Why it hurts
A snapshot in the same system disappears with it. Teams discover this only when disaster strikes.
Better approach
Copy backups to a separate location and practice restoring from them regularly.
18Best Practices and Common Mistakes
Small habits make a big difference when your data is on the line.
Habits that pay off
- Choose the right class for the job. Fast SSD for databases, cheaper storage for logs and archives.
- Turn on volume expansion. It lets you grow calmly instead of migrating in a panic.
- Prefer WaitForFirstConsumer on zonal clouds. The disk is then created near the node that actually needs it.
- Set the reclaim policy on purpose. Know whether deleting a claim deletes the data.
- Size with room to grow. Leave at least a fifth of the space free, and alarm before it runs out.
- Test your restores. A backup that has never been restored is only a hope.
- Use readiness checks and graceful shutdown. Give databases time to finish writing and close cleanly before a Pod is removed.
- Label everything. Add owner, team and purpose to claims so old volumes can be traced and cleaned up.
- Keep sensitive data encrypted. Use encrypted classes by default so nobody has to remember.
Mistakes beginners make
Claim stuck in Pending
Usually a mistyped class name, a missing driver or an unsupported access mode. Read the events on the claim; they name the cause.
Wrong access mode
Asking for ReadWriteMany from a block disk that supports only ReadWriteOnce. The request cannot be satisfied.
Permission denied errors
The volume is mounted, but its files belong to a different user than the app runs as. Fix the group settings rather than running everything as root.
Forgetting orphaned disks
After using Retain, or deleting things by hand, abandoned disks stay in the cloud and keep charging. Review and clean them regularly.
Two writers, one block disk
Forcing several nodes to write to a single-writer disk can corrupt the data. Respect the access mode.
Ignoring speed limits
Cloud disks have limits on operations per second and throughput that depend on type and size. A small disk may be slow even when it is nearly empty.
19Real-World and Industry Examples
Here is how well-known organizations and typical setups use Persistent Volumes in practice.
Databases at scale: Zalando
The European online fashion retailer Zalando open-sourced a Postgres Operator, a program that runs highly available PostgreSQL databases on Kubernetes. Each database instance gets its own persistent storage, and the operator handles failover, so a lost Pod can return to its data.
Search and logs: Elasticsearch on Kubernetes
Elastic, the company behind Elasticsearch, provides an operator called Elastic Cloud on Kubernetes. Search data nodes use persistent volumes so the indexes survive restarts and upgrades. This is a good example of a workload whose whole purpose is holding data.
Monitoring: Prometheus
Prometheus, the popular monitoring system, stores its time-series data on disk. Teams commonly give it a persistent volume so that weeks of metrics are not lost when the Pod restarts. Sizing that volume for your retention period is a classic capacity task.
Distributed databases: Cassandra and friends
Projects such as K8ssandra package the Cassandra database for Kubernetes. Each database node uses its own volume, and Cassandra itself copies data between nodes, showing the split between storage that keeps data and software that replicates it.
A typical online shop
Picture a store on a managed Kubernetes service. The product catalog database runs as a StatefulSet on fast encrypted block disks spread across zones, with nightly snapshots and off-site backups. Customer photos go to object storage. The web servers stay stateless and share nothing but a small shared file system for generated invoices. This mix keeps each kind of data on the storage best suited to it.
Machine learning training
A team trains models on large datasets. They mount a shared file system with the training data across many worker Pods for reading, and give each job a fast scratch disk. Finished models are copied to durable storage. Different volumes serve different purposes in one pipeline.
20Frequently Asked Questions
Quick answers to the questions beginners ask most often.
21Summary and Key Takeaways
You began with a whiteboard that gets wiped every night. Now you know how to build the filing cabinet next to it.
Key Takeaways
- The problem: Containers and Pods are temporary, so anything stored inside them disappears when they are replaced.
- The trio: A PersistentVolume is the storage, a PersistentVolumeClaim is the request, and a StorageClass is the menu that creates storage on demand.
- The lifecycle: A volume is Available, then Bound to one claim, then Released when the claim is deleted, and the reclaim policy (Retain or Delete) decides what happens next.
- Sharing rules: Access modes (RWO, ROX, RWX, RWOP) say who may use a volume at once, and block disks and shared file systems suit different needs.
- Watch the zones: Many cloud disks belong to one zone, so use WaitForFirstConsumer and spread replicas across zones.
- Stateful apps: StatefulSets give each replica its own claim and stable identity, but the database software must do the replication.
- Protect it: Encrypt volumes, restrict who can delete claims, avoid hostPath, monitor free space, and keep tested backups in a separate place.