Dynamic Provisioning in Kubernetes

Dynamic Provisioning in Kubernetes

How Kubernetes creates storage on demand the moment an application asks for it, what StorageClasses, claims and CSI drivers really do, and how to run this safely and cheaply in production, explained from zero.

Imagine you rent a small office in a big business center. In the old days, if you needed a new filing cabinet, you wrote to the office manager, waited a week, and someone ordered a cabinet, carried it up and placed it in your room. If you forgot to ask, your papers piled up on the floor. If the manager bought too many cabinets, they sat empty in a warehouse and cost money.

Now imagine a modern business center with a self-service counter. You fill in a short form saying “I need one cabinet, medium size, fireproof”. Within a minute, a cabinet appears in your room, exactly as described. When you no longer need it, it is taken away. Nobody wrote letters, nobody guessed in advance, and nothing sat unused.

That is dynamic provisioning. In Kubernetes, applications need disks to store their data. Instead of an administrator creating each disk by hand in advance, the cluster creates the disk automatically the moment an application asks for one. In this guide you will learn what dynamic provisioning is, why it replaced manual storage, which parts make it work, how a request travels from the application to a real disk, and how to run it safely in production. Every new word is explained the first time it appears.

1What Is Dynamic Provisioning?

A one-sentence idea with a lot of machinery behind it.

Dynamic provisioning is the ability of Kubernetes to create storage automatically, on demand, when an application requests it. The application says how much space it needs and what kind of storage it wants. Kubernetes talks to the storage system, such as a cloud disk service, asks it to create a disk of that size, and then attaches the new disk to the application.

The opposite is static provisioning, where an administrator creates disks ahead of time and registers each one in Kubernetes by hand, hoping that the disks match what applications will later ask for.

Everyday analogy

Static provisioning is a library that buys books in advance and hopes readers will want them. Dynamic provisioning is a print-on-demand shop: a reader asks for a title, and the book is printed and handed over a few minutes later. No shelf space is wasted on books nobody wants, and no reader is turned away because the exact book was not in stock.

0
Tickets needed to a storage team for each new disk
3
Key objects: claim, storage class and volume
1
Standard driver interface for all storage vendors: CSI

2The Problem: Why Manual Storage Does Not Scale

To appreciate the solution, first feel the pain of the old way.

Containers are temporary. When a container stops, everything it wrote inside itself disappears. That is perfect for web servers that keep no memory of visitors, but disastrous for databases, uploaded photos, message queues and anything else that must survive restarts. Such applications need persistent storage, which is storage that lives on after the container is gone.

Kubernetes represents this with two objects. A PersistentVolume (PV) is a piece of real storage registered in the cluster, such as a cloud disk. A PersistentVolumeClaim (PVC) is an application’s request for storage, saying how much and what kind. A claim is matched to a volume, and then the Pod uses the claim.

The static way and its pains

Pain 1

Waiting

A developer needs a disk and must ask an administrator, who creates it in the cloud console, then registers it in the cluster. Days pass.

Pain 2

Guessing sizes

Administrators create disks in advance without knowing what applications will need. Sizes rarely match, so claims stay unbound or waste space.

Pain 3

Human error

Wrong region, wrong type, a typo in a volume identifier. Each manual step is a chance for a mistake.

Pain 4

Forgotten leftovers

Disks created for a test are never deleted and keep billing every month.

Pain 5

No self-service

Teams cannot move fast, because every stateful application depends on a person outside the team.

flowchart LR
    subgraph ST["Static provisioning"]
        direction TB
        A1["Developer asks admin"] --> A2["Admin creates disk in cloud"]
        A2 --> A3["Admin registers PersistentVolume"]
        A3 --> A4["Claim finds a matching volume"]
    end
    subgraph DY["Dynamic provisioning"]
        direction TB
        B1["Developer creates claim"] --> B2["Cluster asks storage system for a disk"]
        B2 --> B3["Volume object created and bound automatically"]
    end
    
Figure 1. Static provisioning needs people in the middle. Dynamic provisioning removes them.
Storage should arrive when the application asks, not when the ticket is closed.

3Foundations: Volumes, Claims and Bindings

The storage vocabulary of Kubernetes, one word at a time.

Word

Volume

A folder that a container can read and write. Some volumes vanish with the Pod, others survive. Persistent ones survive.

Word

PersistentVolume (PV)

The cluster’s record of one real piece of storage, with its size, access rules and where it lives. It belongs to the whole cluster, not to a namespace.

Word

PersistentVolumeClaim (PVC)

An application’s request for storage. It belongs to a namespace. It says: this much space, this access style, this class.

Word

StorageClass

A named recipe describing a kind of storage, such as “fast SSD” or “cheap slow disk”, and which driver creates it.

Word

Binding

The one-to-one connection between a claim and a volume. Once bound, the volume belongs exclusively to that claim.

Word

Provisioner

The program that actually creates the real disk when a claim needs one.

Access modes

An access mode says how many machines may use the storage at once.

ModeShort nameMeaningTypical storage
ReadWriteOnceRWORead and write by one node at a timeCloud block disks
ReadOnlyManyROXRead by many nodesShared read-only content
ReadWriteManyRWXRead and write by many nodes at onceNetwork file systems
ReadWriteOncePodRWOPRead and write by exactly one PodDrivers that support it, for strict single-writer safety
Everyday analogy

