Helm Chart Reference¶
This page describes what the meshstor-csi Helm chart deploys and how it integrates with your cluster's policies. Pair it with the auto-generated charts/meshstor-csi/README.md, which lists every value key.
Chart Coordinates¶
| Field | Value |
|---|---|
| Name | meshstor-csi |
| Source | oci://ghcr.io/meshstor/charts/meshstor-csi |
| Repository | https://github.com/meshstor/meshstor-csi (chart at charts/meshstor-csi/) |
| Minimum Kubernetes | 1.27.0 |
appVersion |
Pins the default image tag — when image.tag is empty, the chart's appVersion is used. |
OCI installs require Helm 3.8.0 or newer. See Installation for the install/upgrade commands.
What the Chart Installs¶
flowchart TB
subgraph cluster[Cluster-scoped]
direction LR
CRDs[2 × CustomResourceDefinition<br/>meshstorvolumes · meshstornodedevices]
CSI[CSIDriver<br/>io.meshstor.csi.mesh]
SC[2 × StorageClass<br/>meshstor-replicated · meshstor-local-storage]
CR[2 × ClusterRole + ClusterRoleBinding<br/>controller · node]
end
subgraph ns[Release namespace]
direction LR
SS[StatefulSet · controller<br/>1 replica · 4 containers]
DS[DaemonSet · node<br/>1 per Linux node · 3 containers]
SA[2 × ServiceAccount]
Role[Role + RoleBinding<br/>csi-resizer leader-election lease]
end
A default install (crds.enabled=true, rbac.create=true, serviceAccount.*.create=true, default storageClasses) creates:
| Kind | Name(s) | Notes |
|---|---|---|
CustomResourceDefinition |
meshstorvolumes.csi.meshstor.io, meshstornodedevices.csi.meshstor.io |
Annotated helm.sh/resource-policy: keep when crds.keep=true (default) — see CRD Management. |
CSIDriver |
io.meshstor.csi.mesh |
attachRequired: false, podInfoOnMount: false. |
StatefulSet |
<release>-controller |
1 replica, system-cluster-critical. csi-provisioner has no leader election in the driver pipeline, so the StatefulSet is hardcoded to one replica. |
DaemonSet |
<release>-node |
Every Linux node, system-node-critical, hostNetwork: true. |
ServiceAccount |
<release>-controller, <release>-node |
Split per role so IRSA / Workload Identity can be attached to one. |
ClusterRole + ClusterRoleBinding |
<release>-controller, <release>-node |
Cluster-scoped CR access, PV/PVC, events, storage classes — see RBAC. |
Role + RoleBinding |
<release>-controller (release namespace) |
coordination.k8s.io/leases for csi-resizer leader election. |
StorageClass |
meshstor-replicated (default), meshstor-local-storage |
Configurable via storageClasses — see Default StorageClasses. |
(templated extraObjects) |
user-supplied | Each entry is rendered through tpl against the release context. |
Resource names are derived from the release name. Never run multiple instances side-by-side.
Cluster Integration¶
MeshStor's chart touches several cluster-wide policies.
RBAC¶
rbac.create=true (default) renders ClusterRoles for the controller and node, plus their bindings, plus a Role/RoleBinding pair in the release namespace for csi-resizer's leader-election lease. Set rbac.create=false if you manage RBAC out-of-band (sealed-secrets, vault, GitOps).
| Subject | Scope | Grants | Why |
|---|---|---|---|
<release>-controller ClusterRole |
cluster | MeshStor CRs, PV/PVC, events, storage classes, pods | csi-provisioner + controller reconciliation |
<release>-node ClusterRole |
cluster | MeshStor CRs (verbs from _generated-rules-node.tpl) |
node plugin reads/updates CRs during stage/publish |
<release>-controller Role |
release namespace | coordination.k8s.io/leases |
csi-resizer leader election |
Pod Security Admission¶
The controller pod fits PSA restricted. The node pod's csi-plugin container requires privileged and cannot be reduced — mdadm, nvme-cli, and mount(2) are not optional. If you label namespaces with PSA enforcement, the namespace hosting the DaemonSet must be enforce=privileged. Both pods set seccompProfile: RuntimeDefault, which the baseline policy requires for privileged pods.
| Pod | Container | Privilege | PSA fit |
|---|---|---|---|
| Controller (StatefulSet) | csi-plugin, sidecars | runAsNonRoot, readOnlyRootFilesystem, drop:[ALL] |
restricted |
| Node (DaemonSet) | csi-plugin | privileged: true |
privileged (required) |
| Node (DaemonSet) | sidecars | allowPrivilegeEscalation: false, readOnlyRootFilesystem, drop:[ALL] |
unprivileged inside privileged pod |
Host Requirements¶
The node pod takes a privileged container, real node IPs, and several host paths. None of these are reducible without losing functionality. If your cluster enforces host access via Kyverno, OPA, or admission webhooks, pre-clear these.
| Requirement | Why |
|---|---|
hostNetwork: true |
NVMe-oF target/host bind to node IPs (TCP and RDMA) |
privileged: true (csi-plugin) |
runs mdadm, nvme-cli, mount(2) |
Host path /dev |
create/delete/grow GPT partitions on nvme block devices |
Host path /sys/kernel/config |
NVMe-oF target configfs |
Host path /run/udev |
udev settle/notification |
Kubelet dir (default /var/lib/kubelet) |
mount propagation; override with node.kubeletDir for k0s, microk8s, talos |
| Plugin / registration subdirs | kubelet plugin registration socket |
| Mount propagation | Bidirectional on kubelet dir, HostToContainer on /sys/kernel/config — kubelet sees mount(2) results from inside the container |
The node pod runs a preStop that deletes its CSI socket so kubelet rebinds cleanly on restart.
CRD Management¶
| Value | Default | Effect |
|---|---|---|
crds.enabled |
true |
Chart renders the two CRDs into templates/crds/. Set to false to manage CRDs out-of-band (Argo CD pre-sync hook, kubectl apply, etc.). |
crds.keep |
true |
Adds helm.sh/resource-policy: keep to each CRD. helm uninstall leaves the CRDs in place, so existing MeshStorVolume and MeshStorNodeDevice resources survive a reinstall. |
Setting crds.keep=false is destructive
Without the keep annotation, helm uninstall deletes the CRDs, which cascades to delete every MeshStorVolume in the cluster — and that destroys the underlying data path state. Only use keep=false if you also keep your own out-of-band backups of the CRs and partitions.
Helm does not upgrade CRDs on helm upgrade — they are installed only on the first helm install. Releases that change CRD schema include reapply instructions in the release notes.
Default StorageClasses¶
The chart ships with two StorageClasses; storageClasses is a list, so you can add your own or set it to [] to skip creation entirely.
| Name | Default? | Replication | Use case |
|---|---|---|---|
meshstor-replicated |
yes | replicaCount: 2, stripeWidth: 1 (RAID1) |
General-purpose replicated block storage. |
meshstor-local-storage |
no | replicaCount: 1, stripeWidth: 1 (RAID1 with placeholder) |
Local-only with relocation support. See replicaCount=1 positioning. |
Both default to reclaimPolicy: Delete, allowVolumeExpansion: true, and memberMissingTimeout: "900". Per-StorageClass tunables are in StorageClass Parameters.
Two fields are intentionally not exposed per StorageClass:
volumeBindingModeis hardcoded toWaitForFirstConsumer. The driver doesn't consume CSI topology hints today, but binding deferral still avoids zombie PVs from PVCs that are never claimed.allowedTopologiespasses through to the rendered StorageClass but is not honored by the driver — placement is driven byinternal/nodeinfo's scoring algorithm, not by Kubernetes topology. Setting it does not constrain where MeshStor places replicas.
Container Images & Sidecars¶
The driver and four sidecars are configured separately under image.* and sidecars.* so a single sidecar bump is one focused PR.
| Component | Default registry | Default image |
|---|---|---|
| Manager (driver) | ghcr.io |
meshstor/meshstor-csi (tag falls back to chart appVersion) |
csi-provisioner |
registry.k8s.io |
sig-storage/csi-provisioner |
csi-resizer |
registry.k8s.io |
sig-storage/csi-resizer |
node-driver-registrar |
registry.k8s.io |
sig-storage/csi-node-driver-registrar |
livenessprobe |
registry.k8s.io |
sig-storage/livenessprobe |
pullPolicy defaults to IfNotPresent for every image. imagePullSecrets accepts a string, a list of names, or a list of {name: …} dicts; the chart references existing secrets — it does not create them from username/password.
Where to Tune¶
The full list of values lives in the auto-generated charts/meshstor-csi/README.md. Two cluster-level defaults worth surfacing here:
defaultRelocationReservePercent(default10) — per-node free-space reserve so a failed node's replicas can relocate to survivors. Set0cluster-wide, or override per node with themeshstor.io/relocation-reserve-percentlabel.node.kubeletDir— change from/var/lib/kubeletif your distro uses a different path (k0s, microk8s, talos).
Common production knobs (image pinning, resources, tolerations, custom StorageClasses, extraObjects) are documented per-key in the chart README.
What's Next¶
- Installation — install and upgrade commands
- StorageClass Parameters — tunables exposed through StorageClass
parameters - Compatibility — supported Kubernetes versions, kernel requirements, distributions
- Prerequisites — node-side setup the chart does not handle (udev rule, drive selection labels)