A CSI driver for NASty — dynamic provisioning of storage volumes in Kubernetes from a bcachefs-based NAS.
- Multiple Protocols: NFS, NVMe-oF, iSCSI, SMB
- Volume Snapshots: Create, delete, and restore from snapshots
- Volume Cloning: Create new volumes from existing snapshots
- Volume Expansion: Resize volumes without pod recreation
- Volume Retention:
deleteStrategy: retainto keep volumes on PVC deletion - Volume Adoption: Migrate volumes between clusters with
markAdoptable/adoptExisting - Volume Name Templating: Customize volume names with Go templates or prefix/suffix
- Encryption: Filesystem-level bcachefs encryption validation
- Configurable Mount Options: Per-StorageClass mount options
- Kubernetes 1.26+
- Helm 3.0+
- A running NASty appliance with an API key
- Protocol-specific:
- NFS:
nfs-commonon all nodes - NVMe-oF:
nvme-tcpkernel module - iSCSI:
open-iscsion all nodes - SMB:
cifs-utilson all nodes - Snapshots: VolumeSnapshot CRDs installed
- NFS:
helm install nasty-csi oci://ghcr.io/nasty-project/charts/nasty-csi-driver \
--namespace kube-system \
--set nasty.url="wss://YOUR-NASTY-IP/ws" \
--set nasty.apiKey="YOUR-API-KEY" \
--set storageClasses[0].filesystem="YOUR-FS-NAME" \
--set storageClasses[0].server="YOUR-NASTY-IP"Chart 0.0.13 defaults to CSI v0.0.15. It passes the NASty API key through
Secret-backed NASTY_API_KEY environment variables rather than driver process
arguments. Do not override this chart to CSI v0.0.12 or older: those images do not
support this credential path. Wait for the v0.0.15 image to be published before
deploying this chart.
CSI v0.0.13 includes strict deletion ownership checks and uncertain RPC outcome handling. Existing unowned/incompletely initialized storage is not automatically adopted or deleted; review ownership explicitly if deletion fails closed. These changes do not make provisioning crash-atomic.
CSI v0.0.14 refills the nasty_csi_volume_capacity_bytes metric when the
controller starts, so capacity graphs survive controller restarts. Its image runs
on Alpine 3.24 with a refreshed CA bundle and is built with Go 1.27.3.
CSI v0.0.15 keeps iSCSI and NVMe-oF sessions connected when the kubelet re-stages a volume that is still mounted, for example after a kubelet restart, so running pods keep their storage. Its API client reconnects after three failed keepalive pings and fails in-flight calls promptly when the connection drops. Retried SMB volume creation now verifies the requested capacity.
Chart 0.0.11 defaults to CSI v0.0.12 unless image.tag is overridden. Chart and driver versions are independent.
CSI v0.0.12 moves volume health reporting to the CSI 1.13 alpha ControllerGetVolumeHealth and NodeGetVolumeHealth RPCs. The legacy VolumeCondition fields are no longer returned by volume info/stats RPCs; older health-monitor consumers need compatible client support. Normal volume operations are unaffected by this health API change.
| Parameter | Description | Default |
|---|---|---|
nasty.url |
WebSocket URL (wss://host/ws) |
"" (required) |
nasty.apiKey |
API key from NASty Settings | "" (required) |
nasty.existingSecret |
Existing Secret with url and api-key keys |
"" |
nasty.skipTLSVerify |
Skip TLS verification (self-signed certs) | false |
The controller and node pass the API credential through NASTY_API_KEY, not
command-line arguments. This requires a CSI image with environment credential
support; older images that require --api-key are incompatible with this change.
Environment credentials are still secrets: restrict access to pod specifications,
exec/debug facilities and the Kubernetes Secret. This does not make them anonymous
or inaccessible to privileged processes.
Each entry in storageClasses creates a Kubernetes StorageClass. Multiple entries per protocol are supported.
| Field | Description | Default |
|---|---|---|
name |
StorageClass name | nasty-nfs |
protocol |
nfs, nvmeof, iscsi, smb |
— |
enabled |
Create this StorageClass | true |
isDefault |
Set as default storage class | false |
filesystem |
bcachefs filesystem name on NASty | "storage" |
server |
NASty IP/hostname | "" |
reclaimPolicy |
Delete or Retain |
Delete |
volumeBindingMode |
Immediate or WaitForFirstConsumer |
Immediate |
allowVolumeExpansion |
Enable PVC resize | true |
mountOptions |
Additional mount options | [] |
deleteStrategy |
delete or retain (NASty-side) |
"" |
compression |
bcachefs compression (lz4, zstd) |
"" |
foregroundTarget |
Device group for foreground writes | "" |
backgroundTarget |
Device group for background moves (tiering) | "" |
promoteTarget |
Device group to promote data to on read | "" |
metadataTarget |
Device group for metadata/btree writes | "" |
dataReplicas |
Number of data replicas ("1" for expendable, "2" for durable) |
"" |
encryption |
Require encrypted filesystem | "" |
nameTemplate |
Go template for volume names | "" |
namePrefix / nameSuffix |
Volume name prefix/suffix | "" |
commentTemplate |
Go template for subvolume comments | "" |
markAdoptable |
Allow cross-cluster adoption | "" |
adoptExisting |
Adopt existing volumes | "" |
parameters |
Additional protocol-specific parameters | {} |
Block protocol fields (NVMe-oF, iSCSI):
| Field | Description | Default |
|---|---|---|
transport |
NVMe-oF transport (tcp/rdma) |
tcp |
port |
Target port | 4420 / 3260 |
fsType |
Filesystem on block device | ext4 |
SMB-specific fields:
| Field | Description | Default |
|---|---|---|
smbCredentialsSecret.name |
Secret name with SMB credentials | "" |
smbCredentialsSecret.namespace |
Secret namespace | "" |
smbUsername |
SMB user for share directory ownership | "" |
Example — multiple classes:
storageClasses:
- name: nasty-nfs
protocol: nfs
filesystem: "storage"
server: "10.0.0.1"
- name: nasty-nfs-retain
protocol: nfs
filesystem: "storage"
server: "10.0.0.1"
reclaimPolicy: Retain
deleteStrategy: retain
- name: nasty-nvmeof
enabled: true
protocol: nvmeof
filesystem: "storage"
server: "10.0.0.1"
transport: tcp
port: "4420"
fsType: ext4| Parameter | Description | Default |
|---|---|---|
snapshots.enabled |
Enable snapshot support | false |
snapshots.volumeSnapshotClass.create |
Create VolumeSnapshotClass | true |
snapshots.volumeSnapshotClass.deletionPolicy |
Delete or Retain |
Delete |
Install CRDs first:
kubectl apply -f https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/release-8.2/client/config/crd/snapshot.storage.k8s.io_volumesnapshotclasses.yaml
kubectl apply -f https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/release-8.2/client/config/crd/snapshot.storage.k8s.io_volumesnapshotcontents.yaml
kubectl apply -f https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/release-8.2/client/config/crd/snapshot.storage.k8s.io_volumesnapshots.yamlapiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: my-data
spec:
accessModes: [ReadWriteMany]
resources:
requests:
storage: 10Gi
storageClassName: nasty-nfs# Check pods
kubectl get pods -n kube-system -l app.kubernetes.io/name=nasty-csi-driver
# Controller logs
kubectl logs -n kube-system -l app.kubernetes.io/component=controller -c nasty-csi-driver
# Node logs
kubectl logs -n kube-system -l app.kubernetes.io/component=node -c nasty-csi-driver
# Enable debug
helm upgrade nasty-csi ... --set controller.logLevel=4 --set node.logLevel=4GPL-3.0