Installation¶
MeshStor ships as a Helm chart. The chart installs the CRDs, RBAC, the controller StatefulSet, the node DaemonSet, the CSIDriver object, and a pair of default StorageClasses.
Before you start: complete the Prerequisites checklist.
Already have MeshStor running? Jump straight to Create Your First Volume below.
Deploy¶
The chart is published to GitHub Container Registry as an OCI artifact. Install it directly — no helm repo add is needed:
helm install meshstor-csi oci://ghcr.io/meshstor/charts/meshstor-csi \
--namespace meshstor \
--create-namespace
To pin a specific chart version, pass --version:
helm install meshstor-csi oci://ghcr.io/meshstor/charts/meshstor-csi \
--version 0.1.0 \
--namespace meshstor --create-namespace
Available versions are listed at https://github.com/meshstor/meshstor-csi/pkgs/container/charts%2Fmeshstor-csi. OCI installs require Helm 3.8 or newer.
This creates:
| Resource | Name (default release) | Description |
|---|---|---|
| Namespace | meshstor |
Created by --create-namespace |
| CRDs | meshstorvolumes.csi.meshstor.io, meshstornodedevices.csi.meshstor.io |
Volume and device tracking. Chart defaults to crds.keep=true so helm uninstall will not delete them — see Uninstall below. |
| CSIDriver | io.meshstor.csi.mesh |
Registers MeshStor with the kubelet |
| ServiceAccounts | meshstor-csi-controller, meshstor-csi-node |
Identity for controller and node pods |
| ClusterRoles / Bindings | meshstor-csi-controller, meshstor-csi-node |
Permissions for CRs, nodes, PVCs, events |
| StatefulSet | meshstor-csi-controller |
Controller (1 replica) |
| DaemonSet | meshstor-csi-node |
Node plugin (every Linux node) |
| StorageClasses | meshstor-replicated (default), meshstor-local-storage |
Preconfigured — see StorageClass Examples for the full set |
Resource names are derived from the release name (meshstor-csi above). Use --set fullnameOverride= or a different release name to run multiple instances side by side.
Customising the install¶
An operational walkthrough of what the chart deploys and the values most often tuned in production lives in the Helm Chart Reference. The full per-key value table is auto-generated in charts/meshstor-csi/README.md. The most common overrides:
# Pin a specific image tag
helm install meshstor-csi oci://ghcr.io/meshstor/charts/meshstor-csi \
--namespace meshstor --create-namespace \
--set image.tag=v0.1.0
# Skip the bundled StorageClasses (install your own separately)
helm install meshstor-csi oci://ghcr.io/meshstor/charts/meshstor-csi \
--namespace meshstor --create-namespace \
--set storageClasses=null
# Let GitOps manage CRDs
helm install meshstor-csi oci://ghcr.io/meshstor/charts/meshstor-csi \
--namespace meshstor --create-namespace \
--set crds.enabled=false
A custom values.yaml is usually cleaner than many --set flags:
helm install meshstor-csi oci://ghcr.io/meshstor/charts/meshstor-csi \
--namespace meshstor --create-namespace \
-f my-values.yaml
Verify the Deployment¶
It is critical for self-healing capability.
Disable udev MD auto-assembly on each node. (see Prerequisites)
sudo tee /etc/udev/rules.d/10-mdadm-no-udev-assemble.rules > /dev/null <<'EOF'
SUBSYSTEM!="block", GOTO="md_no_udev_end"
ACTION=="remove", GOTO="md_no_udev_end"
ENV{ID_FS_TYPE}=="", IMPORT{builtin}="blkid"
ENV{ID_FS_TYPE}=="linux_raid_member", ENV{ANACONDA}="1"
LABEL="md_no_udev_end"
EOF
sudo udevadm control --reload-rules
sudo udevadm trigger
Check that all pods are running:
NAME READY STATUS RESTARTS AGE
meshstor-csi-controller-0 4/4 Running 0 30s
meshstor-csi-node-abc12 3/3 Running 0 30s
meshstor-csi-node-def34 3/3 Running 0 30s
Confirm the default StorageClasses exist:
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
meshstor-replicated (default) io.meshstor.csi.mesh Delete Immediate true 30s
meshstor-local-storage io.meshstor.csi.mesh Delete Immediate true 30s
Verify device discovery (each node reports its NVMe drives):
NAME MODEL SERIAL LOCALPARTITIONS REMOTEPARTITIONS UNKNOWNPARTITIONS MULTIQUEUE BIGGESTUSABLEFREESPACE SIZE SECTORSIZE UPDATEDAT
node1-nvme0n1 WD_BLACK SN7100 1TB 244... 0 0 0 20 931.5Gi 931.5Gi 4096 5s
node2-nvme1n1 WD_BLACK SN7100 500GB 260... 0 0 0 16 465.8Gi 465.8Gi 512 5s
No devices listed
If kubectl get msnd returns no resources, check that:
- NVMe drives are present on the nodes (
lsblk -d | grep nvme) - The node pods are running and not crash-looping (
kubectl -n meshstor logs daemonset/meshstor-csi-node -c csi-plugin) - Drive selection labels are set on each node (see Prerequisites) — without the label, no drives are registered for that node
Create Your First Volume¶
The chart preinstalls meshstor-replicated as the default StorageClass, so a PVC with no storageClassName set will land on it. Create a PVC and a pod that writes to it.
1. PersistentVolumeClaim¶
kubectl apply -f - <<'EOF'
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: my-first-volume
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
storageClassName: meshstor-replicated
volumeMode: Filesystem
EOF
2. Workload¶
kubectl apply -f - <<'EOF'
apiVersion: v1
kind: Pod
metadata:
name: writer
spec:
containers:
- name: writer
image: busybox
command: ["sh", "-c", "while true; do date >> /data/log.txt; sleep 5; done"]
volumeMounts:
- name: data
mountPath: /data
volumes:
- name: data
persistentVolumeClaim:
claimName: my-first-volume
EOF
3. Verify the Volume¶
Check that the PVC is bound:
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
my-first-volume Bound pvc-cd1038a7-... 1Gi RWO meshstor-replicated 30s
Check the volume status — it should reach Synced with READY showing 2/2:
The NODE column is the consumer node — the one whose pod has the PVC mounted. Run kubectl get msvol <volume-name> -o jsonpath='{.status.partitions[*].nodeID}' to see all nodes hosting the partitions.
Check the partitions are on different nodes:
kubectl get msvol pvc-cd1038a7-... -o jsonpath='{range .status.partitions[*]}{.nodeID} {.state}{"\n"}{end}'
Verify the workload is writing data:
Clean Up the Test Volume¶
Upgrade MeshStor¶
Pin to a specific release with --version <x.y.z>; omit it to pick up the latest published chart.
CRDs bundled via crds.enabled=true are installed on first helm install only — Helm does not upgrade them on helm upgrade. If a release includes a CRD schema change, the release notes will say so and explain how to reapply the updated CRDs.
Uninstall MeshStor¶
helm uninstall removes the workloads, RBAC, CSIDriver, and StorageClasses but keeps the CRDs by default (crds.keep=true). Existing MeshStorVolume and MeshStorNodeDevice resources are preserved so you can reinstall without losing state.
Deleting CRDs is destructive
Removing the CRDs cascades to delete every MeshStorVolume in the cluster, which destroys the underlying data path state. Only do this after you have deleted all PVCs backed by MeshStor and confirmed the data is no longer needed.
To remove the CRDs anyway:
Alternatively, pass --set crds.keep=false when installing — but note this removes the safety net on every subsequent uninstall.
What's Next¶
- StorageClass Examples — configurations for different workloads
- Replication — understand RAID levels and fault tolerance
- Monitoring — track volume health in production