Access Modes

Access modes determine how a PersistentVolume can be mounted and accessed by pods. They specify whether one or multiple pods can access the volume, and whether those pods have read-only or read-write access. Choosing the correct access mode is crucial for ensuring your application works correctly and efficiently.

Understanding Access Modes

Access modes are declared in both PersistentVolumes and PersistentVolumeClaims. For a PVC to bind to a PV, their access modes must be compatible. Kubernetes defines three access modes:

graph TB A[Access Mode] --> B[ReadWriteOnce<br/>RWO] A --> C[ReadOnlyMany<br/>ROX] A --> D[ReadWriteMany<br/>RWX] B --> E[Single Node<br/>Read + Write] C --> F[Multiple Nodes<br/>Read Only] D --> G[Multiple Nodes<br/>Read + Write] style A fill:#e1f5ff style B fill:#fff4e1 style C fill:#e8f5e9 style D fill:#f3e5f5

ReadWriteOnce (RWO)

ReadWriteOnce allows the volume to be mounted as read-write by a single node. This is the most common and widely supported access mode.

Key characteristics:

  • One pod can mount the volume at a time
  • The pod has both read and write access
  • Most storage types support RWO (AWS EBS, GCE Persistent Disk, Azure Disk, local storage)
  • If multiple pods try to mount, only one succeeds

Binding behavior:

  • The volume is bound to a specific node
  • Pods on the same node can potentially share the volume (rarely used in practice)
  • When the pod is deleted, the volume can be bound to a pod on a different node
graph LR A[PVC with RWO] --> B[PV Bound] B --> C[Pod on Node 1] C --> D[Pod Deleted] D --> E[PV Released] E --> F[New Pod on Node 2] style A fill:#e1f5ff style B fill:#fff4e1 style C fill:#e8f5e9 style F fill:#e1f5ff

Example:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: database-pvc
spec:
  accessModes:
    - ReadWriteOnce  # Only one pod can mount
  storageClassName: fast-ssd
  resources:
    requests:
      storage: 100Gi

Use cases:

  • Databases (MySQL, PostgreSQL, MongoDB)
  • Single-instance applications with persistent data
  • Applications that need exclusive write access
  • Most stateful applications

Limitations:

  • Cannot be shared by multiple pods simultaneously
  • If you need multiple pods to write, you must use ReadWriteMany (if supported)

ReadOnlyMany (ROX)

ReadOnlyMany allows the volume to be mounted as read-only by multiple nodes simultaneously.

Key characteristics:

  • Multiple pods can mount the volume at the same time
  • All mounts are read-only (no writes allowed)
  • Useful for sharing configuration or reference data
  • Fewer storage types support ROX compared to RWO

Binding behavior:

  • Multiple pods can mount the same volume
  • All mounts are read-only
  • If a pod tries to write, the write operation fails
graph TB A[PV with ROX] --> B[Pod 1 on Node 1] A --> C[Pod 2 on Node 2] A --> D[Pod 3 on Node 3] B --> E[Read Only] C --> E D --> E style A fill:#e1f5ff style E fill:#e8f5e9

Example:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: config-pvc
spec:
  accessModes:
    - ReadOnlyMany  # Multiple pods, read-only
  storageClassName: standard
  resources:
    requests:
      storage: 10Gi

Use cases:

  • Configuration files shared across multiple pods
  • Reference data (databases, lookup tables)
  • Read-only content distribution
  • Shared libraries or assets

Limitations:

  • No write access (all mounts are read-only)
  • Not all storage types support ROX
  • If you need writes from multiple pods, use ReadWriteMany

ReadWriteMany (RWX)

ReadWriteMany allows the volume to be mounted as read-write by multiple nodes simultaneously. This is the most flexible but least commonly supported access mode.

Key characteristics:

  • Multiple pods can mount the volume simultaneously
  • All pods have read and write access
  • Only network-based storage typically supports RWX (NFS, some cloud file storage)
  • Performance can be slower than RWO due to network overhead

Binding behavior:

  • Multiple pods on different nodes can mount and write
  • Filesystem-level locking may be needed for concurrent writes
  • Network latency affects performance
graph TB A[PV with RWX] --> B[Pod 1 on Node 1] A --> C[Pod 2 on Node 2] A --> D[Pod 3 on Node 3] B --> E[Read + Write] C --> E D --> E style A fill:#e1f5ff style E fill:#fff4e1

Example:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: shared-content-pvc
spec:
  accessModes:
    - ReadWriteMany  # Multiple pods, read-write
  storageClassName: nfs-storage
  resources:
    requests:
      storage: 500Gi

Use cases:

  • Shared file storage (web content, user uploads)
  • Content management systems
  • Applications that need shared writable storage
  • Collaboration tools

Limitations:

  • Only supported by network file systems (NFS, cloud file storage)
  • Performance is typically slower than RWO
  • Requires careful application design for concurrent writes
  • May need application-level locking for data consistency