The PV is a real storage locker in a warehouse. The PVC is your rental request form: “one locker, medium size, climate controlled”. The StorageClass is the price list that says what kinds of lockers exist and who builds them. Binding is the moment your key is handed over.

4The StorageClass: The Heart of Dynamic Provisioning

Everything dynamic starts with a StorageClass. Without one, there is no recipe to follow.

A StorageClass is a cluster-wide object that describes one kind of storage you offer. Administrators create a small menu of classes, for example “standard”, “fast” and “shared-files”. Developers pick from the menu by name, without needing to know any cloud details.

Fields of a StorageClass

FieldMeaningCommon values
provisionerWhich driver creates the storageA driver name such as the AWS EBS, Google persistent disk or Azure Disk CSI drivers
parametersDriver-specific optionsDisk type, speed, encryption, file system format
reclaimPolicyWhat happens to the disk when the claim is deletedDelete (default) or Retain
volumeBindingModeWhen the disk is created and boundImmediate (default) or WaitForFirstConsumer
allowVolumeExpansionWhether claims may grow laterTrue or false
mountOptionsExtra options used when mountingDriver and file-system specific
allowedTopologiesWhich zones or areas the disk may be created inA list of zone labels

The default class

One StorageClass can be marked as the cluster’s default, using a special annotation. When a claim does not name any class, Kubernetes assigns the default one. This makes life easy for beginners, since a claim with only a size will just work.

There is a subtle trap here. A claim that sets its class name to an empty text is different from a claim that leaves the field out. An empty class name means “do not use dynamic provisioning; bind me only to an existing volume that has no class”. Leaving the field out means “use the default class, if any”.

!
More than one default

Having two default classes confuses the cluster, and new claims may be rejected or picked unpredictably depending on the version. Keep exactly one default.

Everyday analogy

A StorageClass is a menu item in a restaurant: “Espresso, double shot, ceramic cup”. You order by name. The kitchen knows the recipe. If you just say “coffee”, the waiter brings the house special, which is the default class.

5Architecture and Components

Who does what when a disk is created? Here is the cast of characters.

flowchart TB
    DEV["Developer: creates claim"] --> API["API server"]
    API --> PVCTL["Volume controllers inside Kubernetes"]
    API --> PROV["CSI external provisioner sidecar"]
    subgraph CTRL["CSI controller Pod"]
        PROV
        ATT["External attacher sidecar"]
        RES["External resizer sidecar"]
        SNAP["External snapshotter sidecar"]
        DRV["CSI driver: controller service"]
    end
    PROV --> DRV
    ATT --> DRV
    RES --> DRV
    SNAP --> DRV
    DRV --> CLOUD["Storage system: cloud disk service or storage array"]
    subgraph NODE["CSI node Pod on every machine"]
        REG["Node driver registrar"]
        NDRV["CSI driver: node service"]
    end
    KL["Kubelet"] --> NDRV
    NDRV --> DISK["Mounted disk in the Pod"]
    
Figure 2. The cluster side watches objects and calls the driver. The driver talks to the storage system. The node side mounts the disk.

What is CSI?

CSI stands for Container Storage Interface. It is a standard agreement between Kubernetes and storage vendors about how to create, attach, mount, resize and snapshot disks. Before CSI, storage code lived inside Kubernetes itself, so every new storage system meant changing Kubernetes. With CSI, vendors ship a separate driver, and Kubernetes talks to every driver in the same way.

The moving parts

1

PV controller

Part of Kubernetes itself. It matches claims with volumes and manages the binding and the reclaim step.

2

External provisioner

A helper container that watches for claims that need a new volume, and asks the driver to create one. It then creates the PV object for the result.

3

External attacher

Asks the driver to connect a disk to a specific machine, for storage that must be attached before use.

4

External resizer and snapshotter

Handle growing volumes and taking point-in-time copies called snapshots.

5

The CSI driver

The vendor’s program. Its controller half talks to the storage system’s programming interface. Its node half runs on every machine and performs formatting and mounting.

6

The kubelet

The agent on each node. It asks the node half of the driver to prepare the disk and make it visible inside the Pod.

i
Tip

The helper containers are called sidecars because they run beside the driver in the same Pod. They are maintained by the Kubernetes project, so every driver reuses the same well-tested logic for watching objects, and vendors only write the storage-specific part.

6Internal Working: From Claim to Disk

Let us follow one request through every step, from the moment a developer asks for storage.

sequenceDiagram
    participant D as Developer
    participant A as API server
    participant P as External provisioner
    participant C as CSI driver
    participant S as Storage system
    participant V as PV controller
    D->>A: Create PVC with size and class
    A-->>P: Watch event: new claim needs a volume
    P->>C: CreateVolume request
    C->>S: Create disk of requested size and type
    S-->>C: Disk identifier
    C-->>P: Volume created
    P->>A: Create PV object for that disk
    A-->>V: New PV matches claim
    V->>A: Bind PV and PVC
    A-->>D: Claim status is Bound
    
Figure 3. The provisioning half of the journey: from claim to a bound volume.

Step by step

1

The claim is created

