# csi-driver-nfs: NFS volumes for Kubernetes through the Container Storage Interface

> The NFS CSI driver lets Kubernetes mount an existing NFSv3 or NFSv4 server through the Container Storage Interface, and it provisions volumes dynamically by creating a subdirectory per claim. It is a GA project in the Kubernetes storage special interest group, and the driver is deliberately a thin client rather than a storage system.

**kubernetes-csi/csi-driver-nfs** — This driver allows Kubernetes to access NFS server on Linux node.

- Repository: https://github.com/kubernetes-csi/csi-driver-nfs
- Stars: 1,335 · Forks: 324
- Language: Go
- License: Apache-2.0
- Published: 2026-10-19 · Updated: 2026-10-19 · Language: en
- Canonical page: https://hysenlabs.com/projects/kubernetes-csi-csi-driver-nfs

## A thin client, and it says so up front

The NFS CSI driver for Kubernetes allows Kubernetes to access an NFS server. The About section is short, and the second sentence matters more than the first: the driver requires an existing and already configured NFSv3 or NFSv4 server.

That single requirement defines the whole project. It is not a storage system, it is not a NAS appliance, and it does not manage the export list, the users or the shares on the server side. What it does is teach Kubernetes how to talk to an NFS server that already exists, using the Container Storage Interface, and to create the volumes Kubernetes asks for inside that server.

Dynamic provisioning works by creating a new sub directory under the NFS server. A Persistent Volume Claim becomes a directory, and the pod mounts it as a volume. That is a simple model with a clear consequence: the number of directories on the server grows with the number of claims, and the lifecycle of those directories is the thing you have to get right.

Two identifiers pin the project down. The CSI plugin name is nfs.csi.k8s.io, which is the string that appears in a StorageClass and in the CSI driver objects, and the project status is GA. The primary language is Go, the licence is Apache-2.0, and the repository lives in the Kubernetes storage special interest group organisation, which is the group that owns the CSI drivers.

## The compatibility matrix is short and stable

The Container Images and Kubernetes Compatibility table is the kind of table that tells you a project has settled down.

Four rows are listed. The master branch supports Kubernetes 1.21 and later and is GA. Version v4.13.5 supports 1.21 and later and is GA, v4.12.1 supports 1.21 and later and is GA, and v4.11.0 supports 1.21 and later and is GA.

Every row has the same supported Kubernetes range, which means the driver is not tracking a narrow window of cluster versions. The minimum of 1.21 is more than four years old at the time of writing, and the driver still declares support for it. That is a deliberately conservative posture: the NFS client path is stable, so the driver does not need to be rebuilt for every Kubernetes release.

The release history is regular and recent. v4.13.3 was tagged on 2026-06-15, v4.13.4 on 2026-07-01 and v4.13.5 on 2026-10-08, with the last push to the repository on 2026-10-14.

The build system, however, is ahead of the compatibility promise. The Makefile carries IMAGE_VERSION ?= v4.14.0 as the default version stamped into the image, which is a patch series beyond the newest tag in the release list. That is the normal state of a repository where the master branch is always the next release, and it is another reason to install a tagged version rather than tracking the branch.

## Install with Helm or kubectl

There are two documented installation routes, and the choice between them is a matter of how much of the deployment you want to own.

Install by Helm charts is the first route, with the charts in the charts/ directory in the repository. Install by kubectl is the second, with the procedure in docs/install-nfs-csi-driver.md. There is also a link for installing the NFS CSI driver on MicroK8s, which is a useful pointer to a distribution-specific installation guide.

The deployment manifests live in the deploy/ directory, and the examples are also under deploy/example/. The example set is the part worth reading, because each one exercises a different feature of the driver rather than repeating the same basic case. There is a basic usage README, an fsGroupPolicy example, a snapshot example and a volume cloning example.

fsGroupPolicy deserves a note. It is the mechanism that decides which ownership and permission handling a volume gets when a pod runs with a security context that sets fsGroup, and the fact that the project ships a dedicated example for it tells you it is a configuration point people get wrong. The Makefile's end-to-end options also set feature.enableInlineVolume=true and externalSnapshotter.enabled=true, which shows that inline volumes and the external snapshotter are feature flags in the chart rather than always-on behaviour.

For a first attempt, the basic usage example in the deploy directory is the right place to start, and the driver parameters documentation is the reference to have open beside you.

## The image is a Debian base and the mount tools

The Dockerfile is short, and its contents tell you exactly what the driver needs from the system it runs in.

The base is registry.k8s.io/build-image/debian-base:bookworm-v1.0.8, and the plugin binary is copied in as /nfsplugin with the architecture passed in as a build argument. The runtime packages are installed with clean-install and are ca-certificates, mount, nfs-common and netbase, with libcap2 explicitly unheld so it can be upgraded, and the entrypoint is /nfsplugin.

The two packages that matter are mount and nfs-common, and their presence is the implementation strategy. The driver does not implement the NFS client protocol itself; it uses the system's mount utility and the system's NFS client to perform the mount inside the container, which is why the image is a Debian base with those tools rather than a distroless or scratch image.

That is a trade-off. It means the driver behaves exactly like the host's NFS client, including its quirks and its security options, and it means the image is a normal Debian image with a normal package set. It also means the container is not a hermetic build, and a change in the base image can change mount behaviour, which is one reason the project pins an exact base image tag rather than tracking Debian bookworm generally.

The image is published to a registry, the Artifact Hub badge in the README points at the package listing, and the driver image build pipeline has its own TestGrid dashboard, post-csi-driver-nfs-push-images, which is where you can watch the images being produced.

## The build stamps the version into the binary

