How to fix Permission denied accessing volume mount in Kubernetes

KubernetesINTERMEDIATEMEDIUMUpdated Dec 6, 2025ยท 293 views

A container running as a non-root user cannot access a volume because it's owned by root or a different user. Fix by adding fsGroup to the pod's securityContext to grant group-based access, or use init containers to change permissions before the main container starts.

Quick fix

Fixes Permission denied accessing volume mount

apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  securityContext:
    runAsUser: 1000        # Non-root user ID
    fsGroup: 2000          # Supplemental group ID for volume access
  containers:
  - name: app
    image: my-image
    volumeMounts:
    - name: data
      mountPath: /data
  volumes:
  - name: data
    persistentVolumeClaim:
      claimName: my-pvc
  1. Add fsGroup to pod securityContext (primary fix)
  2. For large volumes, use fsGroupChangePolicy to skip slow permission recursion
  3. Align fsGroup with runAsGroup for simpler permission model
  4. Use init containers for NFS or HostPath volumes that don't support fsGroup
kubernetes โ€” error
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
securityContext:
runAsUser: 1000 # Non-root user ID
fsGroup: 2000 # Supplemental group ID for volume access
containers:
- name: app
image: my-image
volumeMounts:
- name: data
mountPath: /data
volumes:
- name: data
persistentVolumeClaim:
claimName: my-pvc
Permission denied accessing volume mount

What this error means

When Kubernetes mounts a volume into a container, file ownership on the volume defaults to the host's root user. If a container runs as a non-root user (via runAsUser in securityContext), it lacks read/write permissions on the mounted files and directories. Kubernetes provides fsGroup as a solution: specifying fsGroup in the pod securityContext tells Kubernetes to automatically change the volume's group ownership to that GID, granting access to containers running as that group. This is a fundamental Linux permissions issue applied to Kubernetes storage.

Typical symptoms

  • Container fails to start with "Permission denied" accessing mounted volumes
  • Application logs show "read-only file system" or "operation not permitted" errors
  • CI/CD pipeline fails at container initialization when trying to write to PVCs
  • Issue only occurs with non-root security context; works fine when running as root
  • Pod startup is very slow, taking minutes instead of seconds (permission recursion on large volumes)
  • Some directories/files accessible, others not (inconsistent permissions)

Common causes

  1. Container running as non-root user (runAsUser) without corresponding fsGroup in securityContext
  2. fsGroup set to wrong GID that doesn't match container's effective GID
  3. Volume owned by different user/group on host with no group overlap
  4. fsGroup not applied to volume type that doesn't support permission changes (HostPath, NFS)
  5. SELinux enforced on host, restricting access regardless of UNIX permissions
  6. Large volume causing slow recursive permission change (Kubernetes 1.19 and earlier)
  7. CSI driver not supporting fsGroup capability (missing VOLUME_MOUNT_GROUP feature)

How to fix "Permission denied accessing volume mount"

1Add fsGroup to pod securityContext (primary fix)

Edit your pod or Deployment manifest to add fsGroup. Kubernetes will automatically change the volume's group ownership, allowing non-root containers to access it:

yaml
apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  securityContext:
    runAsUser: 1000        # Non-root user ID
    fsGroup: 2000          # Supplemental group ID for volume access
  containers:
  - name: app
    image: my-image
    volumeMounts:
    - name: data
      mountPath: /data
  volumes:
  - name: data
    persistentVolumeClaim:
      claimName: my-pvc

Apply the change:

bash
kubectl apply -f pod.yaml

Kubernetes will automatically change the volume's group to GID 2000, allowing the user (UID 1000) to read/write files.

2For large volumes, use fsGroupChangePolicy to skip slow permission recursion

By default, Kubernetes recursively changes permissions on every file in the volume (slow for large volumes). Use fsGroupChangePolicy to skip this if the root directory already has correct permissions (Kubernetes 1.20+):

yaml
apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  securityContext:
    runAsUser: 1000
    fsGroup: 2000
    fsGroupChangePolicy: "OnRootMismatch"  # Only change if root dir doesn't match
  containers:
  - name: app
    image: my-image
    volumeMounts:
    - name: data
      mountPath: /data
  volumes:
  - name: data
    persistentVolumeClaim:
      claimName: my-pvc

For volumes with millions of files, this can reduce startup time from 10+ minutes to seconds.