The claim is stored in the API server with status Pending. It names a class, or receives the default one automatically.

2

The provisioner notices

The provisioner sidecar for that class’s driver sees a claim that has no volume yet. It checks that the class names its driver.

3

The driver creates the disk

The provisioner calls the driver’s create-volume operation with the size and the class parameters. The driver asks the storage system to create the disk and returns its identifier.

4

The PV object is written

The provisioner creates a PersistentVolume object describing the new disk, including its identifier, size, access modes and, importantly, the zone it lives in.

5

Binding

The PV controller matches the new volume to the claim, marks both as bound, and the claim’s status changes to Bound.

6

The Pod is scheduled

The scheduler places the Pod on a machine that can reach the disk, considering the zone recorded in the volume.

7

Attach, format and mount

For block disks, the attacher connects the disk to the machine. The node half of the driver then formats it with a file system if it is new, and mounts it into the Pod’s container at the path you chose.

Everyday analogy

A developer fills in a room-booking form (the claim). A booking clerk (the provisioner) reads it, phones the hotel (the driver and the storage system), receives a room number, and writes it on the guest card (the PV). The desk (the PV controller) hands the guest card to the guest. Then the porter (the kubelet) carries the bags to the room and opens the door.

7Binding Modes: Immediate or Wait for the Pod?

One setting in the StorageClass decides whether your disk lands in the right place. It is one of the most important settings in the whole topic.

flowchart TD
    subgraph IM["Immediate mode"]
        I1["Claim created"] --> I2["Disk created at once in some zone"]
        I2 --> I3["Pod scheduled later"]
        I3 --> I4["Pod may need another zone: stuck Pending"]
    end
    subgraph WF["WaitForFirstConsumer mode"]
        W1["Claim created and waits"] --> W2["Pod is scheduled first, node and zone chosen"]
        W2 --> W3["Disk created in that same zone"]
        W3 --> W4["Pod starts normally"]
    end
    
Figure 4. Immediate mode may create a disk in the wrong place. Waiting for the first user chooses the place using the Pod.

The zone problem

Many cloud disks live in one specific availability zone, which is a separate building within a region. A Pod can only use a zonal disk if it runs on a machine in that same zone. If the disk is created immediately in zone A, but the Pod is later scheduled onto a machine in zone B because that is where free processor time exists, the Pod is stuck: the disk cannot travel.

The solution: wait for the first consumer

With WaitForFirstConsumer, the claim stays unbound until a Pod that uses it is created. The scheduler first picks a node, considering processor, memory, affinity and also storage zones. Then the provisioner creates the disk in the chosen node’s zone. The disk and the Pod always match.

AspectImmediateWaitForFirstConsumer
When is the disk created?As soon as the claim is madeWhen a Pod using the claim is scheduled
Placement chosen byThe storage driver, with little knowledge of the PodThe scheduler, with full knowledge of the Pod
Claim status before useBoundPending, which is normal
Best forStorage reachable from everywhere, such as network file systemsZonal or local disks
!
Do not panic at Pending

With the waiting mode, a claim showing Pending before any Pod uses it is expected behavior, not an error. Beginners often think something is broken. It becomes Bound when the first Pod arrives.

Production example: multi-zone database

A team runs three database replicas across three zones. Each replica has its own claim. Using the waiting mode, each disk is created in the zone where its replica was scheduled. Combined with rules that spread replicas over zones, the database survives the loss of any single zone.

8Reclaim Policy: What Happens When You Delete?

Creating storage is easy. Deleting it safely is where careers get tested.

The reclaim policy decides what happens to the real disk and its data when the claim is deleted. Dynamically created volumes take the policy from their StorageClass.

Delete (the default)

  • Deleting the claim also deletes the volume object and the real disk.
  • No leftover cost and no orphans.
  • Perfect for temporary, test and reproducible data.
  • Dangerous for data you cannot recreate.

Retain

  • Deleting the claim keeps the disk and its data.
  • The volume becomes Released and cannot be reused automatically.
  • An administrator must clean up or recover it by hand.
  • Safer for valuable data, but leftovers can keep billing.

The classic accident

A developer deletes the Kubernetes namespace of a test system, or removes the wrong claim. Under the Delete policy, the underlying cloud disks are erased along with it, and the data is gone for good. Many teams have learned this the hard way.

Protective habits

  • Use a separate class with the Retain policy for production databases.
  • You can change the reclaim policy of an already created volume to Retain before doing risky work.
  • Take snapshots or backups before destructive changes.
  • Kubernetes protects claims that are in use by Pods: a claim in use is not removed until the Pod finishes with it.
Everyday analogy

Delete is a rental locker that is emptied and cleaned the moment you hand back your key. Retain is a locker that is locked and put aside for the manager to inspect. The first is tidy and cheap. The second is safe when the contents matter.

9Data Flow and Lifecycle of a Volume

A dynamically provisioned volume passes through recognizable stages, each with its own status.

1

Claim Pending

The request exists but has no volume yet. Either the disk is being created, or the class waits for a Pod.

2

Provisioning

The driver is creating the disk. Cloud disks usually take seconds; some systems take longer.

3

Bound

The claim and volume are paired. The claim can now be used by Pods.

4

In use

A Pod mounts the volume. Data is written and read. The volume can be expanded or snapshotted during this stage.

