In multi-tenant workloads or any scenario where pods must not share storage, you need per-pod data isolation without provisioning separate NAS file systems. Container Network File System (CNFS) solves this by mapping each directory in a single NAS file system to an independent persistent volume (PV), so different pods mount separate subdirectories and cannot access each other's data.
This topic uses a StatefulSet to walk through creating isolated NAS volumes, verifying that data is mounted correctly, and confirming that writes in one pod are invisible to another.
Prerequisites
Before you begin, ensure that you have:
NAS activated. If this is your first time, visit the NAS product page and follow the on-screen instructions
An ACK cluster running Kubernetes 1.20 or later, with the Container Storage Interface (CSI) plug-in as the volume plug-in. For details, see Create an ACK managed cluster
kubectl connected to your cluster. For setup instructions, see Obtain the kubeconfig file of a cluster and use kubectl to connect to the cluster
Component version requirements — verify these if you have an existing cluster:
csi-plugin and csi-provisioner: v1.24.11-5221f79-aliyun or later. For upgrade instructions, see Install and update the CSI components
storage-operator: v1.24.105-825188d-aliyun or later. For upgrade instructions, see Manage components
For a CNFS overview, see CNFS overview. To learn how to manage NAS file systems with CNFS, see Use CNFS to manage NAS file systems (recommended).
How it works
When you set volumeAs: subpath in a StorageClass and reference a CNFS object, the CSI plug-in provisions each persistent volume claim (PVC) as a distinct subdirectory under the NAS file system root. Because each pod mounts a different subdirectory, writes in one pod's /data path are not visible in another pod's /data path — even though all pods share the same underlying NAS file system.
Step 1: Create the workload
First, get the name of your CNFS object:
kubectl get cnfsThe output lists available CNFS objects. Note the name of the one that manages your NAS file system — you will reference it as the value of containerNetworkFileSystem in the StorageClass.
Create a StorageClass named cnfs-nas-sc and a StatefulSet named cnfs-nas-dynamic-sts. The StatefulSet uses volumeClaimTemplates to automatically provision a separate PVC (and therefore a separate NAS subdirectory) for each pod replica.
cat << EOF | kubectl apply -f -
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: cnfs-nas-sc
mountOptions:
- nolock,tcp,noresvport
- vers=3
parameters:
volumeAs: subpath
containerNetworkFileSystem: cnfs-nas-filesystem # Replace with your CNFS object name.
path: "/"
archiveOnDelete: "false"
provisioner: nasplugin.csi.alibabacloud.com
reclaimPolicy: Delete
allowVolumeExpansion: true
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: cnfs-nas-dynamic-sts
labels:
app: busybox
spec:
serviceName: "busybox"
replicas: 2
selector:
matchLabels:
app: busybox
template:
metadata:
labels:
app: busybox
spec:
containers:
- name: busybox
image: busybox
command: ["/bin/sh"]
args: ["-c", "sleep 3600;"]
volumeMounts:
- mountPath: "/data"
name: pvc
volumeClaimTemplates:
- metadata:
name: pvc
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: "cnfs-nas-sc" # Reference the StorageClass named cnfs-nas-sc.
resources:
requests:
storage: 50Gi
EOFKey StorageClass parameters:
| Parameter | Description |
|---|---|
volumeAs: subpath | Provisions each PVC as a subdirectory of the NAS file system, enabling per-pod isolation. |
containerNetworkFileSystem | The name of the CNFS object that manages your NAS file system. Run kubectl get cnfs to find it. |
path: "/" | The base path in the NAS file system under which subdirectories are created. |
archiveOnDelete: "false" | Deletes the NAS subdirectory when the PVC is deleted. Set to "true" to retain the data. |
reclaimPolicy: Delete | Deletes the PV when the PVC is deleted. |
allowVolumeExpansion: true | Allows you to expand the PVC size after creation. |
Step 2: Verify the mount
Run the following command to confirm the NAS volume is mounted in cnfs-nas-dynamic-sts-0:
kubectl exec cnfs-nas-dynamic-sts-0 -- mount | grep nfsExpected output:
971134b0e8-****.cn-zhangjiakou.nas.aliyuncs.com:/nas-95115c94-2ceb-4a83-b4f4-37bd35df**** on /data type nfs (rw,nosuid,nodev,relatime,user_id=0,group_id=0,default_permissions,allow_other)The NAS file system is mounted at /data. Each pod in the StatefulSet mounts a different subdirectory, indicated by the unique path suffix in the output.
Step 3: Write data to the volume
To confirm that isolation works, write a test file to cnfs-nas-dynamic-sts-0 and then check whether it appears in cnfs-nas-dynamic-sts-1. Because each pod mounts a separate NAS subdirectory, the file written in one pod must not be visible in the other.
Write a 1 GB temporary file to /data in cnfs-nas-dynamic-sts-0:
kubectl exec cnfs-nas-dynamic-sts-0 -ti -- sh -c 'dd if=/dev/zero of=/data/1G.tmpfile bs=1G count=1;'Verify the file exists in cnfs-nas-dynamic-sts-0:
kubectl exec cnfs-nas-dynamic-sts-0 -- ls -arlth /dataExpected output:
total 1G
-rw-r--r-- 1 root root 1.0G Dec 15 12:11 1G.tmpfileStep 4: Confirm isolation between pods
Run the following command to check whether the file appears in cnfs-nas-dynamic-sts-1:
kubectl exec cnfs-nas-dynamic-sts-1 -- ls -arlth /dataExpected output:
sh-4.4# ls -arlth
total 8.0K
drwxr-xr-x 1 root root 4.0K Dec 15 18:07 ..
drwxr-xr-x 2 root root 4.0K Dec 15 18:07 .The directory is empty. Together, steps 3 and 4 confirm that cnfs-nas-dynamic-sts-0 and cnfs-nas-dynamic-sts-1 write to isolated NAS subdirectories — data written in one pod is not visible in the other.
What's next
To configure multiple pods to share the same NAS directory, see Use CNFS to manage shared NAS volumes (recommended).
To automatically expand a NAS volume when usage exceeds a threshold, see Use CNFS to automatically expand NAS volumes.