3Align fsGroup with runAsGroup for simpler permission model

Make the container's primary group match the fsGroup:

yaml
apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  securityContext:
    runAsUser: 1000
    runAsGroup: 1000      # Primary group ID
    fsGroup: 1000         # Must match runAsGroup
  containers:
  - name: app
    image: my-image
    volumeMounts:
    - name: data
      mountPath: /data
  volumes:
  - name: data
    persistentVolumeClaim:
      claimName: my-pvc

This simplifies debugging: files on the volume are owned by UID:GID 1000:1000, and the container runs as the same user.

4Use init containers for NFS or HostPath volumes that don't support fsGroup

Some volume types (NFS, HostPath) don't support automatic permission changes. Use an init container with elevated privileges to fix permissions:

yaml
apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  initContainers:
  - name: fix-permissions
    image: busybox
    command: ['sh', '-c', 'chown -R 1000:2000 /data']
    volumeMounts:
    - name: data
      mountPath: /data
  containers:
  - name: app
    image: my-image
    securityContext:
      runAsUser: 1000
    volumeMounts:
    - name: data
      mountPath: /data
  volumes:
  - name: data
    nfs:
      server: 192.168.1.100
      path: "/exports/data"

The init container runs as root (by default) and changes ownership before the main container starts.

5Verify file ownership on the volume

Check actual ownership to confirm the fix:

bash
# Inside a running container
kubectl exec -it <pod-name> -- ls -la /data

# Expected output for the examples above:
# drwxr-xr-x 1000 2000  (or 1000 1000 if fsGroup=1000)

# Check from outside (if host access available)
kubectl debug -it <pod-name> --image=busybox
ls -la /data

Files should be owned by the fsGroup, and the running user should have read/write permissions.

6For SELinux-enabled systems, configure SELinux labels

If workers have SELinux enforced, additional configuration is needed:

yaml
apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  securityContext:
    runAsUser: 1000
    fsGroup: 2000
    seLinuxOptions:
      level: "s0:c123,c456"
  containers:
  - name: app
    image: my-image
    volumeMounts:
    - name: data
      mountPath: /data
  volumes:
  - name: data
    persistentVolumeClaim:
      claimName: my-pvc

Note: HostPath and NFS don't support SELinux relabeling through seLinuxOptions. For these, configure SELinux policy on the NFS server or mount with -o context=... options.

Advanced notes

fsGroup is fully supported on most volume types (emptyDir, configMap, secret, downwardAPI, projected, and cloud provider volumes like EBS). NFS and HostPath volumes don't support Kubernetes-managed permission changes; configure NFS host exports with matching GIDs or use init containers instead. CSI drivers must declare VOLUME_MOUNT_GROUP capability to support fsGroup; check driver documentation. Kubernetes 1.20+ fsGroupChangePolicy "OnRootMismatch" significantly speeds up large volume mounts by skipping recursive chown if the root directory already has correct permissions. For Azure File Storage, permission management is handled by the storage account, not Kubernetes; volume mount issues there usually require different fixes. SELinux is complex; if using SELinux on workers, consult your SELinux policy team before mounting volumes into restricted contexts. Performance tip: For very large volumes (100k+ files), test fsGroupChangePolicy behavior in non-production first, as behavior varies by storage backend.

Frequently asked questions

What does "Permission denied accessing volume mount" mean?
When Kubernetes mounts a volume into a container, file ownership on the volume defaults to the host's root user. If a container runs as a non-root user (via runAsUser in securityContext), it lacks read/write permissions on the mounted files and directories. Kubernetes provides fsGroup as a solution: specifying fsGroup in the pod securityContext tells Kubernetes to automatically change the volume's group ownership to that GID, granting access to containers running as that group.
How do I fix "Permission denied accessing volume mount"?
A container running as a non-root user cannot access a volume because it's owned by root or a different user. Fix by adding fsGroup to the pod's securityContext to grant group-based access, or use init containers to change permissions before the main container starts.
What causes "Permission denied accessing volume mount"?
Container running as non-root user (runAsUser) without corresponding fsGroup in securityContext fsGroup set to wrong GID that doesn't match container's effective GID Volume owned by different user/group on host with no group overlap
Is the "Permission denied accessing volume mount" error serious?
It is a medium-severity error โ€” more of a blocker than a risk. The steps above resolve it.

Official resources & further reading