QNAP NAS as a Kubernetes Storage Backend: iSCSI, NFS, or Just Don't
Three ways to give your cluster persistent storage off a consumer NAS, ranked by regret

Everyone who builds a homelab Kubernetes cluster hits the same wall about a week in: stateful workloads. Your pods are stateless and beautiful until you want to run Postgres, or a media server, or anything that remembers things between restarts. Then you need persistent volumes, and you look around your house, and your eyes land on the QNAP NAS humming away in the corner with several terabytes of perfectly good storage. Surely you can just point the cluster at that?
You can. I have. There are three roads, and they offer very different amounts of pain. Let me walk you through iSCSI, NFS, and the third option — “just don’t, here’s what to do instead” — because pretending a consumer NAS is enterprise SAN gear is how you end up with a cluster that corrupts a database at 3am.
1 NFS: the easy road with a sharp edge
NFS is the path of least resistance. QNAP exposes it from the web UI in about four clicks, and Kubernetes has a well-trodden CSI driver for it. The killer feature is ReadWriteMany — multiple pods on different nodes can mount the same volume simultaneously, which is exactly what you want for shared media libraries or a bunch of replicas reading the same files.
Install the NFS CSI driver and define a StorageClass pointing at the NAS:
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: qnap-nfs
provisioner: nfs.csi.k8s.io
parameters:
server: 192.168.1.10
share: /share/k8s
mountOptions:
- nfsvers=4.1
- hard
- noatime
reclaimPolicy: Retain
volumeBindingMode: ImmediateThe sharp edge: NFS is a network filesystem, not a block device. Databases hate it. Postgres and SQLite both have known foot-guns with NFS locking, and a flaky network or a NAS that goes to sleep can corrupt data in ways that block storage wouldn’t. Use hard mounts (so I/O blocks and retries rather than failing), never soft, and keep databases off NFS. For media, documents, and bulk files it’s genuinely great.
2 iSCSI: block storage, more performance, more rope
iSCSI gives Kubernetes a real block device — the NAS carves out a LUN, the node attaches it, and as far as the pod is concerned it’s a local disk. This makes databases happy and gets you proper ReadWriteOnce semantics. QNAP supports iSCSI targets natively under Storage & Snapshots → iSCSI & Fibre Channel.
The democratic-csi project provides a CSI driver that can dynamically provision QNAP LUNs over SSH/API. A config snippet looks roughly like:
driver: freenas-iscsi # democratic-csi works with QNAP via the generic iscsi driver too
iscsi:
targetPortal: "192.168.1.10:3260"
namePrefix: csi-
targetGroups:
- targetGroupPortalGroup: 1
targetGroupInitiatorGroup: 1And every node that will mount these needs the initiator installed and running:
$ sudo apt install open-iscsi
$ sudo systemctl enable --now iscsid
$ sudo iscsiadm -m discovery -t sendtargets -p 192.168.1.10
192.168.1.10:3260,1 iqn.2004-04.com.qnap:ts-453:iscsi.k8s.abc123
$ sudo iscsiadm -m session
tcp: [1] 192.168.1.10:3260,1 iqn.2004-04.com.qnap:ts-453:... (non-flash)
The catch with iSCSI on a consumer QNAP is twofold. First, a LUN is single-attach — only one node mounts it at a time, so no ReadWriteMany. Second, and more importantly, your NAS is now a single point of failure for block storage that a pod believes is a local disk. If the QNAP reboots for a firmware update mid-write, the node sees a disk vanish out from under a running database. That’s a worse failure mode than a dropped NFS mount.
3 Just don’t: when the answer is distributed storage
Here’s the uncomfortable truth I arrived at. A consumer NAS is a fine file server. It is a poor storage backend for a cluster that’s supposed to be resilient, because the whole point of a cluster is to survive a node dying — and you’ve just made one box the thing everything depends on.
If you have three or more nodes with spare disks, run distributed storage inside the cluster instead: Longhorn or Ceph (via Rook). Longhorn in particular is almost embarrassingly easy:
$ kubectl apply -f https://raw.githubusercontent.com/longhorn/longhorn/v1.5.1/deploy/longhorn.yaml
$ kubectl -n longhorn-system get pods -w
It replicates each volume across nodes, survives a node loss, snapshots, and backs up to S3 or — yes — your NAS over NFS, which is exactly the right job for it. The NAS becomes the backup target, not the live storage path.
4 Verdict
So, which one? NFS off the QNAP for media, config, and any ReadWriteMany workload — easy, robust enough, just keep databases off it. iSCSI only if you specifically need block performance and you genuinely accept that the NAS is now a single point of failure; treat it as a deliberate trade, not a default. And for anything that’s meant to be highly available, don’t use the NAS as live storage at all — run Longhorn across your nodes and demote the QNAP to the backup target it’s actually good at. The NAS is a member of your storage strategy, not the whole of it.




