Helm values
Every Helm value in the pillar-csi chart with its type, default and description, generated from values.yaml. Use it to configure backends, mTLS and nodes.
On this page
This page covers chart version 0.3.3. Pass overrides with -f my-values.yaml or --set key=value when you run helm install or helm upgrade. Each value has its own heading, so you can link to it, for example agent.backends.
agent.backends has no default entries, and the agent exits with an error when it has no backend. Every install must set it.
agent
agent.annotations
Type: object. Default: {}
Annotations added to the agent DaemonSet.
agent.backends
Type: list. Default: []
Backend placement config for the pillar-agent. The list is rendered verbatim into the backends: list of the agent config file (ConfigMap <fullname>-agent-config, passed to the agent via --config). Each entry sets exactly one of zfs or lvm, with the same keys as the placement fields of PillarStore.spec.backend: - zfs: pool is required; volumeType (only zvol, the default) and parentDataset are optional. properties is refused: ZFS properties are per-volume settings of the PillarStore, PillarStorageClass overrides or PVC backend document. - lvm: volumeGroup is required; thinPool (thin pool LV used by thin volumes) and provisioningMode (linear default | thin; the mode for agent requests that name none — CSI always names the resolved mode) are optional. The agent rejects unknown keys with their path and exits with an error when no backend is configured. An entry setting neither or both of zfs/lvm fails the chart render. Each ZFS pool and LVM volumeGroup may appear in at most one entry (a ZFS pool and an LVM VG must not share a name either): volumes are routed to a backend by pool/VG name alone, so a duplicate fails the chart render and the agent refuses to start when given one. parentDataset and thinPool decide where volumes are created and must equal the PillarStore’s spec.backend.zfs.parentDataset / spec.backend.lvm.thinPool for that pool/VG (omitted = pool root / no thin pool). On a mismatch the PillarStore is not Ready (PoolDiscovered=False, BackendLayoutMismatch) and CreateVolume fails; volumes are never placed elsewhere. Example: backends: - zfs: pool: tank - zfs: volumeType: zvol pool: hot-data parentDataset: k8s - lvm: volumeGroup: data-vg thinPool: thin0 provisioningMode: linear
agent.extraArgs
Type: list. Default: []
Extra command-line arguments appended to the pillar-agent entrypoint.
agent.extraEnv
Type: list. Default: []
Additional environment variables injected into the agent container.
agent.grpcPort
Type: int. Default: 9500
gRPC listen port inside the container (also exposed as hostPort).
agent.hostNetwork
Type: bool. Default: true
Run the agent Pod in the host network namespace. Required for the NVMe-oF data plane (see PRD §2.4). Set to false only for isolated gRPC-only deployments where no kernel target is exported (e.g. unit-test harnesses); production NVMe-oF exports will fail with “connection refused” at NodeStageVolume when this is false.
agent.hostPort
Type: int. Default: 9500
hostPort number bound on the node IP for agent gRPC access. Must match grpcPort. Set to 0 to disable hostPort (not recommended).
agent.image.pullPolicy
Type: string. Default: ""
Per-container image pull policy override.
agent.image.repository
Type: string. Default: "ghcr.io/isac322/pillar-csi/agent"
Container image repository for the pillar-agent binary.
agent.image.tag
Type: string. Default: ""
Image tag. Defaults to the chart’s appVersion when empty.
agent.initModprobe.image.pullPolicy
Type: string. Default: ""
agent.initModprobe.image.repository
Type: string. Default: "busybox"
Image used for the modprobe init container (needs kmod/modprobe binary).
agent.initModprobe.image.tag
Type: string. Default: "1.38.0"
Init container image tag.
agent.initModprobe.modules
Type: list. Default: ["nvmet","nvmet_tcp"]
Kernel modules to load. Failures are silently ignored (best-effort). nvmet must be listed before nvmet_tcp (it is a dependency).
agent.initModprobe.resources
Type: object. Default:
{
"limits": {
"cpu": "50m",
"memory": "32Mi"
},
"requests": {
"cpu": "5m",
"memory": "16Mi"
}
}Resource requests/limits for the modprobe init container.
agent.nodeSelector
Type: object. Default:
{
"pillar-csi.bhyoo.com/agent-node": "true"
}Node selector applied to agent DaemonSet Pods. The controller automatically adds pillar-csi.bhyoo.com/agent-node=true to nodes referenced by PillarAgent CRs; this selector ensures the agent runs only on those nodes.
agent.podAnnotations
Type: object. Default: {}
Annotations added to the agent Pod template.
agent.podLabels
Type: object. Default: {}
Labels added to the agent Pod template.
agent.privileged
Type: bool. Default: true
Run the agent container in privileged mode (default: true). The storage backends open host device nodes directly: LVM needs /dev/mapper/control and every PV block device (and dm-N nodes created at runtime by lvcreate); ZFS needs /dev/zfs. For a non-privileged container the container runtime installs the default OCI device cgroup allowlist (on cgroup v2 an eBPF device filter), which rejects open() on these nodes with EPERM even for runAsUser=0 + CAP_SYS_ADMIN and a hostPath /dev mount — capabilities cannot bypass the device cgroup. The agent then cannot query pool capacity, reports degraded health and no discovered pools, and PillarStores never become Ready. This applies to bare-metal nodes as well as Kind/nested setups. Set to false only when the deployment authorizes those host devices for the agent container by other means (e.g. runtime device-cgroup configuration or a device plugin/CDI covering every required device).
agent.resources
Type: object. Default:
{
"limits": {
"cpu": "500m",
"memory": "256Mi"
},
"requests": {
"cpu": "10m",
"memory": "64Mi"
}
}Resource requests/limits for the pillar-agent container.
agent.tolerations
Type: list. Default: []
Tolerations applied to agent DaemonSet Pods.
controller
controller.affinity
Type: object. Default: {}
Affinity rules for the controller Pod.
controller.annotations
Type: object. Default: {}
Annotations added to the controller Deployment.
controller.csiSocketPath
Type: string. Default: "/csi/csi.sock"
CSI Unix socket path on the shared emptyDir volume.
controller.extraArgs
Type: list. Default: []
Extra command-line arguments appended to the manager entrypoint.
controller.extraEnv
Type: list. Default: []
Additional environment variables injected into the manager container.
controller.healthProbePort
Type: int. Default: 8081
HTTP port exposed by the manager health-probe endpoint.
controller.image.pullPolicy
Type: string. Default: ""
Per-container image pull policy override.
controller.image.repository
Type: string. Default: "ghcr.io/isac322/pillar-csi/controller"
Container image repository for the controller (manager) binary.
controller.image.tag
Type: string. Default: ""
Image tag. Defaults to the chart’s appVersion when empty.
controller.livenessPort
Type: int. Default: 9809
HTTP port exposed by the liveness-probe sidecar for CSI socket health checks.
controller.metricsPort
Type: int. Default: 8080
Metrics port exposed by the manager.
controller.nodeSelector
Type: object. Default: {}
Node selector applied to the controller Pod.
controller.podAnnotations
Type: object. Default: {}
Annotations added to the controller Pod template.
controller.podLabels
Type: object. Default: {}
Labels added to the controller Pod template.
controller.replicaCount
Type: int. Default: 1
Number of controller replicas. >1 is safe: every replica serves the pod-local CSI socket so its sidecars stay healthy, while the manager and the CSI sidecars hold independent leader-election leases. Pair with controller.affinity podAntiAffinity so replicas land on different nodes.
controller.resources
Type: object. Default:
{
"limits": {
"cpu": "500m",
"memory": "128Mi"
},
"requests": {
"cpu": "10m",
"memory": "64Mi"
}
}Resource requests/limits for the manager container.
controller.sidecars.attacher.extraArgs
Type: list. Default: []
Extra arguments for csi-attacher.
controller.sidecars.attacher.image.pullPolicy
Type: string. Default: ""
controller.sidecars.attacher.image.repository
Type: string. Default: "registry.k8s.io/sig-storage/csi-attacher"
csi-attacher image repository.
controller.sidecars.attacher.image.tag
Type: string. Default: "v4.12.0"
csi-attacher image tag.
controller.sidecars.attacher.resources
Type: object. Default:
{
"limits": {
"cpu": "100m",
"memory": "64Mi"
},
"requests": {
"cpu": "10m",
"memory": "32Mi"
}
}Resource requests/limits for the attacher sidecar.
controller.sidecars.livenessProbe.image.pullPolicy
Type: string. Default: ""
controller.sidecars.livenessProbe.image.repository
Type: string. Default: "registry.k8s.io/sig-storage/livenessprobe"
livenessprobe image repository.
controller.sidecars.livenessProbe.image.tag
Type: string. Default: "v2.19.0"
livenessprobe image tag (shared with node liveness sidecar).
controller.sidecars.livenessProbe.resources
Type: object. Default:
{
"limits": {
"cpu": "50m",
"memory": "32Mi"
},
"requests": {
"cpu": "5m",
"memory": "16Mi"
}
}Resource requests/limits for the liveness-probe sidecar.
controller.sidecars.provisioner.extraArgs
Type: list. Default: []
Extra arguments for csi-provisioner. --extra-create-metadata is always passed: CreateVolume reads the PVC override annotations through it.
controller.sidecars.provisioner.image.pullPolicy
Type: string. Default: ""
controller.sidecars.provisioner.image.repository
Type: string. Default: "registry.k8s.io/sig-storage/csi-provisioner"
csi-provisioner image repository.
controller.sidecars.provisioner.image.tag
Type: string. Default: "v6.3.0"
csi-provisioner image tag.
controller.sidecars.provisioner.resources
Type: object. Default:
{
"limits": {
"cpu": "100m",
"memory": "64Mi"
},
"requests": {
"cpu": "10m",
"memory": "32Mi"
}
}Resource requests/limits for the provisioner sidecar.
controller.sidecars.resizer.extraArgs
Type: list. Default: []
Extra arguments for csi-resizer.
controller.sidecars.resizer.image.pullPolicy
Type: string. Default: ""
controller.sidecars.resizer.image.repository
Type: string. Default: "registry.k8s.io/sig-storage/csi-resizer"
csi-resizer image repository.
controller.sidecars.resizer.image.tag
Type: string. Default: "v2.2.1"
csi-resizer image tag.
controller.sidecars.resizer.resources
Type: object. Default:
{
"limits": {
"cpu": "100m",
"memory": "64Mi"
},
"requests": {
"cpu": "10m",
"memory": "32Mi"
}
}Resource requests/limits for the resizer sidecar.
controller.tolerations
Type: list. Default: []
Tolerations applied to the controller Pod.
csiDriver
csiDriver.attachRequired
Type: bool. Default: true
Indicates this CSI driver requires an attach operation (ControllerPublishVolume).
csiDriver.create
Type: bool. Default: true
Set to false to skip CSIDriver object creation.
csiDriver.fsGroupPolicy
Type: string. Default: "File"
fsGroupPolicy for the CSIDriver. Valid values: None, File, ReadWriteOnceWithFSType.
csiDriver.podInfoOnMount
Type: bool. Default: true
Inject Pod info (name/namespace/UID) as volume attributes on mount.
csiDriver.volumeLifecycleModes
Type: list. Default: ["Persistent"]
volumeLifecycleModes supported by the driver.
fullnameOverride
fullnameOverride
Type: string. Default: ""
Full name override for resource naming.
imagePullPolicy
imagePullPolicy
Type: string. Default: "IfNotPresent"
Global image pull policy applied to all containers unless overridden per component.
imagePullSecrets
imagePullSecrets
Type: list. Default: []
Optional list of imagePullSecrets applied to all Pods.
installCRDs
installCRDs
Type: bool. Default: true
Install CRDs as part of the Helm release. Set to false when managing CRDs separately (e.g. via GitOps or a dedicated CRD chart). CRDs are annotated with helm.sh/resource-policy: keep so they are never deleted on chart uninstall.
metrics
metrics.serviceMonitor
Type: object. Default:
{
"additionalLabels": {},
"enabled": false,
"interval": ""
}Set to true to create a Prometheus ServiceMonitor (requires prometheus-operator CRDs).
metrics.serviceMonitor.additionalLabels
Type: object. Default: {}
Additional labels added to the ServiceMonitor.
metrics.serviceMonitor.interval
Type: string. Default: ""
Scrape interval override. Defaults to the Prometheus global scrapeInterval.
mtls
mtls.certDir
Type: string. Default: "/etc/pillar-csi/mtls"
Path inside controller and agent containers where the cert Secret is mounted. Templates expose this via the pillar-csi.mtls.certDir helper.
mtls.certManager.duration
Type: string. Default: "2160h"
Certificate lifetime; cert-manager renews “renewBefore” the expiry.
mtls.certManager.enabled
Type: bool. Default: false
If true the chart renders a cert-manager Issuer plus two Certificate resources that produce Secrets named “<fullname>-controller-mtls” and “<fullname>-agent-mtls”. Requires cert-manager CRDs in the cluster.
mtls.certManager.issuerRef
Type: object. Default:
{
"group": "cert-manager.io",
"kind": "Issuer",
"name": ""
}Override the IssuerRef. When name is empty the chart creates a self-signed Issuer in the release namespace.
mtls.certManager.renewBefore
Type: string. Default: "360h"
mtls.enabled
Type: bool. Default: false
Enable mTLS for controller ↔ agent gRPC traffic. When false the controller dials the agent with plaintext credentials.
mtls.secretRefs
Type: object. Default:
{
"agent": {
"secretName": "pillar-agent-mtls"
},
"controller": {
"secretName": "pillar-controller-mtls"
}
}When certManager.enabled is false the chart mounts pre-existing Secrets. The operator MUST create these Secrets in the release namespace with keys tls.crt, tls.key, ca.crt before installing.
mtls.serverName
Type: string. Default: ""
Override the TLS server name the controller uses when verifying the agent’s certificate (SNI / SAN match). Required when the agent certificate is issued against a DNS name (cert-manager auto-issuance always does so) instead of the per-node IP the controller dials. Leave empty to let cert-manager mode auto-derive it as “<fullname>-agent.<namespace>.svc”; the operator must set it when providing custom Secrets whose agent cert SAN differs from the node IP.
nameOverride
nameOverride
Type: string. Default: ""
Name override (replaces the chart name portion of generated names).
namespaceOverride
namespaceOverride
Type: string. Default: ""
Namespace override. Defaults to the Helm release namespace.
node
node.annotations
Type: object. Default: {}
Annotations added to the node DaemonSet.
node.csiSocketPath
Type: string. Default: "/var/lib/kubelet/plugins/pillar-csi.bhyoo.com/csi.sock"
CSI Unix socket path on the node host.
node.extraArgs
Type: list. Default: []
Extra command-line arguments appended to the pillar-node entrypoint.
node.extraEnv
Type: list. Default: []
Additional environment variables injected into the node container.
node.hostNetwork
Type: bool. Default: true
Run the node Pod in the host network namespace. Required because nvme connect writes to /dev/nvme-fabrics issue TCP SYNs from the caller’s netns; with hostNetwork: false the SYNs originate in the pod netns and cannot reach the host-network nvmet listener exposed by the agent. See PRD §2.4 for the kernel netns rationale.
node.image.pullPolicy
Type: string. Default: ""
Per-container image pull policy override.
node.image.repository
Type: string. Default: "ghcr.io/isac322/pillar-csi/node"
Container image repository for the pillar-node binary.
node.image.tag
Type: string. Default: ""
Image tag. Defaults to the chart’s appVersion when empty.
node.initModprobe.image.pullPolicy
Type: string. Default: ""
node.initModprobe.image.repository
Type: string. Default: "busybox"
Image used for the modprobe init container (needs kmod/modprobe binary).
node.initModprobe.image.tag
Type: string. Default: "1.38.0"
Init container image tag.
node.initModprobe.modules
Type: list. Default: ["nvme_fabrics","nvme_tcp"]
Kernel modules to load. Failures are silently ignored (best-effort). nvme_fabrics must be listed before nvme_tcp (it is a dependency).
node.initModprobe.resources
Type: object. Default:
{
"limits": {
"cpu": "50m",
"memory": "32Mi"
},
"requests": {
"cpu": "5m",
"memory": "16Mi"
}
}Resource requests/limits for the modprobe init container.
node.kubeletPluginRegistrationDir
Type: string. Default: "/var/lib/kubelet/plugins_registry"
Host path for the kubelet plugin registration socket directory.
node.kubeletPluginsDir
Type: string. Default: "/var/lib/kubelet/plugins"
Host path for the kubelet plugin registration directory.
node.livenessPort
Type: int. Default: 9808
Liveness probe HTTP port exposed by the node liveness sidecar (hostPort NOT used).
node.nodeSelector
Type: object. Default: {}
Node selector applied to node DaemonSet Pods. By default runs on all worker nodes.
node.podAnnotations
Type: object. Default: {}
Annotations added to the node Pod template.
node.podLabels
Type: object. Default: {}
Labels added to the node Pod template.
node.resources
Type: object. Default:
{
"limits": {
"cpu": "500m",
"memory": "256Mi"
},
"requests": {
"cpu": "10m",
"memory": "64Mi"
}
}Resource requests/limits for the pillar-node container.
node.sidecars.livenessProbe.image.pullPolicy
Type: string. Default: ""
node.sidecars.livenessProbe.image.repository
Type: string. Default: "registry.k8s.io/sig-storage/livenessprobe"
livenessprobe image repository (can differ from controller’s).
node.sidecars.livenessProbe.image.tag
Type: string. Default: "v2.19.0"
livenessprobe image tag.
node.sidecars.livenessProbe.resources
Type: object. Default:
{
"limits": {
"cpu": "50m",
"memory": "32Mi"
},
"requests": {
"cpu": "5m",
"memory": "16Mi"
}
}Resource requests/limits for the liveness-probe sidecar.
node.sidecars.nodeDriverRegistrar.extraArgs
Type: list. Default: []
Extra arguments for csi-node-driver-registrar.
node.sidecars.nodeDriverRegistrar.image.pullPolicy
Type: string. Default: ""
node.sidecars.nodeDriverRegistrar.image.repository
Type: string. Default: "registry.k8s.io/sig-storage/csi-node-driver-registrar"
csi-node-driver-registrar image repository.
node.sidecars.nodeDriverRegistrar.image.tag
Type: string. Default: "v2.17.0"
csi-node-driver-registrar image tag.
node.sidecars.nodeDriverRegistrar.resources
Type: object. Default:
{
"limits": {
"cpu": "100m",
"memory": "64Mi"
},
"requests": {
"cpu": "10m",
"memory": "32Mi"
}
}Resource requests/limits for the node-driver-registrar sidecar.
node.tolerations
Type: list. Default: []
Tolerations applied to node DaemonSet Pods.
rbac
rbac.create
Type: bool. Default: true
Set to false to skip ClusterRole/ClusterRoleBinding creation.
serviceAccount
serviceAccount.agent.annotations
Type: object. Default: {}
Annotations added to the agent ServiceAccount.
serviceAccount.agent.create
Type: bool. Default: true
Set to false to skip ServiceAccount creation for pillar-agent.
serviceAccount.agent.name
Type: string. Default: ""
Override the ServiceAccount name. Defaults to <fullname>-agent.
serviceAccount.controller.annotations
Type: object. Default: {}
Annotations added to the controller ServiceAccount (e.g. for IRSA/Workload Identity).
serviceAccount.controller.create
Type: bool. Default: true
Set to false to skip ServiceAccount creation for the controller.
serviceAccount.controller.name
Type: string. Default: ""
Override the ServiceAccount name. Defaults to <fullname>-controller.
serviceAccount.node.annotations
Type: object. Default: {}
Annotations added to the node ServiceAccount.
serviceAccount.node.create
Type: bool. Default: true
Set to false to skip ServiceAccount creation for pillar-node.
serviceAccount.node.name
Type: string. Default: ""
Override the ServiceAccount name. Defaults to <fullname>-node.
webhook
webhook.certDir
Type: string. Default: "/tmp/k8s-webhook-server/serving-certs"
Directory where the generated serving certificate is mounted.
webhook.enabled
Type: bool. Default: true
Enable admission validation and defaulting webhooks.
webhook.port
Type: int. Default: 9443
HTTPS port served by controller-runtime inside the controller Pod.