5

Claim deleted

The application no longer needs the storage. Kubernetes waits until no Pod is still using the claim.

6

Released, then Deleted or kept

With the Delete policy, the driver removes the disk and the volume object disappears. With Retain, the volume stays as Released for manual handling.

What happens when a Pod moves?

When a Pod using a block disk is rescheduled to another machine in the same zone, Kubernetes detaches the disk from the old machine and attaches it to the new one before starting the Pod. This takes time: often tens of seconds, and sometimes minutes if the old machine failed and the cloud still thinks the disk is attached there. That delay is a real factor in how quickly a stateful application recovers.

i
Good to know

The data belongs to the claim, not to the Pod. You can delete and recreate the Pod, even change its container image, and the same data appears again, as long as the new Pod refers to the same claim.

10StatefulSets and Automatic Claims

For databases and similar software, Kubernetes can create one claim per replica automatically.

A StatefulSet is a Kubernetes controller for applications that need a stable identity and their own storage, such as database members. Instead of asking for claims one by one, a StatefulSet carries a template for claims, called volumeClaimTemplates. For each replica it creates a claim from the template, giving each replica its own disk.

flowchart LR
    SS["StatefulSet with claim template"] --> R0["Replica 0"]
    SS --> R1["Replica 1"]
    SS --> R2["Replica 2"]
    R0 --> C0["Claim 0"] --> D0["Disk 0"]
    R1 --> C1["Claim 1"] --> D1["Disk 1"]
    R2 --> C2["Claim 2"] --> D2["Disk 2"]
    
Figure 5. Each replica of a StatefulSet gets its own claim, and each claim dynamically gets its own disk.

Important behaviors

  • Claim names follow a pattern based on the template name and the replica number, so replica 1 always gets back its own disk.
  • If a replica is deleted and recreated, it reattaches to the same claim, keeping its data.
  • By default, scaling down does not delete claims. This is a safety feature, but it also means leftover disks that keep billing. Newer Kubernetes versions let you choose a retention policy that deletes claims on scale-down or on deletion of the StatefulSet.
  • Deleting a StatefulSet does not by default delete its claims either.

Production example: replicated database

A three-member database runs as a StatefulSet. Each member gets its own fast disk from the “fast” class. When one node fails, the affected member is rescheduled, its disk is reattached elsewhere in the same zone, and the member rejoins the group with all its data. Nobody creates or attaches a disk by hand.

11Expansion, Snapshots and Clones

Provisioning is only the start. Storage also needs to grow, be copied and be backed up.

Grow

Volume expansion

If the class allows it, you raise the requested size in the claim and Kubernetes asks the driver to enlarge the disk. Many drivers can also grow the file system while the Pod runs. Shrinking is not supported.

Copy in time

Snapshots

A snapshot is a point-in-time copy of a volume, requested through a VolumeSnapshot object and a matching class. Fast to take and useful for quick recovery.

Copy to new

Restore and cloning

A new claim can declare a snapshot or another claim as its data source, and the new disk starts out with that data. Good for creating test copies of production data.

Expansion rules of thumb

  • Expansion must be allowed in the class before it is needed. It is much easier to allow it from the start.
  • Only increase the size; the request to decrease is refused.
  • Cloud providers may limit how often a disk can be modified, so do not resize in tiny steps repeatedly.
  • Not every driver or file system supports online expansion. Check your driver’s notes.

Snapshots are not backups

A snapshot usually lives in the same storage system as the original. If that system fails, or someone deletes the storage account, the snapshots go too. A true backup is stored separately, ideally in another region or account. Use snapshots for speed and backups for safety.

Everyday analogy

Expansion is asking the storage room for a bigger shelf. A snapshot is taking a photograph of the shelf exactly as it looks now. A clone is building a new shelf that looks just like the photograph. A backup is keeping a second copy of everything in a different building.

12Choosing a Storage Backend

Dynamic provisioning works with many kinds of storage. The right choice depends on what your application needs.

Kind of storageExamplesAccessStrengthsCautions
Cloud block disksAWS EBS, Google persistent disks, Azure DisksUsually RWOFast, simple, well supportedTied to one zone; attach delay on failover
Cloud file systemsAWS EFS, Google Filestore, Azure FilesRWXShared by many Pods and nodes; not zone-bound in many designsHigher latency and often higher cost per GB
Software-defined storageCeph via Rook, Longhorn, OpenEBS, PortworxRWO and RWXWorks on any infrastructure, replicates data across nodesYou operate it; performance depends on your hardware
Local disksLocal SSDs on the node, a local path provisionerRWO on one nodeLowest latency, cheapData is lost or stranded if the node dies; limited dynamic support
Enterprise storage arraysVendor arrays with their own CSI driversRWO, RWXMature features like replication and snapshotsCost, vendor dependency
Object storageS3-compatible servicesNot a diskHuge and cheap; accessed by the application over the networkNot a file system; not provisioned as a volume in the usual way

Local development clusters

Small learning clusters, such as minikube and kind, come with a simple built-in provisioner that creates folders on the machine. It is perfect for practice. It offers no replication and no protection against losing the machine, so never treat it as production storage.

!
Old in-tree names

