Kubernetes NFS PersistentVolumes: Remote storage explained
Learn why Kubernetes remote storage exists and how to create a PersistentVolume backed by an NFS server. Covers static PV and PVC creation, ReadWriteMany access mode, and mounting NFS storage into a pod.
5 lessons · 16 min · Intermediate
Written by
Marketing Team at Civo
Written by
Marketing Team at Civo
Both emptyDir and hostPath have the same fundamental limitation: the data is tied to a specific node. If a pod is rescheduled to a different node, it no longer has access to the data it wrote previously. For production workloads, this is not acceptable.
Remote storage solves this problem. A remote volume lives outside the Kubernetes cluster entirely, on a separate server or storage system. When a pod mounts a remote volume and is later rescheduled to a different node, it reconnects to the same storage and finds the same data. The pod's location in the cluster is irrelevant.
NFS (Network File System) is one of the most common remote storage options. It is simple to set up, widely supported, and provides ReadWriteMany access mode, meaning multiple pods across different nodes can mount and write to the same volume simultaneously.
The recommended pattern for using NFS in Kubernetes is to create a PersistentVolume backed by the NFS server, then claim storage via a PVC. This abstracts the NFS server details away from the application developer.
Prerequisites
Before running this demo, ensure:
- An NFS server is running and reachable from all cluster nodes
- The shared path is exported with appropriate permissions on the NFS server
- The
nfs-commonpackage is installed on all cluster nodes (Debian/Ubuntu):
sudo apt-get install -y nfs-common
On RHEL/CentOS, install nfs-utils instead:
sudo yum install -y nfs-utils
Without the NFS client packages installed on the nodes, pods will fail to mount the volume and the pod will stay in a waiting state.
Static vs dynamic NFS provisioning
This page covers static provisioning: the NFS server details are known upfront and the PersistentVolume is created manually. This is straightforward and works well when you have a single NFS server and a small number of volumes to manage.
For self-service NFS storage where developers can request volumes on demand via a StorageClass, see the dynamic provisioning guide, which covers using nfs-subdir-external-provisioner to provision NFS-backed PVs automatically.
Step 1: Create the PersistentVolume
Replace <nfs-server-ip> with the IP address of your NFS server and <shared-path> with the exported directory path.
apiVersion: v1kind: PersistentVolumemetadata:name: pv-nfsspec:storageClassName: manualcapacity:storage: 1GiaccessModes:- ReadWriteManynfs:server: <nfs-server-ip>path: <shared-path>
kubectl create -f pv.yaml
Step 2: Create the PersistentVolumeClaim
apiVersion: v1kind: PersistentVolumeClaimmetadata:name: pvc-nfsspec:storageClassName: manualaccessModes:- ReadWriteManyresources:requests:storage: 1Gi
kubectl create -f pvc.yaml
Verify both are bound:
kubectl get pv,pvc
Expected output:
NAME CAPACITY ACCESS MODES STATUS STORAGECLASSpersistentvolume/pv-nfs 1Gi RWX Bound manualNAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASSpersistentvolumeclaim/pvc-nfs Bound pv-nfs 1Gi RWX manual
The PVC binds immediately without waiting for a pod. With static provisioning there is no WaitForFirstConsumer binding mode. The PV and PVC match on StorageClass name and access mode and bind straight away.
Step 3: Create a pod that uses the PVC
This pod mounts the NFS volume at /mnt and writes memory information to a file:
apiVersion: v1kind: Podmetadata:name: pod-using-nfsspec:volumes:- name: nfs-volumepersistentVolumeClaim:claimName: pvc-nfscontainers:- name: alpineimage: alpinecommand: ["sh", "-c", "cat /proc/meminfo > /mnt/memory.txt && while true; do sleep 3600; done"]volumeMounts:- mountPath: /mntname: nfs-volume
kubectl create -f pod.yamlkubectl get pods
Expected output:
NAME READY STATUS RESTARTS AGEpod-using-nfs 1/1 Running 0 10s
Step 4: Verify the data
Exec into the pod:
kubectl exec -it pod-using-nfs -- sh
Navigate to the mount path and check the file:
cd /mntls
Expected output:
memory.txt
cat memory.txt
The file contains memory information written by the container. The same file is simultaneously visible on the NFS server at the shared path. If the pod is deleted and recreated on a different node, it will reconnect to the same NFS share and find the file still there.
Why remote storage matters for production
emptyDir data is lost when the pod is deleted. hostPath data stays on a specific node and is inaccessible if the pod moves. NFS and other remote storage options decouple data from both pod and node lifecycle. Even if the entire Kubernetes cluster is lost, the data on the NFS server remains intact and recoverable.
This makes remote storage the right choice for any workload where data must survive pod restarts, rescheduling, or cluster failures.

Marketing Team at Civo
Civo is the Sovereign Cloud and AI platform designed to help developers and enterprises build without limits. We bridge the gap between the openness of the public cloud and the rigorous security of private environments, delivering full cloud parity across every deployment. As a team, we are dedicated to providing scalable compute, lightning-fast Kubernetes, and managed services that are ready in minutes. Through CivoStack Enterprise and our FlexCore appliance, we empower organizations to maintain total data sovereignty on their own hardware.
Our mission is to make the cloud faster, simpler, and fairer. By providing enterprise-grade NVIDIA GPUs and streamlined model management, we ensure that high-performance AI and machine learning are accessible to everyone. Built for transparency and performance, the Civo Team is here to give you total control over your infrastructure, your data, and your spend.
Share this lesson
Nice work, you finished Kubernetes Volumes: Persisting and sharing data in your cluster.
Your next step is up to you - keep building on what you've learned, or put it into practice on Civo.
Next Course
Kubernetes Networking: How pods, services and nodes communicate
2 lessons · 9 min
Understand how networking works in Kubernetes. Covers the networking model, CNI plugins, pod-to-pod communication, node-to-node routing, and container networking within a pod.
Put it into practice
Spin up your first cluster on Civo
Get $250 free credit and launch a production-ready Kubernetes cluster in under 90 seconds.