Access Mode Selection Guide

Use this decision tree to choose the right access mode:

graph TD A[Need Persistent Storage?] --> B{How many pods need access?} B -->|One pod| C[Use ReadWriteOnce RWO] B -->|Multiple pods| D{Need write access?} D -->|Yes| E[Use ReadWriteMany RWX<br/>Requires NFS or compatible] D -->|No| F[Use ReadOnlyMany ROX] style A fill:#e1f5ff style C fill:#e8f5e9 style E fill:#fff4e1 style F fill:#f3e5f5

Storage Type Support

Not all storage types support all access modes:

Storage TypeRWOROXRWX
AWS EBS
GCE Persistent Disk
Azure Disk
Local Storage
NFS
GlusterFS
CephFS
AWS EFS
Azure Files
GCE Filestore

Multiple Access Modes

You can specify multiple access modes in a PVC. The PV must support at least one of them:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: flexible-pvc
spec:
  accessModes:
    - ReadWriteOnce
    - ReadOnlyMany  # Will bind to PV that supports either
  storageClassName: standard
  resources:
    requests:
      storage: 50Gi

However, once bound, the actual access mode is determined by what the PV supports.

Real-World Examples

Database (RWO)

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: postgres-data
spec:
  accessModes:
    - ReadWriteOnce  # Database needs exclusive access
  storageClassName: fast-ssd
  resources:
    requests:
      storage: 200Gi
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: postgres
spec:
  serviceName: postgres
  replicas: 1  # Single instance with RWO
  template:
    spec:
      containers:
      - name: postgres
        image: postgres:14
        volumeMounts:
        - name: data
          mountPath: /var/lib/postgresql/data
  volumeClaimTemplates:
  - metadata:
      name: data
    spec:
      accessModes:
        - ReadWriteOnce
      storageClassName: fast-ssd
      resources:
        requests:
          storage: 200Gi

Shared Configuration (ROX)

apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:
  config.yaml: |
    database: postgres
    cache: redis
---
# Using ConfigMap is better, but if you need a large volume:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: shared-config
spec:
  accessModes:
    - ReadOnlyMany  # Multiple pods read configuration
  storageClassName: standard
  resources:
    requests:
      storage: 1Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: app
spec:
  replicas: 3  # Multiple replicas sharing config
  template:
    spec:
      containers:
      - name: app
        image: myapp:latest
        volumeMounts:
        - name: config
          mountPath: /etc/app
          readOnly: true
      volumes:
      - name: config
        persistentVolumeClaim:
          claimName: shared-config

Shared Content (RWX)

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: web-content
spec:
  accessModes:
    - ReadWriteMany  # Multiple pods write content
  storageClassName: nfs-storage
  resources:
    requests:
      storage: 500Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-server
spec:
  replicas: 5  # Multiple replicas sharing content
  template:
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        volumeMounts:
        - name: content
          mountPath: /usr/share/nginx/html
      volumes:
      - name: content
        persistentVolumeClaim:
          claimName: web-content

Access Mode Mismatch

If a PVC requests an access mode that no available PV supports, the PVC will remain in Pending state:

# Check PVC status
kubectl get pvc
NAME      STATUS    VOLUME   CAPACITY   ACCESS MODES
my-pvc    Pending                                      # Stuck because no PV matches

# Check events
kubectl describe pvc my-pvc
# Events:
#   Warning  ProvisioningFailed  no volume plugin matched

Solutions:

  1. Create a StorageClass that supports the required access mode
  2. Use a storage backend that supports the access mode (e.g., NFS for RWX)
  3. Change the access mode in the PVC to match available storage

Best Practices

  1. Use RWO by default - It’s the most widely supported and performant option
  2. Only use RWX when necessary - It requires network storage and has performance implications
  3. Consider alternatives - For read-only shared data, consider ConfigMaps instead of ROX volumes
  4. Match access mode to use case - Don’t request RWX if you only need RWO (better performance)
  5. Test access patterns - Verify that your storage backend supports the access mode you need
  6. Document requirements - Document why a specific access mode is needed
  7. Plan for scaling - Consider how access modes affect horizontal scaling

Troubleshooting

PVC Stuck in Pending

If a PVC is stuck because of access mode mismatch:

  1. Check available StorageClasses: kubectl get storageclass
  2. Verify StorageClass supports the access mode
  3. Check PVC events: kubectl describe pvc <name>
  4. Consider using a different storage backend that supports your access mode

Multiple Pods Need Write Access

If multiple pods need write access but you’re using RWO:

  1. Consider if RWX is truly needed (often RWO per pod is sufficient)
  2. Use StatefulSets with individual PVCs per pod (RWO per pod)
  3. Use a storage backend that supports RWX (NFS, cloud file storage)
  4. Consider application architecture changes to reduce shared write requirements

See Also