Helm Values Reference¶
This reference describes the configurable values for the zfs-csi Helm chart, which lives
in the repository under charts/zfs-csi. The chart is version 0.1.0 with an appVersion
of dev.
The chart declares kubeVersion: ">=1.36.0-0" and depends on the pinned
bitnami/common library chart
(oci://registry-1.docker.io/bitnamicharts, version 2.41.0, recorded in Chart.lock).
Run helm dependency build charts/zfs-csi before helm template, helm lint, or
helm install from a source checkout; packaged releases already vendor the dependency.
The library supplies the standard app.kubernetes.io/* and helm.sh/chart object labels
and the image-reference helper. Workload spec.selector.matchLabels and pod template
labels are deliberately left unchanged, because those are immutable on existing objects
and would otherwise roll every workload on an unrelated chart version bump.
Top-Level Values¶
| Key | Type | Default | Description |
|---|---|---|---|
namespace |
string | "" |
Namespace the driver components run in. Defaults to the Helm release namespace. |
Image¶
| Key | Type | Default | Description |
|---|---|---|---|
image.repository |
string | ghcr.io/randomvariable/zfs-csi |
Container image repository. Override with your own registry. |
image.tag |
string | "" |
Image tag. Defaults to the chart appVersion when empty. |
image.digest |
string | "" |
Immutable image digest. When set, takes precedence over image.tag and renders an image reference using the digest. |
image.pullPolicy |
string | IfNotPresent |
Image pull policy. |
Storage Node¶
Storage owner configuration
storageNode configures one legacy logical owner. For multiple owners, use the
storageOwners list and configure each owner's placement, pool GUIDs, network domains, and
NFS/NVMe endpoints explicitly.
authoritativePoolGUIDs remains plural for NVMe and future topology. In this release, an
enabled owner with more than one GUID cannot be combined with an enabled chart NFS
StorageClass. No owner-scoped NFS switch exists: disable tankNFS, tankNFSTLS, and
flashNFS, or split NFS pools across owners with distinct endpoints and separate host nfsd
instances.
These values currently pin the controller Deployment, storage agent, and nvmet controller to
one ZFS host.
| Key | Type | Default | Description |
|---|---|---|---|
storageNode.name |
string | "" |
Required when controller.enabled, storage.enabled, or nvmet.enabled is true. Kubernetes node name hosting the ZFS pool. |
storageNode.authoritativePoolGUIDs |
string list | [] |
Immutable administrator-declared decimal pool GUID set for the logical owner. Required when rendering StorageNode. |
storageNode.networkDomain |
string | workers |
Immutable reachability domain published by the owner. Kubernetes label value, not an endpoint. |
storageNode.enabled |
boolean | true |
Allows fresh owner inventory to participate in new placement. |
storageNode.selector |
map | {kubernetes.io/arch: amd64, zfs.csi.randomvariable.co.uk/storage: "true"} |
Node selector for legacy storage-owning components and nvmet. The storage node must carry these labels. Explicit storageOwners[].nodeSelector maps also receive the amd64 selector. |
storageNode.tolerations |
list | Tolerates key zfs.csi.randomvariable.co.uk/storage, value "true", effect NoSchedule |
Tolerations so the components schedule onto the tainted storage node. |
storageNode.poolMountRoot |
string | /tank |
Host directory where the ZFS pool mounts its datasets (the pool's mountpoint; a pool named tank mounts at /tank). Bind-mounted with Bidirectional propagation so datasets the storage agent mounts inside its container appear in the host mount namespace, which the node's in-kernel NFS server requires to export a populated path. |
Network¶
When network.tls.enabled=true, Kubernetes 1.36 clusters must enable the
PodCertificateRequest feature gate on kube-apiserver, kube-controller-manager,
and kubelet. The gate is
beta and defaults off in 1.36. Node tlshd reads the kubelet-rotated
certificateChainPath and keyPath files directly; no credential relay or
process reload signal is used.
The chart creates the deterministic TLS signing Namespace and annotates it with
helm.sh/resource-policy: keep. Helm uninstall therefore retains the Namespace
and its private CA authority. Operators must remove that Namespace only after
intentionally retiring the trust authority and every certificate that chains to
it; uninstalling the driver is not authority retirement.
| Key | Type | Default | Description |
|---|---|---|---|
network.portalHost |
string | "" |
Required only when an enabled workload uses an NVMe StorageClass, encryption, or nvmet. Host or IP the NVMe-TCP initiators connect to. A valid change refreshes owned volume status for future publish/stage operations; active attachments do not migrate. |
network.portalPort |
integer | 4420 |
NVMe-TCP portal port. |
network.nfsServer |
string | "" |
Required only when node.enabled and an NFS StorageClass are enabled. Host or IP the NFS clients mount from. A valid change refreshes owned volume status for future publish/stage operations; active mounts do not migrate. |
network.tls.enabled |
boolean | true |
Enables kernel RPC-with-TLS support. TLS requires both node.enabled=true and storage.enabled=true; the chart rejects TLS transport classes unless it is enabled. The node and storage workloads add privileged, host-network tlshd sidecars and use hostUsers: true. |
network.tls.signer.nodeSelector |
map | {kubernetes.io/arch: amd64} |
Node selector for the TLS signer StatefulSet. Additional keys merge with the amd64 default. |
network.tls.tlshd.loglevel |
integer | 0 |
tlshd configuration log level. Increase only for TLS transport troubleshooting. |
network.tls.tlshd.extraArgs |
string list | [] |
Additional arguments passed to each tlshd sidecar. Use only arguments supported by the host tlshd implementation. |
node.networkDomain |
string | workers |
Domain reported by every node-plugin pod through NodeGetInfo. Each node-plugin pod currently advertises one configured domain, which must be reachable from the selected owner. |
Storage Classes¶
Each of tankNVMe, tankNFS, flashNVMe, and flashNFS exposes the common
sub-keys below. fsType, blocksize, and mountOptions apply only to NVMe
block classes; nfsExportCIDRs applies to the filesystem classes. Because the
driver requires an explicit export CIDR, plaintext NFS classes are disabled by
default. TLS tank classes are enabled by default; enable only the transports
required by workloads in this release.
| Key | Type | Default | Description |
|---|---|---|---|
storageClasses.defaultClass |
string | "" |
Optionally selects exactly ONE chart StorageClass to carry storageclass.kubernetes.io/is-default-class: "true". Empty (the default) keeps the historical behaviour: no chart StorageClass becomes the cluster default and unrelated PVCs are unaffected. Rendering fails when the named key is unknown, disabled, or not rendered by this release. |
storageClasses.defaultClassVariant |
string | plain |
Which variant of defaultClass becomes the cluster default when encryption.enabled=true renders both: plain or encrypted. Ignored when defaultClass is empty. encrypted requires encryption.enabled=true. |
storageClasses.<class>.enabled |
boolean | false |
Whether the chart creates this StorageClass. tankNFSTLS and tankNVMeTLS default to true; plaintext and flash* classes default to false. |
storageClasses.<class>.name |
string | zfs-tank-nvme, zfs-tank-nfs, zfs-flash-nvme, zfs-flash-nfs, zfs-tank-nfs-tls, zfs-tank-nvme-tls |
StorageClass metadata name. |
storageClasses.<class>.pool |
string | tank for the tank classes, flash for the flash classes |
ZFS pool the class provisions into. |
storageClasses.<class>.reclaimPolicy |
string | Delete |
Reclaim policy of the StorageClass. |
storageClasses.<class>.fsType |
string | xfs |
Block filesystem passed through Kubernetes' reserved csi.storage.k8s.io/fstype parameter. Set ext4 for metadata-heavy small-file workloads. |
storageClasses.<class>.blocksize |
string | 16k |
Immutable ZFS volblocksize for new zvols. Use 16k for database-style I/O or 128k for sequential/VM workloads. |
storageClasses.<class>.mountOptions |
list | [] |
Additional Kubernetes StorageClass mount options for NVMe block filesystems. Do not use nobarrier; XFS must retain flush ordering. |
storageClasses.<class>.nfsExportCIDRs |
string list | [] |
Required IPv4/IPv6 CIDRs permitted to mount an enabled NFS StorageClass. The chart joins the list into the StorageClass string parameter. |
storageClasses.tankNFSTLS |
map | {enabled: true, name: zfs-tank-nfs-tls, pool: tank, nfsExportCIDRs: [127.0.0.1/32], reclaimPolicy: Delete} |
TLS-protected NFS class for the tank pool. Replace the loopback-only default export CIDR with consumer-node CIDRs before use. Requires network.tls.enabled=true. |
storageClasses.tankNVMeTLS |
map | {enabled: true, name: zfs-tank-nvme-tls, pool: tank, fsType: xfs, blocksize: 16k, mountOptions: [], reclaimPolicy: Delete} |
TLS-protected NVMe-TCP class for the tank pool. Requires network.tls.enabled=true. |
Throughput And Control Plane¶
| Key | Default | Description |
|---|---|---|
controller.nodeSelector |
{kubernetes.io/arch: amd64} |
Node selector for multi-owner controller pods. Additional keys merge with the amd64 default. |
controller.metricsBindAddress / controller.healthProbeBindAddress |
:8080 / :8082 |
Controller metrics and health listener addresses. |
controller.manager.syncPeriod |
10m |
Informer full-resync interval. Increasing it reduces periodic reconcile load but lengthens drift repair. |
controller.sidecars.* |
upstream defaults | Worker, Kubernetes API QPS/burst, and RPC timeout settings for provisioner, attacher, resizer, and snapshotter. Tune after API/server measurements. |
storage.metricsBindAddress / storage.healthProbeBindAddress |
:8080 / :8082 |
Storage agent metrics and health listener addresses. |
storage.manager.maxConcurrentReconciles / syncPeriod |
10 / 10m |
Bounds storage-agent parallel work and controls periodic drift reconciliation. |
storage.enableVolumeImports |
false |
Enables storage-administrator VolumeImport validation and materialisation. Enable only after retain-aware storage agents run on every storage node. |
node.maxVolumesPerNode |
128 |
Scheduler-facing maximum attachable volumes; set 0 to omit a limit. |
node.nodeSelector |
{kubernetes.io/arch: amd64} |
Node selector for node-plugin pods. Additional keys merge with the amd64 default. |
node.nvme.ctrlLossTMO / reconnectDelay |
-1 / 10 seconds |
NVMe-oF reconnect policy. Keep ctrlLossTMO=-1; finite values break reboot recovery. |
CSI Service Account Tokens¶
These values opt the CSIDriver into KEP-5538 service-account-token delivery in
NodePublishVolumeRequest.secrets. Core zfs-csi does not consume these tokens or
use them for authorization. Enable this only when a downstream node-publish
policy integration consumes the token; otherwise it creates sensitive tokens
and token-refresh churn without any benefit. This opt-in requires Kubernetes
1.35 or newer. Kubernetes 1.35 requires the CSIServiceAccountTokenSecrets
feature gate on the kube-apiserver and kubelet; the feature is locked on in
Kubernetes 1.36.
| Key | Type | Default | Description |
|---|---|---|---|
serviceAccountToken.enabled |
boolean | false |
Render spec.tokenRequests and spec.serviceAccountTokenInSecrets: true. Disabled by default, so the chart requests no workload tokens. |
serviceAccountToken.audience |
string | "" |
Token audience. Must be non-empty when enabled and must identify the downstream policy integration that validates the token. |
serviceAccountToken.expirationSeconds |
integer | 3600 |
Requested token lifetime. Kubernetes requires at least 600 seconds. |
serviceAccountToken.requiresRepublish |
boolean | false |
Set CSIDriver.spec.requiresRepublish. Enable only if the integration needs refreshed tokens through repeated NodePublishVolume calls; this adds kubelet and driver churn. |
Encryption¶
OpenBao Transit-backed ZFS native encryption. When enabled, the controller and storage
agent authenticate to OpenBao, generate a per-volume data-encryption key via Transit, and
create datasets with encryption=on. Enabling encryption also causes the chart to render
the zfs-tank-nvme-encrypted StorageClass.
| Key | Type | Default | Description |
|---|---|---|---|
encryption.enabled |
boolean | false |
Enable per-volume ZFS native encryption. |
encryption.openbao.addr |
string | http://openbao.openbao.svc:8200 |
OpenBao API address. |
encryption.openbao.transitMount |
string | transit |
OpenBao Transit mount path. |
encryption.openbao.role |
string | zfs-csi-storage |
OpenBao Kubernetes auth role the driver authenticates as. |
encryption.openbao.token |
string | "" |
Static OpenBao token for dev mode. Leave empty to use Kubernetes auth (the recommended path). |
Minimal Values Example¶
A minimal values file sets the image repository, the storage node name and address, and
enables the required tank StorageClasses explicitly. No StorageClass becomes the
Kubernetes default.
image:
repository: registry.example.com/zfs-csi/zfs-csi
tag: "v0.1.0"
storageNode:
name: storage-node-1
# Replace with `zpool get -H -o value guid tank` output.
authoritativePoolGUIDs:
- "12345678901234567890"
networkDomain: workers
poolMountRoot: /tank
network:
# Example RFC1918 address; replace with the storage node's reachable address.
portalHost: 10.42.0.7
nfsServer: 10.42.0.7
storageClasses:
tankNVMe:
enabled: true
tankNFS:
enabled: true
nfsExportCIDRs:
- 10.42.0.0/16
- 2001:db8:42::/64
See Also¶
- Install zfs-csi with Helm (how-to)
- StorageClass Reference (reference)
- Enable Per-Volume Encryption (how-to)
- Import an Existing ZFS Volume (how-to)
- VolumeImport Reference (reference)
- Multi-Storage-Agent Topology and Placement (explanation)
Last Updated: July 2026 Chart Version: 0.1.0