<p>If anyone comes across this later I resolved my issue by using an <code>initContainer</code> for any Pod that needed to write to the file system.</p>
<p>For example:</p>
<pre class="lang-yaml prettyprint-override"><code>apiVersion: v1
kind: Pod
metadata:
  name: app3
spec:
  containers:
  - name: app3
    image: busybox
    command: [&quot;/bin/sh&quot;]
    args: [&quot;-c&quot;, &quot;while true; do echo $(date -u) &gt;&gt; /data/out3.txt; sleep 5; done&quot;]
    volumeMounts:
    - name: persistent-storage
      mountPath: /data
    securityContext:
      runAsGroup: 1337
  initContainers:
  - name: fs-owner-change
    image: busybox
    command:
    - chown
    - &quot;root:1337&quot;
    - &quot;/efs-fs&quot;
    volumeMounts:
    - mountPath: /efs-fs
      name: persistent-storage
  securityContext:
    fsGroup: 1337
  volumes:
  - name: persistent-storage
    persistentVolumeClaim:
      claimName: efs-claim
</code></pre>
<p>The rest of the definitions match what was in my question.</p>
<hr />
<p>Working sort of off what @JerryChen suggested (&quot;use access points&quot;) I discovered that things were simpler if I just used a <a href="https://github.com/kubernetes-sigs/aws-efs-csi-driver/tree/master/examples/kubernetes/dynamic_provisioning" rel="nofollow noreferrer">dynamically provisioned EFS</a> which does utilize EFS access points to allow shared access to an EFS instance. Below is the StorageClass, PersistentVolumeClaim, and an example Pod.</p>
<pre class="lang-yaml prettyprint-override"><code>kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: efs-sc
provisioner: efs.csi.aws.com
parameters:
  provisioningMode: efs-ap
  fileSystemId:  {{ .Values.efsVolumeHandle }}
  directoryPerms: &quot;775&quot;
reclaimPolicy: Retain
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: efs-claim
spec:
  accessModes:
    - ReadWriteMany
  storageClassName: efs-sc
  resources:
    requests:
      storage: 5Gi  # Not actually used - see https://aws.amazon.com/blogs/containers/introducing-efs-csi-dynamic-provisioning/
---
apiVersion: v1
kind: Pod
metadata:
  name: app3
spec:
  containers:
  - name: app3
    image: busybox
    command: [&quot;/bin/sh&quot;]
    args: [&quot;-c&quot;, &quot;while true; do echo $(date -u) &gt;&gt; /data/out3.txt; sleep 5; done&quot;]
    volumeMounts:
    - name: persistent-storage
      mountPath: /data
  securityContext:
    runAsUser: 1000
    runAsGroup: 1337
    fsGroup: 1337
  volumes:
  - name: persistent-storage
    persistentVolumeClaim:
      claimName: efs-claim
</code></pre>
<p>Note the <code>directoryPerms</code> (775) specified in the StorageClass, as well as the <code>runAsGroup</code> and <code>fsGroup</code> specified in the Pod. When utilizing this PVC in a Pod that runs as a non-root user shared a user group number is the key.</p>
<p><code>runAsUser</code> was only used to ensure the busybox command was executed by a non-root user.</p>
<p>This is likely leagues better than brute-forcing the file system permissions using an <code>initContainer</code></p>

CC BY-SA 4.0
2021-05-17T21:20:32.470Z
2022-01-18T19:42:56.600Z
2022-01-18T19:42:56.600Z
R. Arctor
<p>You should try the access point in EFS, <a href="https://docs.aws.amazon.com/efs/latest/ug/efs-access-points.html" rel="nofollow noreferrer">https://docs.aws.amazon.com/efs/latest/ug/efs-access-points.html</a></p>
<p>It enforces an operating system user and group, and a directory for every file system request made through the access point.</p>
<p>In other words, you can set the path as uid 1337 and gid 1337.</p>

