<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>

R. Arctor
<p>I worked out two ways of resolving this and thought I should update this in case someone else runs into the same problem.</p>
<p>The first, probably better way is to just use 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> PersistentVolume. This way creates an access point in EFS that is shared by all containers that utilize the PersistentVolumeClaim.</p>
<p>Here is an example of the StorageClass, PersistentVolumeClaim, and a pod that utilizes the PVC.</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> is only specified to ensure the <code>busybox</code> stuff does not run as root</p>
<hr />
<p>The second method is what I worked out initially and probably is the &quot;nuclear&quot; option, but does work for statically provisioned EFS.</p>
<p>I have omitted the rest of the pod definition for the sake of brevity. You can use an <code>initContainer</code> to ensure certain permissions are set on the mounted EFS volume.</p>
<pre class="lang-yaml prettyprint-override"><code>      initContainers:
      - name: fs-permission-update
        image: busybox
        command:
        - chown
        - &quot;root:{{ .Values.groupId }}&quot;
        - &quot;/efs-fs&quot;
        volumeMounts:
        - mountPath: /efs-fs
          name: efs-storage
</code></pre>
<p>Again make sure any Pod which mounts the volume and runs as a non-root user uses the <code>fsGroup</code> and <code>runAsGroup</code> to make sure the user is part of the allowed user group.</p>
<hr />
<p>In summary, probably don't use statically provisioned EFS, instead use dynamically provisioned EFS. Note that this is specific to the EFS CSI driver for Kubernetes. Check out the <a href="https://github.com/kubernetes-sigs/aws-efs-csi-driver" rel="nofollow noreferrer">EKS CSI Driver GitHub</a> for more examples and some additional details.</p>
