Shared storage with NFS
A shared filesystem is the fallback for an app that cannot use object storage, so confirm you need one first with Choose an RWX backend .
NFS gives you a ReadWriteMany filesystem without running an object store. For most shared data, object storage is the better answer, and NFS is for an app that needs a real filesystem and cannot use the S3 API. One server exports a directory, and pods on any node mount it and write to it at the same time. When you want RWX but do not want to run the object store and metadata engine that JuiceFS needs, NFS is the shorter path.
NFS fits when the shared data is small to moderate, the access pattern is a few writers rather than many, and you want the setup to stay simple. JuiceFS fits better when you need the data to live off the nodes in object storage and to scale past what one server holds.
In-cluster server or external server#
You have two ways to get an NFS export:
- Run an NFS server in the cluster. A single pod owns a block or local volume and exports it over NFS. This keeps everything inside Kubernetes, but the export is only as available as that one pod and its volume.
- Point at an external NFS server. If you already run NFS elsewhere, mount it from the cluster. The server lifecycle is then yours to manage outside Kubernetes.
Either way, the backing disk is an ordinary volume. Back an in-cluster server with a Hetzner Cloud block volume so the data survives node replacement.
Dynamic PVCs with the subdir provisioner#
Want each claim to get its own subdirectory automatically? The subdir provisioner handles that.
The nfs-subdir-external-provisioner turns one NFS export into dynamic PersistentVolumeClaims. It creates a subdirectory under the export for each claim and hands it to the pod. You install it once and point it at your server:
$ helm repo add nfs-subdir-external-provisioner https://kubernetes-sigs.github.io/nfs-subdir-external-provisioner/
$ helm repo update
$ helm install nfs-subdir-external-provisioner \
nfs-subdir-external-provisioner/nfs-subdir-external-provisioner \
--namespace kube-system \
--set nfs.server=<nfs-server-ip> \
--set nfs.path=/exported/path
That install registers a StorageClass. Claims against it get ReadWriteMany, so pods on different nodes share one directory:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: shared-data
spec:
accessModes:
- ReadWriteMany
storageClassName: nfs-client
resources:
requests:
storage: 10Gi
Note
The provisioner does not enforce the requested size. 10Gi is a label on the claim, not a quota. The real limit is the free space on the backing volume, so size that volume for the sum of every claim.
One server is a single point of failure#
Warning
A single NFS server is a single point of failure. If the server pod or its node goes down, every pod that mounts the export blocks until it comes back. For data that must stay writable through a node loss, use JuiceFS with a highly available metadata engine instead, or run the NFS server with its own replication.
Performance and locking caveats#
NFS is a network filesystem, so every read and write crosses the network to the server. That is slower than a local disk, and latency shows up most in workloads that touch many small files. File locking over NFS is also weaker than on a local filesystem. Some databases and applications that rely on strict flock or fcntl behavior do not run correctly on NFS. Check your application's own guidance before you put its data directory on an NFS mount.
Back the export up like any other volume. The data on an NFS server is a normal PVC, so Velero copies it out to object storage the same way it protects any other volume.
The NFS server is yours to run, outside the cluster stack and the managed platform. Syself Consulting can set NFS up to best practices with you, or take on running and maintaining the server for you.
Next, weigh NFS against the alternatives in Choose an RWX backend , or keep shared data off the nodes with ReadWriteMany with JuiceFS .
ReadWriteMany with JuiceFS
Stand up a shared ReadWriteMany filesystem on Syself Autopilot with JuiceFS, backed by S3-compatible object storage and a Redis or PostgreSQL metadata engine.
Choose an RWX backend
When to share data through object storage instead of a shared filesystem on Syself Autopilot, and how to choose JuiceFS or NFS when you do need ReadWriteMany.