ZFS LocalPV
Wrapper chart for the upstream zfs-localpv chart (pinned to 2.10.1,
appVersion 2.10.1), OpenEBS's CSI driver (zfs.csi.openebs.io) that provisions ZFS dataset-backed local
PersistentVolumes, with snapshot/clone and per-volume ZFS tuning (recordsize, compression, dedup).
Why it's in KubeAid
Not currently rendered automatically by kubeaid-cli (no entry in pkg/constants/templates.go) — it's an
opt-in chart for Hetzner bare-metal clusters that allocate NVMe disks to a mirrored ZFS pool, per
docs/hosting/cloud-providers.md's bare-metal disk-layout guidance ("Allocate NVMes to a ZPool (mirror mode) for
ContainerD, logs, and OpenEBS ZFS LocalPV"). Where it's used, it's the higher-performance NVMe-backed alternative
to localpv-provisioner's hostPath storage.
Prerequisites
-
A ZFS pool already created on every node that will run the driver, e.g.:
sudo zpool create -m /mnt/nvmelocal mypool mirror /dev/sdb /dev/sdc(assuming
/dev/sdband/dev/sdcare the disks for the mirrored pool, andnvmelocalis the pool name, mounted at/mnt/nvmelocal; usesudo fdisk -lto check available drives first). -
Nodes labelled so
zfsController/zfsNodeland only where the pool exists — this chart's defaultnodeSelectorisdisk: nvme(label nodes withkubectl label node <name> disk=nvme, andfilesystem=zfsif scoping further, e.g. via a customnodeSelector— see examples/values-nodeselector.yaml). Verify withkubectl get node <node_name> --show-labels.
Key values / KubeAid-specific configuration
Upstream values live under the zfs-localpv: key; the chart adds one KubeAid-specific top-level key.
zfs-localpv.zfsNode.nodeSelector/zfsController.nodeSelector:disk: nvme— restrict the driver to NVMe-labelled nodes (values.yaml).zfs-localpv.zfsExporter: a Prometheus exporter (obmondo/zfs_exporter, fromharbor.obmondo.com/) is bundled and enabled by default, with aServiceMonitorscraping/metricsevery 10s on port 9134.zfs-localpv.zfsNode.priorityClass.name: zfs-csi-node-critical/zfsController.priorityClass.name: zfs-csi-controller-critical— dedicatedPriorityClasses, created by default.storageClass.enabled(defaultfalse, chart-added key) — whentrue,templates/storageclass.yamlrenders azfs-localpvStorageClass(and, ifstorageClass.shared: true, also azfs-localpv-sharedone) usingstorageClass.poolName(required when enabled) andstorageClass.reclaimPolicy(defaultDelete). See examples/values-storageclass.yaml for a worked example; confirm withkubectl get sconce deployed.zfs-localpv.crds.csi.volumeSnapshots.enabled/zfsController.snapshotController.enabled:false— the VolumeSnapshot CRDs and thesnapshot-controllercome from thesnapshot-controllerchart, which every cluster taking volume snapshots needs.
Upgrading
Earlier versions installed the VolumeSnapshot CRDs and ran a snapshot-controller container in the controller
pod. On a cluster that ran those, roll out in this order:
- Deploy the
snapshot-controllerchart and sync it, so its Argo CD app takes over thesnapshot.storage.k8s.ioCRDs. - Sync zfs-localpv without pruning, and check the CRDs no longer show under the zfs-localpv app.
Syncing zfs-localpv with pruning while it still owns the CRDs can delete them, and every VolumeSnapshot,
VolumeSnapshotContent and VolumeSnapshotClass with them. To keep the bundled pieces instead, set both values
back to true and don't run the snapshot-controller chart.
Docs links
- Upstream chart & storageclass reference: https://github.com/openebs/zfs-localpv/blob/develop/docs/storageclasses.md
- OpenEBS docs: https://openebs.io/docs
- Hetzner bare-metal disk layout
- KubeAid: Helm umbrella pattern