CC BY-SA 4.0
2021-05-18T09:32:38.887Z
2021-05-18T09:32:38.887Z
Jerry Chen
<p>I am having trouble configuring a statically provisioned EFS such that multiple pods, which run as a non-root user, can read and write the file system.</p>
<p>I am using the AWS EFS CSI Driver. My version info is as follows:</p>
<pre><code>Client Version: version.Info{Major:&quot;1&quot;, Minor:&quot;18&quot;, GitVersion:&quot;v1.18.18&quot;, GitCommit:&quot;6f6ce59dc8fefde25a3ba0ef0047f4ec6662ef24&quot;, GitTreeState:&quot;clean&quot;, BuildDate:&quot;2021-04-15T03:31:30Z&quot;, GoVersion:&quot;go1.13.15&quot;, Compiler:&quot;gc&quot;, Platform:&quot;linux/amd64&quot;}
Server Version: version.Info{Major:&quot;1&quot;, Minor:&quot;18+&quot;, GitVersion:&quot;v1.18.9-eks-d1db3c&quot;, GitCommit:&quot;d1db3c46e55f95d6a7d3e5578689371318f95ff9&quot;, GitTreeState:&quot;clean&quot;, BuildDate:&quot;2020-10-20T22:53:22Z&quot;, GoVersion:&quot;go1.13.15&quot;, Compiler:&quot;gc&quot;, Platform:&quot;linux/amd64&quot;}
</code></pre>
<p>I followed the example from the github repo (<a href="https://github.com/kubernetes-sigs/aws-efs-csi-driver/tree/master/examples/kubernetes/multiple_pods" rel="nofollow noreferrer">https://github.com/kubernetes-sigs/aws-efs-csi-driver/tree/master/examples/kubernetes/multiple_pods</a>) updating the volumeHandle appropriately. The busybox containers defined in the specs for the example are able to read and write the file system, but when I add the same PVC to a pod which does not run as the root user the pod is unable to write to the mounted EFS.
I have tried a couple other things to get this working as I expected it to:</p>
<ul>
<li>just applying the annotation described here: <a href="https://kubernetes.io/docs/tasks/configure-pod-container/configure-persistent-volume-storage/#access-control" rel="nofollow noreferrer">https://kubernetes.io/docs/tasks/configure-pod-container/configure-persistent-volume-storage/#access-control</a> to the persistent volume definition.</li>
<li>applying the aforementioned annotation and including securityContext.runAsGroup to the pod definition (with the appropriate value)</li>
<li>applying the annotation, the runAsGroup, as well as fsGroup for the Pod</li>
</ul>
<p>None of these configurations allowed a non-root user to write to the mounted EFS.
What am I missing in terms of configuring a statically provisioned EFS so that multiple pods, all of which run as a non-root user, can read and write in the mounted EFS?</p>
<p>For reference here are the pod definitions:</p>
<pre class="lang-yaml prettyprint-override"><code>apiVersion: v1
kind: Pod
metadata:
  name: app1
spec:
  containers:
  - name: app1
    image: busybox
    command: [&quot;/bin/sh&quot;]
    args: [&quot;-c&quot;, &quot;while true; do echo $(date -u) &gt;&gt; /data/out1.txt; sleep 5; done&quot;]
    volumeMounts:
    - name: persistent-storage
      mountPath: /data
  volumes:
  - name: persistent-storage
    persistentVolumeClaim:
      claimName: efs-claim
---
apiVersion: v1
kind: Pod
metadata:
  name: app2
spec:
  containers:
  - name: app2
    image: busybox
    command: [&quot;/bin/sh&quot;]
    args: [&quot;-c&quot;, &quot;while true; do echo $(date -u) &gt;&gt; /data/out2.txt; sleep 5; done&quot;]
    volumeMounts:
    - name: persistent-storage
      mountPath: /data
  volumes:
  - name: persistent-storage
    persistentVolumeClaim:
      claimName: efs-claim
---
apiVersion: v1
kind: Pod
metadata:
  name: app3
spec:
  containers:
  - name: app3
    image: busybox
    command: [&quot;/bin/sh&quot;]
    args: [&quot;-c&quot;, &quot;while true; do echo $(date -u) &gt;&gt; /data/out3.txt; sleep 5; done&quot;]
    volumeMounts:
    - name: persistent-storage
      mountPath: /data
  securityContext:
    runAsUser: 1000
    runAsGroup: 1337
    fsGroup: 1337
  volumes:
  - name: persistent-storage
    persistentVolumeClaim:
      claimName: efs-claim
</code></pre>
<p>And the SC/PVC/PV:</p>
<pre class="lang-yaml prettyprint-override"><code>kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: efs-sc
provisioner: efs.csi.aws.com
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: efs-claim
spec:
  accessModes:
    - ReadWriteMany
  storageClassName: efs-sc
  resources:
    requests:
      storage: 5Gi  
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: efs-pv
  annotations:
    pv.beta.kubernetes.io/gid: {{ .Values.groupId | quote }}
spec:
  capacity:
    storage: 5Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteMany
  persistentVolumeReclaimPolicy: Retain
  storageClassName: efs-sc
  csi:
    driver: efs.csi.aws.com
    volumeHandle: fs-asdf123
</code></pre>

<kubernetes><kubernetes-helm>
How to allow a non-root user to write to a mounted EFS in EKS
R. Arctor
# How to allow a non-root user to write to a mounted EFS in EKS

(Asked by: username_0 on 2021-05-17)

I am having trouble configuring a statically provisioned EFS such that multiple pods, which run as a non-root user, can read and write the file system.
I am using the AWS EFS CSI Driver. My version info is as follows:
Client Version: version.Info{Major:"1", Minor:"18", GitVersion:"v1.18.18", GitCommit:"6f6ce59dc8fefde25a3ba0ef0047f4ec6662ef24", GitTreeState:"clean", BuildDate:"2021-04-15T03:31:30Z", GoVersion:"go1.13.15", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"18+", GitVersion:"v1.18.9-eks-d1db3c", GitCommit:"d1db3c46e55f95d6a7d3e5578689371318f95ff9", GitTreeState:"clean", BuildDate:"2020-10-20T22:53:22Z", GoVersion:"go1.13.15", Compiler:"gc", Platform:"linux/amd64"}

I followed the example from the github repo (https://github.com/kubernetes-sigs/aws-efs-csi-driver/tree/master/examples/kubernetes/multiple_pods) updating the volumeHandle appropriately. The busybox containers defined in the specs for the example are able to read and write the file system, but when I add the same PVC to a pod which does not run as the root user the pod is unable to write to the mounted EFS.
I have tried a couple other things to get this working as I expected it to:

just applying the annotation described here: https://kubernetes.io/docs/tasks/configure-pod-container/configure-persistent-volume-storage/#access-control to the persistent volume definition.
applying the aforementioned annotation and including securityContext.runAsGroup to the pod definition (with the appropriate value)
applying the annotation, the runAsGroup, as well as fsGroup for the Pod

None of these configurations allowed a non-root user to write to the mounted EFS.
What am I missing in terms of configuring a statically provisioned EFS so that multiple pods, all of which run as a non-root user, can read and write in the mounted EFS?
For reference here are the pod definitions:
apiVersion: v1
kind: Pod
metadata:
  name: app1
spec:
  containers:
  - name: app1
    image: busybox
    command: ["/bin/sh"]
    args: ["-c", "while true; do echo $(date -u) >> /data/out1.txt; sleep 5; done"]
    volumeMounts:
    - name: persistent-storage
      mountPath: /data
  volumes:
  - name: persistent-storage
    persistentVolumeClaim:
      claimName: efs-claim
---
apiVersion: v1
kind: Pod
metadata:
  name: app2
spec:
  containers:
  - name: app2
    image: busybox
    command: ["/bin/sh"]
    args: ["-c", "while true; do echo $(date -u) >> /data/out2.txt; sleep 5; done"]
    volumeMounts:
    - name: persistent-storage
      mountPath: /data
  volumes:
  - name: persistent-storage
    persistentVolumeClaim:
      claimName: efs-claim
---
apiVersion: v1
kind: Pod
metadata:
  name: app3
spec:
  containers:
  - name: app3
    image: busybox
    command: ["/bin/sh"]
    args: ["-c", "while true; do echo $(date -u) >> /data/out3.txt; sleep 5; done"]
    volumeMounts:
    - name: persistent-storage
      mountPath: /data
  securityContext:
    runAsUser: 1000
    runAsGroup: 1337
    fsGroup: 1337
  volumes:
  - name: persistent-storage
    persistentVolumeClaim:
      claimName: efs-claim

And the SC/PVC/PV:
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: efs-sc
provisioner: efs.csi.aws.com
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: efs-claim
spec:
  accessModes:
    - ReadWriteMany
  storageClassName: efs-sc
  resources:
    requests:
      storage: 5Gi  
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: efs-pv
  annotations:
    pv.beta.kubernetes.io/gid: {{ .Values.groupId | quote }}
spec:
  capacity:
    storage: 5Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteMany
  persistentVolumeReclaimPolicy: Retain
  storageClassName: efs-sc
  csi:
    driver: efs.csi.aws.com
    volumeHandle: fs-asdf123

**Tags:** kubernetes, kubernetes-helm


---

## 2 answers

### Answer by username_0 on 2021-05-17. Score: 1 | Accepted answer

If anyone comes across this later I resolved my issue by using an initContainer for any Pod that needed to write to the file system.
For example:
apiVersion: v1
kind: Pod
metadata:
  name: app3
spec:
  containers:
  - name: app3
    image: busybox
    command: ["/bin/sh"]
    args: ["-c", "while true; do echo $(date -u) >> /data/out3.txt; sleep 5; done"]
    volumeMounts:
    - name: persistent-storage
      mountPath: /data
    securityContext:
      runAsGroup: 1337
  initContainers:
  - name: fs-owner-change
    image: busybox
    command:
    - chown
    - "root:1337"
    - "/efs-fs"
    volumeMounts:
    - mountPath: /efs-fs
      name: persistent-storage
  securityContext:
    fsGroup: 1337
  volumes:
  - name: persistent-storage
    persistentVolumeClaim:
      claimName: efs-claim

The rest of the definitions match what was in my question.

Working sort of off what @JerryChen suggested ("use access points") I discovered that things were simpler if I just used a dynamically provisioned EFS which does utilize EFS access points to allow shared access to an EFS instance. Below is the StorageClass, PersistentVolumeClaim, and an example Pod.
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: efs-sc
provisioner: efs.csi.aws.com
parameters:
  provisioningMode: efs-ap
  fileSystemId:  {{ .Values.efsVolumeHandle }}
  directoryPerms: "775"
reclaimPolicy: Retain
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: efs-claim
spec:
  accessModes:
    - ReadWriteMany
  storageClassName: efs-sc
  resources:
    requests:
      storage: 5Gi  # Not actually used - see https://aws.amazon.com/blogs/containers/introducing-efs-csi-dynamic-provisioning/
---
apiVersion: v1
kind: Pod
metadata:
  name: app3
spec:
  containers:
  - name: app3
    image: busybox
    command: ["/bin/sh"]
    args: ["-c", "while true; do echo $(date -u) >> /data/out3.txt; sleep 5; done"]
    volumeMounts:
    - name: persistent-storage
      mountPath: /data
  securityContext:
    runAsUser: 1000
    runAsGroup: 1337
    fsGroup: 1337
  volumes:
  - name: persistent-storage
    persistentVolumeClaim:
      claimName: efs-claim

Note the directoryPerms (775) specified in the StorageClass, as well as the runAsGroup and fsGroup specified in the Pod. When utilizing this PVC in a Pod that runs as a non-root user shared a user group number is the key.
runAsUser was only used to ensure the busybox command was executed by a non-root user.
This is likely leagues better than brute-forcing the file system permissions using an initContainer


---

### Answer by username_1 on 2021-05-18. Score: 1

You should try the access point in EFS, <https://docs.aws.amazon.com/efs/latest/ug/efs-access-points.html>

It enforces an operating system user and group, and a directory for every file system request made through the access point.

In other words, you can set the path as uid 1337 and gid 1337.


---

