Answers: <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>
  
Answers: CC BY-SA 4.0
Answers: 2021-05-17T21:20:32.470Z
Answers: 2022-01-18T19:42:56.600Z
Answers: 2022-01-18T19:42:56.600Z
Answers: R. Arctor
Answers: <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>
  
Answers: CC BY-SA 4.0
Answers: 2021-05-18T09:32:38.887Z
Answers: 2021-05-18T09:32:38.887Z
Answers: Jerry Chen
Body: <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>
  
Tags: <kubernetes><kubernetes-helm>
Title: How to allow a non-root user to write to a mounted EFS in EKS
UserDisplayName: R. Arctor
ThreadText: # 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:
  
  ```yaml
  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:
  
  ```yaml
  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:
  
  ```yaml
  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 @username_1 suggested ("use access points") I discovered that things were simpler if I just used a [dynamically provisioned EFS](https://github.com/kubernetes-sigs/aws-efs-csi-driver/tree/master/examples/kubernetes/dynamic_provisioning) which does utilize EFS access points to allow shared access to an EFS instance. Below is the StorageClass, PersistentVolumeClaim, and an example Pod.
  
  ```yaml
  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.
  
  
  ---
  
  