Skip to main content

Kubernetes SIG Storage's Next Move Isn't Another Snapshot Feature: What Volume Health Monitoring and Mutable PV Affinity Actually Buy a Self-Hosted Fleet

8 min readDora NodaDora Noda
Share
On this page

Kubernetes SIG Storage's June 2026 roadmap spotlight — an interview with co-chair Xing Yang — names a handful of things coming after Volume Group Snapshot's GA in v1.36. One of them, Changed Block Tracking, builds on the same CSI snapshot machinery this blog already picked apart in detail: Hetzner's own hcloud-csi driver has never implemented the CSI Snapshot API, so anything riding on it — Volume Group Snapshot, Changed Block Tracking, CloudNativePG's fast snapshot-based restore — is simply not available on stock Hetzner Cloud Volumes today, full stop.

That leaves two other items in the same spotlight that nobody's checked against Hetzner yet: Volume Health Monitoring and Mutable PV Affinity. Neither touches the CSI snapshot API at all, which means neither one lives or dies by the same GitHub issue. Each fails — or works — for its own, completely separate reason. Here's the verified breakdown of both, and the concrete yes-or-no answer for a self-hosted, Cluster-API-Provider-Hetzner (CAPH) fleet.

FeatureKEPKubernetes statusDepends on CSI driver support?Works on stock Hetzner Cloud Volumes?
Volume Group SnapshotKEP-3476GA in v1.36Yes — CSI snapshot APINo
Changed Block TrackingKEP-3314Alpha (Sept 2025) → Beta in v1.36Yes — CSI snapshot API + SnapshotMetadata serviceNo
Volume Health MonitoringKEP-1432Alpha since v1.19, redesigned, new alpha targeted v1.37Yes — VOLUME_CONDITION capability + sidecarsNo
Mutable PV AffinityKEP-5381Alpha in v1.35, gate MutablePVNodeAffinityNo — apiserver + kubelet onlyYes

The first two rows are the subject of this blog's earlier CloudNativePG post — both die on the same missing CreateSnapshot implementation. The bottom two rows are what the rest of this post actually verifies.

Volume Health Monitoring: the feature that's been in alpha since 2020

Volume Health Monitoring is KEP-1432, and it is not new. It first shipped alpha in Kubernetes v1.19, back in 2020, got redesigned in v1.21, and — per its own KEP milestones and the June 2026 spotlight — is now targeting a second alpha in v1.37. Six years in, it's still not past the gate it started at.

The goal is straightforward: let a CSI driver and the control plane report that a specific volume has gone bad — device gone missing, a filesystem read-only remount after corruption, an underlying disk giving I/O errors — as a first-class Kubernetes signal instead of a mystery CrashLoopBackOff an operator has to trace back to storage by hand. Xing Yang is explicit in the spotlight about where this actually stands: "We are actively investigating enhancements to this feature with the goal of supporting automated remediation capabilities in the future." That's a stated intent, not a shipped capability — today the feature only ever emits informational Kubernetes events, and nothing acts on them automatically.

The mechanism matters more than the roadmap date, because it decides whether any of this reaches a given fleet at all. A CSI driver has to declare the VOLUME_CONDITION node capability and implement abnormal-condition reporting inside NodeGetVolumeStats, and the cluster typically runs the external-health-monitor-controller and external-health-monitor-agent sidecars alongside it. Nothing about that is automatic just because a Kubernetes version ships the feature gate — the driver has to opt in.

Hetzner's driver doesn't. A look at hetznercloud/csi-driver's node.go shows NodeGetCapabilities declaring exactly two node capabilities: EXPAND_VOLUME and GET_VOLUME_STATS. No VOLUME_CONDITION. Its deployment manifest ships csi-node-driver-registrar, livenessprobe, csi-attacher, csi-resizer, and csi-provisioner — no health-monitor sidecar anywhere in the list. The driver does implement basic NodeGetVolumeStats — filesystem byte and inode usage numbers work fine — but it never reports that a volume is unhealthy. That's a distinct blocker from the snapshot gap covered in the CNPG post: different capability, different missing sidecar, no GitHub issue #849 involved. Volume Health Monitoring simply isn't wired up on Hetzner, independent of whichever Kubernetes version the cluster is running.

Mutable PV Affinity: the one feature that doesn't care what your CSI driver supports

