NFS / CIFS
TL;DR
NFS and CIFS/SMB are common shared filesystem backends for ReadWriteMany workloads. Most incidents are DNS/routing, export/share permissions, node missing mount tools, UID/GID mismatch, or stale mounts.
When To Use
| Backend | Good for | Watch out |
|---|---|---|
| NFS | Linux shared files, simple RWX, on-prem exports. | UID/GID permissions, locking, server throughput. |
| CIFS/SMB | Windows shares, Azure Files, mixed environments. | Credentials, mount options, file mode behavior. |
| Block volume | Databases needing low-latency RWO storage. | Usually cannot mount RWX across nodes. |
Static NFS PV
yamlnfs-static-pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-reports-pv
spec:
capacity:
storage: 500Gi
accessModes:
- ReadWriteMany # Multiple Pods/nodes can mount read-write.
persistentVolumeReclaimPolicy: Retain # Keep data if PVC is deleted.
storageClassName: nfs-static
mountOptions:
- nfsvers=4.1 # Match what the server supports.
- hard # Retry indefinitely; common for data integrity.
nfs:
server: 10.20.30.40 # NFS server IP or resolvable DNS name.
path: /exports/reports # Exported directory on the NFS server.
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: reports
namespace: app
spec:
accessModes: ["ReadWriteMany"]
storageClassName: nfs-static
resources:
requests:
storage: 100GiCIFS / SMB PV
yamlsmb-pv.yaml
apiVersion: v1
kind: Secret
metadata:
name: smb-credentials
namespace: app
type: Opaque
stringData:
username: DOMAIN\\svc-k8s # Use the service account provided by the client.
password: change-me # Store real value in external secret manager when possible.
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: smb-share-pv
spec:
capacity:
storage: 100Gi
accessModes: ["ReadWriteMany"]
persistentVolumeReclaimPolicy: Retain
storageClassName: smb-static
csi:
driver: smb.csi.k8s.io
volumeHandle: smb-share-prod # Unique ID for this share in the cluster.
volumeAttributes:
source: //fileserver.example.com/shared # SMB UNC path.
nodeStageSecretRef:
name: smb-credentials
namespace: appNode-Level Checks
bashnode-mount-checks.sh
# Kubernetes-side symptoms.
kubectl describe pod <pod> -n app # Look for FailedMount and permission errors.
kubectl describe pvc reports -n app
kubectl get events -n app --sort-by=.lastTimestamp | grep -i -E 'mount|volume|nfs|smb|cifs'
# If you have node shell access:
which mount.nfs || rpm -q nfs-utils || dpkg -l nfs-common # NFS mount helper must exist.
which mount.cifs || rpm -q cifs-utils || dpkg -l cifs-utils # CIFS mount helper must exist.
showmount -e 10.20.30.40 # Lists NFS exports if server allows it.
sudo mount -t nfs4 10.20.30.40:/exports/reports /mnt # Manual NFS mount test.
sudo dmesg | tail -50 # Kernel mount errors often show real cause.Permissions Pattern
yamlpod-fsgroup.yaml
apiVersion: v1
kind: Pod
metadata:
name: report-writer
namespace: app
spec:
securityContext:
runAsUser: 1000 # App process UID.
runAsGroup: 1000 # App process primary GID.
fsGroup: 2000 # Kubernetes asks the volume to be group-owned/readable where supported.
containers:
- name: writer
image: busybox:1.36
command: ["sh", "-c", "echo ok >> /reports/health.txt; sleep 3600"]
volumeMounts:
- name: reports
mountPath: /reports
volumes:
- name: reports
persistentVolumeClaim:
claimName: reportsGotchas
- NFS export permissions and Kubernetes Pod permissions both matter; fix both sides.
- Root squash can make root inside the container unable to write to the export.
- RWX does not mean infinite performance. Shared filesystems can become the bottleneck.
- CIFS credentials in Secrets need the same protection as database passwords.