The Makefile is where the release engineering is visible, and a few lines are worth reading.

The build includes release-tools/build.make, which is the shared Kubernetes release tooling rather than something written for this driver. The version and commit are injected into the binary with linker flags, setting the driverVersion, gitCommit and buildDate variables in the nfs package, and the flags are stripped with -s -w -extldflags for a static binary. The build date is generated as a UTC timestamp in the standard format.

The image version is a make variable, IMAGE_VERSION ?= v4.14.0, and the image name defaults to nfsplugin with the registry and tag derived from it. There is also a test-specific override: when the CI environment variable is set and publishing is not, the image version becomes e2e- prefixed with the Git commit, so that end-to-end test images can never be mistaken for a release image. That is a small detail that shows the release process has been through a few iterations.

The end-to-end test options are also make variables, and they set the image repository and tag for the chart, force the pull policy, enable the inline volume feature and enable the external snapshotter, which is how the test harness exercises the same Helm values an operator would use.

The rest of the repository is the standard Kubernetes project layout, with cmd/ for the entry point, pkg/ for the driver packages, test/ for the test suites, hack/ for the build scripts, vendor/ for the vendored dependencies, plus a .golangci.yml for linting, a .trivyignore for the image scanner, and both .prow.sh and .cloudbuild.sh for the two continuous integration paths, the Kubernetes Prow jobs and Google Cloud Build.

## The dependency list explains the size of the build

The go.mod is worth reading for one dependency in particular. The module requires Go 1.26.0, and the direct requirements include the Container Storage Interface specification at v1.11.0, csi-lib-utils at v0.9.0, gRPC at v1.83.2 with protobuf, and the Kubernetes libraries at v0.32.10, including k8s.io/api, k8s.io/apimachinery, k8s.io/client-go, k8s.io/mount-utils, k8s.io/klog/v2, k8s.io/pod-security-admission and k8s.io/utils.

The line to notice is k8s.io/kubernetes at v1.32.10, the main Kubernetes repository, as a direct dependency. Depending on the monorepo rather than only on the published libraries pulls a very large dependency tree, and you can see the size of it in the indirect requirements, which include containerd's API packages, the CNI plugin libraries, cadvisor, the Docker and distribution reference packages and the Windows-specific winio package. The module also requires a Pod Security Admission library, which is consistent with a driver that has to work under a restricted pod security context.

The test dependencies are the usual Kubernetes set, with Ginkgo v2 and Gomega for the specs, testify for assertions, goleak for goroutine leak detection, and uuid for identifiers.

The Kubernetes libraries in the dependency tree are at 1.32, well above the 1.21 minimum the compatibility table advertises.

Two support paths are documented. The troubleshooting guide is at docs/csi-debug.md, and the CI results are on TestGrid, with the sig-storage-csi-nfs dashboard for the tests and the image build pipeline dashboard for the artefacts. The maintainers are reachable on the sig-storage Slack channel and the kubernetes-sig-storage mailing list, and participation is governed by the Kubernetes Code of Conduct.

## Conclusion

Adopt csi-driver-nfs if you already run an NFS server and want Kubernetes workloads to consume it through a standard interface with dynamic provisioning, snapshots and volume cloning. Do not adopt it if you need the driver to manage the storage server itself, since it explicitly requires an existing and already configured NFS server, and do not treat dynamic provisioning as a replacement for capacity planning, because every claim becomes a directory on that server. Before you start, read the driver parameters documentation and pick a deletion policy for the subdirectories, then test the basic usage example and the fsGroupPolicy example before you rely on the driver in production.

## FAQ

### What does the NFS CSI driver require before it can be installed?

It requires an existing and already configured NFSv3 or NFSv4 server. The driver is a client for a server you already run, and it does not manage the exports, users or shares on that server.

### How does dynamic provisioning work with csi-driver-nfs?

When a Persistent Volume Claim is created, the driver creates a new sub directory under the NFS server and mounts it for the pod. The CSI plugin name is nfs.csi.k8s.io, and the project status is GA with Kubernetes 1.21 and later supported.

### How do I install the NFS CSI driver?

There are two documented routes: the Helm charts in the charts/ directory of the repository, or kubectl with the procedure in docs/install-nfs-csi-driver.md. There is also a guide for installing the driver on MicroK8s, and the deploy/example directory holds basic usage, fsGroupPolicy, snapshot and volume cloning examples.

### Which Kubernetes versions does csi-driver-nfs support?

The master branch and the tagged versions v4.13.5, v4.12.1 and v4.11.0 all list Kubernetes 1.21 and later as supported and are marked GA. The recent tags are v4.13.3 on 2026-06-15, v4.13.4 on 2026-07-01 and v4.13.5 on 2026-10-08.

### What is inside the NFS CSI driver container image?

It is built on registry.k8s.io/build-image/debian-base:bookworm-v1.0.8 with the nfsplugin binary as the entrypoint, and it installs ca-certificates, mount, nfs-common and netbase, so the mounting is performed with the system NFS client rather than by an implementation inside the driver.

## Sources

- [Issues](https://github.com/kubernetes-csi/csi-driver-nfs/issues)
- [kubernetes-csi/csi-driver-nfs on GitHub](https://github.com/kubernetes-csi/csi-driver-nfs)
- [License: Apache-2.0](https://github.com/kubernetes-csi/csi-driver-nfs/blob/master/LICENSE)
- [README](https://github.com/kubernetes-csi/csi-driver-nfs/blob/master/README.md)
- [Releases](https://github.com/kubernetes-csi/csi-driver-nfs/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/kubernetes-csi-csi-driver-nfs