KEP-5381, Mutable PV Affinity, shipped alpha in Kubernetes v1.35 behind a disabled-by-default feature gate named MutablePVNodeAffinity. The problem it solves is narrow but real: PersistentVolume.spec.nodeAffinity has been immutable since Kubernetes v1.10, so when a cloud disk gets migrated from zonal to regional storage — or its underlying disk type changes — the PV's stale affinity keeps blocking pods from scheduling onto any node outside the original zone, and the only fix has been deleting and recreating the PV.

What makes this feature genuinely different from Volume Health Monitoring is where the fix lives. Per the KEP text itself, Mutable PV Affinity touches exactly two components: kube-apiserver, which relaxes its validation to allow updating nodeAffinity after the PV already exists, and kubelet, which gets a check in waitForVolumeAttach() so a pod fails cleanly instead of hanging in ContainerCreating if the updated affinity no longer matches the node it landed on. The KEP explicitly requires no changes to any CSI driver, no external-provisioner changes, no controller-manager changes. It's an API-validation relaxation plus a kubelet-side safety check — nothing downstream of the apiserver has to know or care which storage backend is involved.

That's the concrete asymmetry worth sitting with: a tenant on a managed Kubernetes service — GKE, EKS, AKS — generally can't flip an alpha feature gate on someone else's control plane at all. An operator running their own Cluster-API-provisioned control plane can, today, on Hetzner or any other infrastructure CAPH manages, the moment they're willing to run an alpha feature. The honest caveat: nothing automates the actual nodeAffinity patch yet. A human, or some external controller a platform team writes, still has to decide when and how to mutate the field — this is a lever a self-hoster has access to, not a finished automation.

That "still needs a controller to decide when to mutate the field" gap is exactly the shape of problem an operator-facing automation is supposed to close, and it's worth naming directly: a fleet whose machine and volume state is exposed as structured, machine-readable Kubernetes objects — the same objects Cluster API already models as Machine, PersistentVolume, and MachineHealthCheck — is a fleet where deciding "this PV's node affinity is stale, patch it" doesn't have to wait on a human noticing. It's a comparison a CSI-driver-dependent feature like Volume Health Monitoring can't offer yet, precisely because the signal it would act on doesn't exist on Hetzner in the first place.

Where this leaves a Hetzner-backed operator's runbook

Nothing here changes the snapshot-dependent story already covered: Volume Group Snapshot and Changed Block Tracking both ride the same CSI snapshot machinery Hetzner's driver has never implemented, so a backup strategy built on either one is still a non-starter on stock hcloud-csi, and the object-storage-based WAL archiving path (or a swapped-in CSI layer like Piraeus/LINSTOR) remains the actual answer for that specific problem.

Volume Health Monitoring being blocked means the same is true for storage-failure alerting: there's no Kubernetes-native signal telling an operator "this specific PVC's underlying disk is failing" on Hetzner today, regardless of which Kubernetes version the cluster runs. External monitoring — node-level disk health checks, application-level I/O error logging, NodeGetVolumeStats's basic capacity numbers wired into existing metrics — stays necessary, not a stopgap for a feature that's about to land.

Mutable PV Affinity is the one net-new lever in this pair that's actually available today, not blocked on a driver that hasn't shipped a capability. It solves a capacity-planning problem, not a backup one: rebalancing a PV across nodes, zones, or disk types without a delete-and-recreate cycle, the moment a platform team decides that's worth running on an alpha gate.

What to actually do about it

For a Cluster-API-managed Hetzner fleet, three concrete moves fall out of this:

  • Turn on MutablePVNodeAffinity now if PV rebalancing is a real need — it's alpha, disabled by default, and requires no CSI driver support, so the only gate is a platform team's own tolerance for running an alpha feature on their own control plane.
  • Don't wait on Hetzner's CSI driver for native health signals. Neither VOLUME_CONDITION reporting nor a health-monitor sidecar exists in the driver today, and there's no public signal it's coming. Keep whatever external disk/node health monitoring a fleet already runs.
  • Track Volume Health Monitoring's second alpha in v1.37, and Changed Block Tracking's driver adoption, as roadmap items — not inputs to today's runbook. Both are real, both are moving, and neither is close enough to being usable on Hetzner's own driver to plan around yet.

bex is the open-source, AI-native Render alternative — push a git repo, get a running HTTPS service on machines you own, built on Cluster API so the machine fleet underneath is yours to reason about, alpha feature gates included. Star the repo on GitHub or deploy your first app today.

Sources

Related articles

Run this on infrastructure you own

bex is the open-source, AI-native Render alternative — push a git repo and get a running HTTPS service on your own machines.

Get started with bex