Skip to main content

Storage classes reference

Inspect 1.36

Every StorageClass on the cluster in one table. Use it to check which provisioner backs a class, whether it can grow, and what happens to the data when a PVC is deleted.

The classes#

Class Provisioner Access modes Binding Reclaim Expandable Backed by
standard (default) csi.hetzner.cloud RWO WaitForFirstConsumer Retain Yes Hetzner Cloud volumes, cloud nodes
local-nvme topolvm.io RWO WaitForFirstConsumer Retain Yes NVMe disks on bare metal
local-ssd topolvm.io RWO WaitForFirstConsumer Retain Yes SATA SSD disks on bare metal
local-hdd topolvm.io RWO WaitForFirstConsumer Retain Yes HDD disks on bare metal
juicefs csi.juicefs.com RWX, RWO, ROX Immediate Retain Yes Object storage plus a metadata engine

standard is present and set as default on every cluster. The local-* classes appear once you , and juicefs appears once you . List what your cluster has right now:

		$ kubectl get storageclasses
NAME                 PROVISIONER         RECLAIMPOLICY   VOLUMEBINDINGMODE      ALLOWVOLUMEEXPANSION   AGE
local-hdd            topolvm.io          Retain          WaitForFirstConsumer   true                   10d
local-nvme           topolvm.io          Retain          WaitForFirstConsumer   true                   10d
local-ssd            topolvm.io          Retain          WaitForFirstConsumer   true                   10d
standard (default)   csi.hetzner.cloud   Retain          WaitForFirstConsumer   true                   10d
	

Reading the columns#

Access modes decide how many nodes can mount a volume. The block and local classes are ReadWriteOnce; only juicefs offers ReadWriteMany. See .

Binding is when the volume is created. WaitForFirstConsumer waits for a pod so the volume lands where the pod runs. Immediate creates it as soon as the PVC exists, which suits object-backed storage that has no location to match.

Reclaim is Retain on every class, on purpose. Deleting a PVC deletes the Kubernetes object, not the data behind it: the underlying volume is kept, not erased. Syself would rather a mistaken delete leave your data intact than let one command wipe it.

The flip side is that cleanup is a deliberate act. A Hetzner Cloud volume keeps costing money until you delete it yourself, and a local volume keeps holding pool space until you remove it. See and for how to reclaim the space when you mean to.

Important

Deleting a PVC or PV never deletes the data on its own. If you truly want the data gone, delete the underlying Hetzner Cloud volume or remove the local logical volume as a separate, intentional step.

Expandable means you can grow a volume by editing the PVC. Every class allows expansion. Volumes only grow, they never shrink. See .

Backed by is the storage behind each class. standard is Hetzner Cloud volumes on cloud nodes: each volume sits on Ceph with three copies, so losing a disk does not lose the data. Hetzner attaches at most 16 volumes to one server, so plan for that ceiling on a volume-heavy node. The local-* classes are disks inside one bare metal server and carry no built-in redundancy, so keep the data replicated in the app.

The default class and how to change it#

A PVC with no storageClassName uses the default class, marked (default) in the list above.

To make a different class the default, clear the flag on the current one and set it on the new one:

Clear the flag on the current default #

Clear the current default
		$ kubectl patch storageclass standard -p '{"metadata":{"annotations":{"storageclass.kubernetes.io/is-default-class":"false"}}}'
	

Set the flag on the new class #

Set the new default
		$ kubectl patch storageclass local-nvme -p '{"metadata":{"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'
	
Tip

Prefer naming the class explicitly in each PVC (storageClassName: local-nvme) over relying on the default. It makes the intent obvious and survives a change to which class is default.