Older manifests may name provisioners with a prefix such as kubernetes.io followed by the storage type. Kubernetes has moved these built-in storage plugins to CSI drivers, and many of the old built-in ones have been removed or redirected. If you inherit an old cluster, check the migration status of your storage plugins before upgrading.

13Performance: Choosing Speed With Classes

Not all disks are equal. The StorageClass is where you decide how fast, and how expensive, a disk will be.

Three numbers that describe disk speed

Metric

IOPS

Input and output operations per second: how many small reads or writes the disk can do each second. Databases with many tiny operations care most about this.

Metric

Throughput

How many megabytes per second can flow. Analytics and backups that move big files care about this.

Metric

Latency

How long a single operation takes. Interactive applications feel latency directly.

Designing a small menu of classes

A good platform team offers a few clear classes rather than a dozen confusing ones. Here is a typical menu.

Class nameBacked byUse forReclaimExpansion
standardGeneral-purpose diskMost applications, default choiceDeleteAllowed
fastHigh-performance SSD with tuned IOPSDatabases, queuesRetain for productionAllowed
sharedNetwork file systemShared content, uploads read by many PodsDeleteAllowed
archiveCheap, slower diskLogs, rarely read dataDeleteAllowed
scratchLocal or ephemeral diskTemporary processing spaceDeleteNot needed

Performance traps

  • Size can control speed. On some cloud disk types, larger disks receive more IOPS. A tiny disk may be too slow, even if you need little space.
  • Burst credits. Some cheap disk types allow short bursts and then slow down. A test that runs for a minute can look perfect, while a real workload later crawls.
  • Per-machine limits. Each virtual machine can attach only a limited number of disks and only so much combined throughput, whatever the disk itself can do.
  • Noisy neighbors on shared storage. Network file systems and shared arrays can slow down when other tenants are busy.
  • Cross-zone traffic. Mounting network storage across zones adds delay and may add data transfer charges.
Everyday analogy

Choosing a storage class is like choosing a delivery service. Express is fast and costly, standard is fine for most parcels, and economy is cheap but slow. You do not send birthday cakes by economy, and you do not pay for express on old books.

14Scalability, Availability and Reliability

Storage is where “cattle not pets” stops being true. Data must survive what Pods do not.

1

A disk is a single copy

A cloud block disk is usually replicated inside its zone by the provider, but it lives in one zone. If the zone is lost, the disk is unavailable. Plan for this with application-level replication or backups in another zone.

2

Replicate at the application layer

Databases with built-in replication keep copies on several members, each on its own disk in a different zone. This is the standard way to survive a zone outage.

3

Or replicate at the storage layer

Software-defined storage systems copy blocks across nodes for you, allowing Pods to move without losing data, at the cost of running and tuning that system.

4

Know the attach limits

Every node can attach only a certain number of volumes. If you pack many stateful Pods onto few machines, Pods stay Pending with a volume-limit message. Drivers report their limits to the scheduler.

5

Mind the cloud API limits

Creating and attaching disks means calls to the cloud provider. A sudden mass creation, such as recreating hundreds of claims at once, can hit request limits and slow everything down. Stagger big operations.

6

Failover takes time

When a machine dies, its disks must be detached before they can be attached elsewhere. The timings depend on the cloud and on Kubernetes settings, and can stretch to minutes.

7

Capacity awareness

Some storage systems have limited free space per node or per pool. Kubernetes can track storage capacity so that the scheduler avoids placing Pods where the volume could not be created.

!
Backups

Replication protects against hardware loss but not against mistakes. If someone deletes data, or an attacker encrypts it, the replicas faithfully copy the damage. Only tested backups, stored separately, protect against that.

15Advantages, Disadvantages and Trade-offs

Dynamic provisioning is the normal way to do storage on Kubernetes, but it has costs worth understanding.

Advantages

  • Self-service: developers get storage in seconds without tickets.
  • No wasted pre-created disks and no size guessing.
  • Standard interface across many storage vendors through CSI.
  • Consistent, reviewable configuration through classes.
  • Automatic clean-up when claims are deleted.
  • Works with expansion, snapshots and cloning.
  • Fits StatefulSets so each replica gets its own disk.

Disadvantages

  • Accidental deletion can destroy data quickly under the Delete policy.
  • Easy to over-provision and forget, so costs creep up.
  • Zonal disks tie Pods to zones and slow failover.
  • Behavior varies from driver to driver.
  • The driver is another piece of software to install, secure and upgrade.
  • Bulk creation can hit cloud limits.
  • Debugging spans Kubernetes, the driver and the storage system.

The design trade-offs

Freedom versus governance. Letting every team create any size of any class is fast but expensive. Quotas and a short menu of classes keep costs in check, at the price of sometimes saying no.

Delete versus Retain. Delete keeps things tidy and cheap. Retain protects data but leaves manual work and possible orphan bills. Match the policy to how precious the data is.

Immediate versus waiting for the first user. Immediate gives quick “Bound” statuses but can place disks badly. Waiting places disks well but shows Pending until used.

Block versus file storage. Block disks are faster and simpler but usually single-writer and zonal. File systems allow sharing, but are slower and more expensive.

Cloud-managed versus self-run storage. Cloud disks are easy and reliable but tied to a provider. Self-run software-defined storage is portable but demands operations skills.

