To cut Kubernetes storage cost, default your StorageClass to gp3 instead of gp2, right-size PersistentVolumeClaims to real used capacity, enable volume expansion so you can grow on demand, and delete released volumes that nothing will rebind. You pay for provisioned gibibytes, not used ones, so an oversized claim or an orphaned PersistentVolume bills in full. gp3 costs about 0.08 US dollars per gibibyte-month versus 0.10 for gp2, roughly 20 percent less, with 3,000 IOPS and 125 MB/s baseline included. Set the cheap, expandable class as the cluster default and most new spend is controlled automatically.
Last updated: June 2026. Written by Fredrik Filipsson and reviewed by Morten Andersen, built on our See, Cut, Lock, Run method.
This article sits in our complete guide to Kubernetes cost optimization, the cluster pillar it links up to, and connects to the broader cloud cost optimization playbook. Storage caps belong inside the same namespace guardrails as compute, so pair this with our companion guide on how to implement Kubernetes resource quotas and LimitRanges for cost. Clearing orphaned volumes is a classic Cut step move: zombie spend removed before you optimize what remains.
Default your cluster StorageClass to gp3 with allowVolumeExpansion enabled, and make sure no class your developers reach still points at gp2. The default is what every claim that omits a class will use, so getting it right fixes cost for all new volumes without touching a single manifest. gp3 is cheaper per gibibyte and lets you provision IOPS and throughput separately, so you stop buying oversized disks just to get performance. Set the default once, and the savings compound on every future claim.
What is a StorageClass, and why does it control cost?
A StorageClass is a Kubernetes object that defines how a PersistentVolume is dynamically provisioned: which CSI driver creates the disk, the volume type and parameters such as gp3, the reclaim policy, and whether the volume can be expanded later. It controls cost because every PersistentVolumeClaim that references it inherits those settings, so the class is where you decide the price and elasticity of all storage created from it. Point the default class at a cheap, expandable type and new claims are cost-controlled automatically; leave it on an old gp2 class and every team quietly provisions more expensive disks. The Kubernetes storage classes reference documents the full parameter set.
Should I use gp3 or gp2 for persistent volumes?
Use gp3 for almost all Kubernetes persistent volumes. According to Amazon EBS pricing, gp3 costs about 0.08 US dollars per gibibyte-month versus 0.10 for gp2 in US East, roughly 20 percent less, and includes 3,000 IOPS and 125 MB/s of baseline throughput you can provision independently of capacity. gp2 ties performance to size at 3 IOPS per gibibyte, which forces teams to over-provision storage purely to reach the throughput they need. With gp3 you size the disk for capacity and dial in IOPS separately, so you stop paying for gibibytes you only bought to unlock speed. Default the StorageClass to gp3 and migrate gp2 volumes as workloads cycle.
How do I cut storage cost, step by step?
Cut storage cost by auditing what exists, defaulting to the cheaper class, right-sizing claims, and removing orphans. Six steps:
- Audit current volumes and classes. List every PersistentVolume and PersistentVolumeClaim with its StorageClass, size, and bound status. Result: oversized and unbound volumes surfaced.
- Default the StorageClass to gp3. Mark a gp3-backed class as the cluster default. Result: new claims provision the cheaper, performance-decoupled volume.
- Right-size PVC requests. Reduce claim sizes to match real used capacity. Result: you stop paying for provisioned gibibytes the filesystem never touches.
- Enable volume expansion. Set allowVolumeExpansion true on the class. Result: you start small and grow on demand instead of reserving headroom up front.
- Set reclaim policy deliberately. Use Delete where data is reproducible, Retain only where it must survive. Result: volumes are cleaned up with their claim unless you intend otherwise.
- Remove released and unbound volumes. Delete PVs in Released or Available state that nothing will rebind. Result: orphaned storage stops billing.
Want every oversized and orphaned volume found and cleared?
Our Kubernetes cost audit inventories every PersistentVolume, flags oversized claims and Released orphans, migrates gp2 to gp3, and sets expandable defaults so storage stays lean. On the performance model, you pay only from realized savings. No savings, no fee.
Book a Kubernetes cost audit →Why am I still paying for volumes I thought I deleted?
You are still paying because the PersistentVolume reclaim policy was set to Retain, so deleting the claim left the underlying cloud disk and the PV behind in a Released state that keeps billing as provisioned storage. Retain is the safe default for data you cannot lose, but it means cleanup is manual: the PV does not disappear when the workload does. These Released and Available volumes are pure zombie spend once nothing will rebind them. Audit regularly with kubectl get pv, filter for Released and Available status, confirm the data is genuinely unneeded, and delete both the PV and its backing cloud disk. For reproducible data such as caches and scratch space, set the reclaim policy to Delete so this never accumulates in the first place.
Do I pay for provisioned or used capacity?
You pay for provisioned capacity, not used capacity. A 100 gibibyte PersistentVolumeClaim backed by a cloud block volume bills for all 100 gibibytes even if the filesystem holds only 10, because the cloud provider charges for the disk you reserved, not the bytes you wrote. This is the core reason right-sizing claims pays off: most teams pad PVC sizes with headroom they never use. The disciplined pattern is to start the claim near real usage, enable allowVolumeExpansion on the StorageClass, and grow the volume on demand when utilization climbs. You get the safety of expansion without paying for empty space from day one.
The Kubernetes Cost Optimization Handbook includes the storage class migration checklist and the orphaned-volume audit query referenced above. It is the downloadable companion to this guide.
Frequently asked questions
Should I use gp3 or gp2 for Kubernetes persistent volumes?
Use gp3 for almost all Kubernetes persistent volumes. gp3 costs about 0.08 US dollars per gibibyte-month versus 0.10 for gp2 in US East, roughly 20 percent less, and includes 3,000 IOPS and 125 MB/s of baseline performance you can provision independently of capacity. gp2 ties performance to size at 3 IOPS per gibibyte, which forces you to over-provision storage just to get throughput. Default your StorageClass to gp3 and migrate gp2 volumes as they cycle.
Why am I still paying for deleted Kubernetes volumes?
You are paying because the PersistentVolume reclaim policy was set to Retain, so deleting the claim left the underlying cloud disk and PV behind in a Released state that still bills as provisioned storage. Released and Available volumes that nothing will rebind are orphaned spend. Audit for them with kubectl get pv, confirm the data is not needed, and delete the volume and its backing disk to stop the charge.
Do I pay for provisioned or used PVC capacity?
You pay for provisioned capacity, not used. A 100 gibibyte PersistentVolumeClaim backed by a cloud block volume bills for all 100 gibibytes even if the filesystem only holds 10. That is why right-sizing claims and enabling volume expansion matter: start the claim near real usage, turn on allowVolumeExpansion, and grow it on demand rather than reserving headroom you pay for from day one.
What is a StorageClass in Kubernetes?
A StorageClass is a Kubernetes object that defines how a PersistentVolume is dynamically provisioned, naming the CSI provisioner, the volume type and parameters such as gp3, the reclaim policy, and whether the volume can be expanded. When a PersistentVolumeClaim references a StorageClass, the cluster creates a matching cloud volume automatically. Setting a cheap, expandable class as the cluster default is the single most effective storage cost control.
The short version
Default your StorageClass to gp3, right-size every PersistentVolumeClaim to real usage, enable volume expansion so you grow on demand, set reclaim policies deliberately, and delete Released volumes that keep billing. You pay for what you provision, so the lever is provisioning less and cleaning up promptly. When you want every volume audited and migrated for you, that is what our rightsizing and waste elimination service delivers.
Cloud pricing and service behavior change frequently. Verify the specifics in this guide against the providers’ own current documentation and the FinOps Foundation: FinOps Foundation Framework ↗ and FinOps Rate Optimization capability ↗. This article also reflects Cloud Cost Room’s hands-on, vendor-neutral engagement experience.