Install the K8s CSI driver
From nothing to a mounted volume: install the CSI driver against a running storage cluster, provision a PVC, mount it in a pod.
This is the Kubernetes half, and it assumes the storage cluster already exists. If it does not, start at Install the storage cluster — that page ends with the four values the Helm install below needs.
Prerequisites
- A storage cluster reachable from the Kubernetes nodes, with the
management API exposed (default port
8082) and API credentials to hand — see Install the storage cluster. - Kubernetes 1.20+ with the CSI feature set enabled.
- Helm 3.
Step 1 (Optional) — Install the snapshot CRDs
Skip this if the cluster already has them.
kubectl apply -f https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/v8.2.0/client/config/crd/snapshot.storage.k8s.io_volumesnapshotclasses.yaml kubectl apply -f https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/v8.2.0/client/config/crd/snapshot.storage.k8s.io_volumesnapshotcontents.yaml kubectl apply -f https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/v8.2.0/client/config/crd/snapshot.storage.k8s.io_volumesnapshots.yaml
If the cluster has no snapshot controller of its own, let the chart deploy one
with --set externalSnapshotter.enabled=true below. A single snapshot
controller serves every CSI driver in a cluster, so do not add a second.
Step 2 — Install the driver
Two things go into this command: the cluster connection from Install the storage cluster, and the StorageClass parameters Sizing the pool printed — the cache ratios, the ceilings and the QoS caps, worked out from the volumes the pool has to serve.
helm install mgx-csi-driver oci://docker.io/migrx/mgx-csi-driver \
--namespace mgx-system --create-namespace \
--version 0.1.0 \
--set csiSecret.clusterConfig.nodes='{172.31.96.14:8082,172.31.96.15:8082,172.31.96.16:8082}' \
--set csiSecret.clusterConfig.username=admin \
--set csiSecret.clusterConfig.password=secret \
--set storageclass.ratioCacheRCacheSize=0.1 \
--set storageclass.ratioCacheRWCacheSize=0.05 \
--set storageclass.maxCacheRCacheSize=476837 \
--set storageclass.maxCacheRWCacheSize=238419 \
--set storageclass.qosRWIOPS=3000 \
--set storageclass.qosRWMBPerSec=125 \
--set externalSnapshotter.enabled=true
nodes is every management API endpoint of the storage cluster as
<ip>:8082 — list all of them, the driver fails over between them — and the
credentials are its admin user.
The StorageClass parameters from the calculator
Every value in the calculator's second block, and the Helm flag it goes in as. The parameter names are what a hand-written StorageClass uses instead — see StorageClass parameters.
| Sizing output | Helm value | What it is |
|---|---|---|
ratio_cache_r_cache_size | storageclass.ratioCacheRCacheSize | Read cache as a ratio of volume size. This is the volume's whole footprint on the cache disks: it serves reads and writes alike. |
ratio_cache_rw_cache_size | storageclass.ratioCacheRWCacheSize | How much of that footprint may be dirty and waiting to drain — half the read ratio, so half the cache stays clean for reads. |
max_cache_r_cache_size | storageclass.maxCacheRCacheSize | Read-cache ceiling, MiB. The cache is clamp(ratio × volume size, floor, ceiling), so this is what a volume at the sized size actually gets. |
max_cache_rw_cache_size | storageclass.maxCacheRWCacheSize | Write-cache ceiling, MiB — inside the read cache, not beside it. |
qos_rw_ios_per_sec | storageclass.qosRWIOPS | Combined read+write IOPS cap per volume, the per-volume IOPS the pool was sized for. |
qos_rw_mbytes_per_sec | storageclass.qosRWMBPerSec | Combined read+write bandwidth cap per volume, MB/s. |
These have to match the pool they point at. The ceilings are what the pool's
per-disk r_cache_size_in_mib and rw_cache_size_in_mib budgets were sized
from, so a class with larger ones places fewer volumes per node than the
sizing assumed, and the scheduler starts rejecting volumes earlier than
expected — see Caching and tiering.
Nothing here is required: leave a parameter out and the chart's default applies, and an unset QoS cap is omitted from the class entirely rather than sent as a zero. The rest of the chart's values are on the Helm values page.
Step 3 — Verify
kubectl get pods -n mgx-system kubectl get storageclass mgxcsi-sc kubectl get volumesnapshotclass mgxcsi-snapshotclass
You should see one mgxcsi-controller-0 pod and one mgxcsi-node-* pod per
node, all Running. The chart creates a StorageClass named mgxcsi-sc and a
VolumeSnapshotClass named mgxcsi-snapshotclass by default.
Step 4 — Create a test pod with a volume
A PVC and a pod that mounts it, in one file — test-pod.yaml. Nothing about
the volume is special at the pod level:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: mgxcsi-sc
resources:
requests:
storage: 1Ti
---
apiVersion: v1
kind: Pod
metadata:
name: mgx-test
spec:
containers:
- name: app
image: busybox
command: ["sleep", "infinity"]
volumeMounts:
- name: data
mountPath: /data
volumes:
- name: data
persistentVolumeClaim:
claimName: data
kubectl apply -f test-pod.yaml kubectl get pvc data -w # waits for Bound kubectl wait --for=condition=Ready pod/mgx-test --timeout=5m
The volume is formatted and mounted by the node plugin, so df inside the
container is the check that the whole path worked:
kubectl exec mgx-test -- df -h /data
Filesystem Size Used Available Use% Mounted on /dev/nvme1n1 1006.9G 28.0K 955.6G 0% /data
A terabyte, minus the filesystem's own reserve. Then clean up — the pod first, so the volume is unpublished before it is deleted:
kubectl delete pod mgx-test kubectl delete pvc data
The class ships with reclaimPolicy: Delete, so deleting the PVC deletes the
volume on the pool too — the storage group in the CLI is where
to confirm it is gone. Or keep the volume and carry on with
Provisioning volumes.
Next
- Provisioning volumes — mounting, reclaiming space, deleting
- Snapshots and restore — point-in-time copies in S3
- StorageClass parameters — cache sizing, QoS, encryption, compression