Fast to create is not the same as safe to delete.

16Security

Disks hold your most valuable asset: data. Protect them at every layer.

Layer 1

Encrypt at rest

Enable encryption in the class parameters so every new disk is encrypted with a key from your key management service. Make it the default so no one forgets.

Layer 2

Control the keys

Use separate keys for separate environments or sensitive data, restrict who can use them, and keep an audit trail of their use.

Layer 3

Limit who can create claims and classes

Use role-based access control. Developers may create claims in their own namespace; only administrators may create or change StorageClasses and volumes.

Layer 4

Namespace isolation

Claims are per namespace, so a team cannot bind another team’s claim. But volumes are cluster-wide, so guard direct access to volume objects and to Pods that can mount host paths.

Layer 5

Quotas and limits

Resource quotas can cap how much storage and how many claims a namespace may request, even per class. This limits both cost and denial-of-service by greedy or buggy automation.

Layer 6

Safe file ownership

Set the Pod security context so the volume is owned by a non-privileged group, and run containers as a normal user, not as the administrator.

Layer 7

Trust the driver

CSI node components run with high privileges on every machine. Use official drivers, pin versions, keep them patched and give their service accounts only the permissions they need.

Layer 8

Protect snapshots and clones

A snapshot contains all the data of the original. Apply the same encryption and access rules to snapshots, and restrict who can create claims from them.

Layer 9

Wipe on delete

Understand what your storage system does with deleted disks. Some systems guarantee zeroed data before reuse; for sensitive data, encryption with destroyable keys makes deleted data unreadable.

Layer 10

Secure backups separately

Store backups in a different account or region with separate credentials, and consider immutable storage so attackers cannot delete them.

!
Ransomware thinking

An attacker who reaches your cluster or cloud account may delete claims and disks, and then snapshots as well. Keep at least one backup copy outside the reach of the cluster’s own credentials.

Everyday analogy

Good storage security is like a bank vault: the door is strong (encryption), only certain staff have keys (access control), every visit is logged (auditing), the vault has a limit on deposits (quotas), and a second copy of the most valuable papers is kept in a different city (backups).

17Monitoring, Logging and Metrics

A full disk at three in the morning is a classic outage. These signals warn you long before it happens.

1

Claim status

Watch for claims stuck in Pending for longer than expected. Remember that the waiting binding mode makes Pending normal until a Pod appears.

2

Events on claims and Pods

Provisioning failures, quota errors, zone mismatches and attach or mount errors all appear as events. They are the first place to look.

3

Volume usage metrics

The kubelet reports capacity, used and available bytes, and the same for file entries called inodes, for every mounted volume. Alert at around 80 percent full, and again at 90 percent.

4

Driver and sidecar logs

The provisioner, attacher and driver containers log every request to the storage system and its answer. Errors from the cloud, such as limits or permission problems, appear here.

5

Latency and throughput

Measure read and write latency as seen by the application, and use cloud metrics for the disk itself. Compare them with what the class promises.

6

Cloud-side view

Use the provider’s tools to look for unattached disks, throttling and errors that Kubernetes cannot see.

7

Inventory and drift

Regularly list all volumes, and compare them with the claims that use them. Volumes with no claim, or Released volumes, are candidates for cleanup or investigation.

Alarms worth setting

  • Claim Pending beyond a set time with no waiting-mode explanation.
  • Volume usage above 80 percent, and inode usage above 80 percent.
  • Rate of growth predicting a full disk within a few days.
  • Pods stuck in container creating because of attach or mount errors.
  • Provisioner errors or cloud throttling messages.
  • Released or unattached volumes older than a set number of days.
i
Inodes

A disk can be “full” because it has run out of file entries, not space, especially when an application creates millions of tiny files. Watch both numbers.

18Cost Control and Governance

When creating disks is this easy, the danger is creating too many. A few guardrails keep the bill under control.

Guardrail

ResourceQuota for storage

Limits the total requested storage and the number of claims in a namespace, and can set separate limits per class, for example a small allowance for the expensive fast class.

Guardrail

LimitRange for claims

Sets minimum and maximum sizes for a single claim, stopping a typo from requesting ten terabytes.

Guardrail

Labels and cost tags

Tag every claim with a team and project label, and pass tags to the cloud through class parameters where drivers support it, so bills can be split by owner.

Guardrail

Right-sizing

Compare requested size with actual use. Start smaller and rely on expansion, rather than over-provisioning up front.

Guardrail

Orphan sweeps

Regularly find and remove volumes that no claim uses, especially Released ones and leftovers from deleted StatefulSets.

Guardrail

Lifecycle for test environments

Give temporary namespaces an automatic expiry, so their claims and disks are removed with them.

Production example: the forgotten disks

A company scales its test environments up and down every day. Each test run creates StatefulSets with large fast disks. After a year, an audit finds hundreds of unattached disks worth a large monthly bill, left behind because scaling down did not delete claims. A nightly cleanup job, an expiry label on test namespaces and a quota on the fast class cut the waste to almost nothing.

19Design Patterns and Anti-patterns

Proven habits and common traps.

Patterns that work

Pattern: A short, well-named menu of classes

Three to five classes with clear names and documented use cases. Developers choose by purpose, not by cloud jargon.

