Kubernetes Persistent Volume access modes define how a volume can be mounted by nodes in a cluster, governing concurrency and read/write behavior.

Table of Contents#

  1. Overview
  2. Access Mode Definitions
  3. CSI Driver Backend Support
  4. StorageClass Examples
  5. StatefulSet vs Deployment Considerations
  6. Performance Implications
  7. Choosing the Right Access Mode
  8. Troubleshooting
  9. See Also
  10. Sources

1. Overview#

Persistent Volumes (PVs) in Kubernetes abstract the underlying storage implementation and expose it to pods via Persistent Volume Claims (PVCs). Each PV declares which access modes it supports, and each PVC requests a specific access mode. The access mode determines whether the volume can be mounted by a single node or multiple nodes, and whether writes are permitted.

Access modes are enforced at the node level, not the pod level. A volume with ReadWriteOnce can be mounted by multiple pods, provided they all run on the same node.

2. Access Mode Definitions#

ReadWriteOnce (RWO)#

  • Abbreviation: ReadWriteOnce
  • Behavior: The volume can be mounted as read-write by a single node
  • Multiple pods: Yes, if all pods are on the same node
  • Use cases: Single-instance databases (PostgreSQL, MySQL), application state directories, CI build caches

ReadOnlyMany (ROX)#

  • Abbreviation: ReadOnlyMany
  • Behavior: The volume can be mounted as read-only by many nodes simultaneously
  • Multiple pods: Yes, across multiple nodes, all read-only
  • Use cases: Shared configuration data, static web content, pre-built machine learning models, shared certificate stores

ReadWriteMany (RWX)#

  • Abbreviation: ReadWriteMany
  • Behavior: The volume can be mounted as read-write by many nodes simultaneously
  • Multiple pods: Yes, across multiple nodes, all read-write
  • Use cases: Shared upload directories, CMS media storage, shared build artifacts, collaborative application data

ReadWriteOncePod (RWOP)#

  • Abbreviation: ReadWriteOncePod (Kubernetes 1.27+ GA)
  • Behavior: The volume can be mounted as read-write by a single pod on a single node
  • Multiple pods: No, strictly one pod cluster-wide
  • Use cases: Databases requiring exclusive access guarantees, leader-election storage, write-ahead logs

3. CSI Driver Backend Support#

Not all storage backends support all access modes. The table below maps common CSI drivers to their supported modes:

Storage BackendRWOROXRWXRWOPNotes
LonghornYesYesYesYesRWX via NFS share manager; performance reduced
NFS (nfs-subdir-external-provisioner)YesYesYesNoAll modes via NFS protocol; no block support
Ceph RBD (rbd.csi.ceph.com)YesYesNoYesBlock device; ROX via read-only clone
CephFS (cephfs.csi.ceph.com)YesYesYesNoFilesystem-level sharing
AWS EBS (ebs.csi.aws.com)YesNoNoYesBlock device, single-attach only
GCE PD (pd.csi.storage.gke.io)YesYesNoYesROX via multi-attach read-only
Azure Disk (disk.csi.azure.com)YesNoNoYesBlock device, single-attach only
Azure Files (file.csi.azure.com)YesYesYesNoSMB/NFS-based
iSCSI (generic)YesNoNoNoBlock device, single-initiator
Local PVYesNoNoYesNode-local, no network sharing
OpenEBS (Jiva/cStor)YesNoNoNoBlock replication
PortworxYesYesYesYesFull-featured SDS

4. StorageClass Examples#

Longhorn (RWO, Default)#

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: longhorn
provisioner: driver.longhorn.io
parameters:
  numberOfReplicas: "3"
  staleReplicaTimeout: "2880"
  dataLocality: "best-effort"
reclaimPolicy: Delete
volumeBindingMode: Immediate
allowVolumeExpansion: true

Longhorn RWX#

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: longhorn-rwx
provisioner: driver.longhorn.io
parameters:
  numberOfReplicas: "3"
  nfsOptions: "vers=4.1,hard,timeo=600"
reclaimPolicy: Delete
volumeBindingMode: Immediate
allowVolumeExpansion: true

NFS#

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: nfs
provisioner: nfs.csi.k8s.io
parameters:
  server: <nfs-server-ip>
  share: /srv/nfs/k8s
reclaimPolicy: Delete
volumeBindingMode: Immediate
mountOptions:
  - nfsvers=4.1
  - hard
  - noatime