Pattern: Safe defaults

The default class is encrypted, allows expansion and uses the waiting binding mode. Anyone who forgets to choose still gets a sensible result.

Pattern: Separate classes for critical data

A dedicated class with the Retain policy and its own encryption key protects production databases from accidental deletion.

Pattern: Snapshots plus off-cluster backups

Frequent snapshots for quick restore, and periodic backups to a separate account for disaster recovery. Restore drills prove both work.

Pattern: Zone-aware stateful design

The waiting mode, spreading rules and application-level replication together give a database that survives zone loss.

Pattern: Storage as code

Classes, quotas and claim templates are kept in version control and applied automatically, so environments are reproducible.

Traps to avoid

ANTI-PATTERN 01 Avoid
What it looks like

Production databases on a class with the Delete policy and no backups.

Why it hurts

One wrong command removes both the claim and the disk, and the data is gone.

Better approach

Use a Retain class, take snapshots and keep off-cluster backups, and test restores.

ANTI-PATTERN 02 Avoid
What it looks like

Immediate binding for zonal disks in a multi-zone cluster.

Why it hurts

Disks are created in random zones, and Pods get stuck Pending because they cannot reach them.

Better approach

Use the waiting binding mode for any zonal or local storage.

ANTI-PATTERN 03 Avoid
What it looks like

Class without expansion enabled.

Why it hurts

When a disk fills up, the only fix is a risky copy of data to a new bigger disk, often under pressure.

Better approach

Allow expansion from the start, and monitor usage so you grow before it is urgent.

ANTI-PATTERN 04 Avoid
What it looks like

Using local, node-bound storage for data that cannot be rebuilt.

Why it hurts

If the node dies, the data is stranded or lost, and the Pod cannot move.

Better approach

Use replicated storage, or make sure the application replicates its own data across nodes.

ANTI-PATTERN 05 Avoid
What it looks like

Treating a snapshot as the only backup.

Why it hurts

Snapshots usually live with the original disk and share its fate and its credentials.

Better approach

Copy backups to another account or region and protect them from deletion.

20Best Practices and Common Mistakes

A checklist for storage that stays safe, fast and affordable.

Habits that pay off

  • Use CSI drivers from your cloud or storage vendor, and keep them updated in step with Kubernetes upgrades.
  • Enable expansion and encryption in every class from the start.
  • Prefer the waiting binding mode for zonal and local storage.
  • Pick the reclaim policy per class and document what each class does on deletion.
  • Set quotas and size limits per namespace.
  • Monitor usage and growth, including inodes, and alert early.
  • Test restores on a schedule. A backup you have never restored is only a hope.
  • Use claim templates in StatefulSets rather than hand-made claims.
  • Check driver limits such as maximum volumes per node before packing stateful Pods.
  • Practice failure: kill a node running a stateful Pod in a test cluster and time the recovery.

Mistakes beginners make

Mistake

No default class and no class name

The claim stays Pending forever because nothing knows how to create the disk.

Mistake

Typing the class name wrong

The claim refers to a class that does not exist, so no provisioner picks it up.

Mistake

Empty class name by accident

Setting the class to an empty text disables dynamic provisioning, and the claim waits for a matching pre-made volume.

Mistake

Driver not installed

The class names a driver that is missing from the cluster, so nobody responds to the claim.

Mistake

Missing cloud permissions

The driver cannot create disks because its cloud identity lacks the right to do so. The logs show a permission error.

Mistake

Using one disk from two nodes

A single-writer block disk requested by Pods on different machines. The second Pod cannot attach it.

Mistake

Deleting the namespace casually

The claims disappear with it, and under the Delete policy, so does the data.

Mistake

Confusing StorageClass immutability

Most fields of a class cannot be edited after creation. To change them, create a new class and migrate.

21Real-World and Industry Examples

How real teams use dynamic provisioning every day.

Managed Kubernetes on the big clouds

On the major managed services, a default StorageClass backed by the provider’s block disks is normally present out of the box, so a claim with only a size produces a working disk. Teams add their own classes for fast and shared storage.

Databases as operators

Database operators for PostgreSQL, MySQL, MongoDB, Kafka and others rely on StatefulSets and claim templates. The operator sets the class, size and spreading rules, so a whole database cluster, with a disk per member, appears from a short description.

Shared content with file storage

A publishing company stores uploaded images on a network file system class, so many web Pods on many machines read and write the same folder. Content survives Pod restarts and scaling events.

Self-managed clusters

Organizations running Kubernetes in their own data centers use software-defined storage such as Ceph through Rook, Longhorn or vendor arrays with CSI drivers. They get the same claim-based experience as the cloud, with their own hardware.

Data science and machine learning

Notebook servers give each user a personal disk that follows them across sessions. Training jobs use fast scratch space, and datasets are cloned from snapshots so experiments always start from the same data.

A typical online shop

The shop’s orders database runs as three replicas across three zones, each on its own fast disk with the Retain policy, with hourly snapshots and nightly backups copied to another account. Product images use a shared file class. The web tier uses no persistent storage at all. When traffic grows, the team expands the database disks with a single change, and no downtime is needed.

22Troubleshooting Storage Problems

Follow the request from the claim to the mount, and the fault reveals itself.

flowchart TD
    S1["Pod stuck or claim Pending"] --> S2{"Claim status?"}
    S2 -->|Pending| S3{"Class exists and driver installed?"}
    S3 -->|No| F1["Fix class name or install driver"]
    S3 -->|Yes| S4{"Waiting binding mode and no Pod yet?"}
    S4 -->|Yes| F2["Normal: create the Pod"]
    S4 -->|No| F3["Read provisioner and driver logs: permissions, quota, cloud limits"]
    S2 -->|Bound| S5{"Pod status?"}
    S5 -->|Pending| F4["Zone mismatch, volume limit per node or affinity conflict"]
    S5 -->|Container creating| F5["Attach or mount error: check events and node driver logs"]
    S5 -->|Running but failing| F6["Permissions, full disk, file system errors"]
    
Figure 6. A troubleshooting path from claim to running Pod.
SymptomLikely causeWhat to check
Claim Pending, no eventsNo class and no default classList classes, check the default marker and the claim’s class name
Claim Pending, provisioning failed eventDriver error, quota or permissionsProvisioner and driver logs; cloud identity permissions
Claim Pending, “waiting for first consumer”Waiting binding mode, no Pod yetCreate the Pod that uses the claim
Pod Pending with volume node affinity conflictDisk is in a different zone than available nodesNode zones, disk zone, Pod placement rules
Pod Pending with too many volumesNode attach limit reachedDriver limits; spread stateful Pods over more nodes
Pod stuck in container creatingAttach or mount failing; disk still attached to a dead nodeEvents; cloud console attachment status
Multi-attach errorSingle-writer disk requested by a second nodeWhich Pods use the claim and where they run
Expansion not completingFile system resize needs a Pod restart or driver supportClaim conditions and driver notes
Application reports no spaceDisk or inodes are fullVolume usage metrics; expand the claim
Claim stuck TerminatingA Pod still uses itFind and remove the Pod

23Frequently Asked Questions

Short answers to the questions people ask most.

Q1What is dynamic provisioning in one sentence?
It is Kubernetes creating a real storage volume automatically when an application submits a claim, using the recipe in a StorageClass and a driver for the storage system.
Q2Do I still need to create PersistentVolumes by hand?
Not with dynamic provisioning. The provisioner creates the volume object for you. Manual volumes are only needed for special cases, such as attaching an existing disk that already holds data.
Q3What if my claim does not name a class?
If the cluster has a default StorageClass, it is used. If there is no default, the claim stays Pending. If the class name is set to an empty text, dynamic provisioning is turned off for that claim.
Q4Why is my claim Pending when no Pod uses it?
If the class uses the waiting binding mode, that is normal. The disk is created only after a Pod that uses the claim is scheduled.
Q5What happens to my data when I delete a claim?
It depends on the reclaim policy of the volume. With Delete, the disk and data are removed. With Retain, the disk and data are kept, and an administrator handles them manually.
Q6Can I change a StorageClass after creating it?
Most fields are fixed at creation. Create a new class with the settings you want and move workloads to it. Some fields, such as allowing volume expansion, can be updated in place on recent versions.
Q7Can I make a claim smaller?
No. Kubernetes supports growing claims but not shrinking them. To reduce size, create a new smaller claim, copy the data and remove the old one.
Q8How do I share a volume between many Pods?
Use a storage class backed by a shared file system that supports the many-writers access mode. Ordinary cloud block disks are usually single-node.
Q9What is the difference between a snapshot and a backup?
A snapshot is a quick point-in-time copy that usually lives with the original storage. A backup is stored separately, ideally in another region or account, so it survives the loss of the original system.
Q10What is CSI and why does it matter?
CSI is the standard interface between Kubernetes and storage systems. It lets vendors ship their own drivers, so Kubernetes supports many storage systems in one consistent way, without changing Kubernetes itself.
Q11Is dynamic provisioning safe for production databases?
Yes, when you choose the right class, use the Retain policy where appropriate, replicate across zones at the application level, keep tested backups and monitor usage. The mechanism is sound; the safety comes from these habits.

24Summary and Key Takeaways

You began with a business center where filing cabinets arrive on request. Now you know how a cluster does the same for disks.

Key Takeaways

  • The idea: Dynamic provisioning creates real storage automatically when a claim is made, using a StorageClass recipe and a CSI driver, so no administrator has to prepare disks in advance.
  • The flow: A claim is created, the provisioner asks the driver for a disk, a volume object is written and bound, the Pod is scheduled, and the disk is attached, formatted and mounted.
  • Two key settings: The binding mode decides where the disk lands, and the waiting mode is best for zonal storage. The reclaim policy decides what happens on deletion, so use Retain for precious data.
  • Grow and protect: Enable expansion from the start, use snapshots for speed, and keep real backups outside the cluster’s reach.
  • Design for failure: Disks live in one zone, failover takes time, and nodes have attach limits, so replicate at the application or storage layer and spread across zones.
  • Secure and govern: Encrypt by default, restrict who can create classes and claims, use quotas and size limits, patch the drivers and watch for orphaned volumes that keep costing money.
  • Observe it: Alert on Pending claims, mount errors, volume and inode usage, growth trends and provisioner errors, and rehearse restores and failovers before you need them.