Ceph RBD#

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: ceph-rbd
provisioner: rbd.csi.ceph.com
parameters:
  clusterID: <ceph-cluster-id>
  pool: kubernetes
  imageFeatures: layering
  csi.storage.k8s.io/provisioner-secret-name: csi-rbd-secret
  csi.storage.k8s.io/provisioner-secret-namespace: ceph-system
  csi.storage.k8s.io/node-stage-secret-name: csi-rbd-secret
  csi.storage.k8s.io/node-stage-secret-namespace: ceph-system
reclaimPolicy: Delete
allowVolumeExpansion: true

PVC Requesting a Specific Access Mode#

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: my-pvc
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: longhorn
  resources:
    requests:
      storage: 10Gi

5. StatefulSet vs Deployment Considerations#

AspectDeployment + PVCStatefulSet + volumeClaimTemplates
PVC bindingAll pods share one PVCEach pod gets its own PVC (e.g., data-myapp-0, data-myapp-1)
Access mode requiredRWX (if replicas > 1 across nodes) or RWO (if single replica or co-located)RWO is sufficient (each pod has its own volume)
ScalingNew replicas mount the same volumeNew replicas get new PVCs automatically
Data isolationNo isolation between replicasFull isolation; each replica has its own data
Storage backendMust support RWX for multi-nodeAny backend supporting RWO works
Pod identityPods are interchangeablePods have stable identities (ordinal index)
DeletionPVC persists; manually deletePVCs persist by default; use persistentVolumeClaimRetentionPolicy (1.27+)

When to Use Each#

  • StatefulSet with RWO: Databases (PostgreSQL, MySQL, MongoDB), message brokers (Kafka, RabbitMQ), any workload needing per-instance persistent state
  • Deployment with RWX: Shared media uploads, CMS content, log aggregation directories, shared build caches
  • Deployment with RWO: Single-replica applications with persistent state (simple, no scaling)
  • Deployment with ROX: Configuration or static content distributed to many read-only replicas

6. Performance Implications#

Access ModeBackendTypical LatencyThroughputNotes
RWO (block)Local SSD / NVMeLowest (<0.1 ms)HighestDirect device access
RWO (block)Ceph RBD / LonghornLow (0.5-2 ms)HighNetwork replication adds latency
RWO (block)Cloud EBS/PDLow-Moderate (1-5 ms)ModerateNetwork-attached block
ROX (any)NFS/CephFSModerate (1-10 ms)ModerateRead caching helps
RWX (NFS)NFS / Longhorn NFSModerate (2-10 ms)ModerateNFS protocol overhead
RWX (CephFS)CephFSModerate (1-5 ms)HighParallel metadata servers
RWOP (block)Any block backendSame as RWOSame as RWONo additional overhead vs RWO

Key considerations:

  • RWX via NFS adds a protocol translation layer, increasing latency compared to direct block access
  • Longhorn RWX creates an NFS share manager pod per volume, consuming additional CPU and memory
  • For read-heavy workloads, ROX with client-side caching can outperform RWX
  • RWOP guarantees exclusive access, enabling filesystem optimizations (no lock contention)

7. Choosing the Right Access Mode#

Decision process:

  1. Does the workload need write access?
    • No: Use ROX
    • Yes: Continue
  2. Do multiple pods on different nodes need write access?
    • No: Use RWO (or RWOP for strict single-pod guarantee)
    • Yes: Use RWX
  3. Is the storage backend compatible?
    • Check the CSI driver support table above
    • If RWX is needed but the backend only supports RWO, consider NFS on top of block storage or a different backend
  4. Are you using StatefulSet or Deployment?
    • StatefulSet: RWO is usually sufficient since each pod gets its own PVC
    • Deployment with replicas > 1: RWX is required if pods land on different nodes

Troubleshooting#

IssueCauseSolution
PVC stuck in PendingNo PV matches the requested access mode and StorageClassVerify the StorageClass provisioner supports the requested access mode; check PV availability
Multi-Attach error for volumeTwo pods on different nodes trying to mount an RWO volumeChange to RWX access mode, or use a StatefulSet so each pod gets its own PVC
Pod stuck in ContainerCreating with volume mount errorCSI driver cannot attach the volumeCheck CSI driver pods are running; inspect events with kubectl describe pod <pod>
RWX volume has poor write performanceNFS protocol overhead or contentionIncrease NFS server threads; use nconnect mount option; consider CephFS for better parallel performance
Data corruption with RWXApplication not designed for concurrent writesUse application-level locking (flock), or switch to a database; RWX does not guarantee consistency between writers
RWOP not availableKubernetes version <1.27 or CSI driver does not support itUpgrade Kubernetes to 1.27+; check CSI driver documentation for RWOP support
Volume expansion failsStorageClass does not have allowVolumeExpansion: trueEdit the StorageClass to enable expansion; some backends require offline expansion (pod must be deleted first)

See Also#

Sources#