3 min read | by Jordi Prats
As a best practice we should try run containers with the minimum privileges they require: If we want to run a container with a non-root user we need to specify the user we want to use with securityContext.runAsUser (unless the container is not already using a non-privileged user).
By doing so when working with Volumes we might get a Permission denied while accessing the container
We can reproduce this problem by running the following StatefulSet that will use a PersistentVolume for /test:
apiVersion: apps/v1 kind: StatefulSet metadata: name: sts-test-volume-runasuser spec: serviceName: default replicas: 1 selector: matchLabels: component: test-volume volumeClaimTemplates: - metadata: name: test-volume labels: component: test-volume spec: accessModes: [ "ReadWriteOnce" ] volumeMode: Filesystem resources: requests: storage: 10Gi template: metadata: labels: component: test-volume spec: securityContext: runAsUser: 1000 containers: - name: test-container image: "alpine:latest" command: - sleep - 24h volumeMounts: - mountPath: /test name: test-volume
You can find all the yaml files on the pet2cattle/kubernetes-volume-fsgroup repository on GitHub.
If we try to create a file on the Volume we are going to get a Permission denied error:
$ kubectl exec -it sts-test-volume-runasuser-0 -n test -- touch /test/permissions touch: /test/permissions: Permission denied command terminated with exit code 1
Because the Volume is mounted as root
$ kubectl exec -it sts-test-volume-runasuser-0 -n test -- ls -ld /test drwxr-xr-x 3 root root 4096 Feb 18 04:48 /test
To be able to access the volume we'll need to use the securityContext.fsGroup. By using it, all processes of the container are also part of the supplementary group we set (So it doesn't need to be the same as runAsGroup)
apiVersion: apps/v1 kind: StatefulSet metadata: name: sts-test-volume-runasuser-fsgroup spec: serviceName: default replicas: 1 selector: matchLabels: component: test-volume volumeClaimTemplates: - metadata: name: test-volume labels: component: test-volume spec: accessModes: [ "ReadWriteOnce" ] volumeMode: Filesystem resources: requests: storage: 10Gi template: metadata: labels: component: test-volume spec: securityContext: runAsUser: 1000 fsGroup: 1000 containers: - name: test-container image: "alpine:latest" command: - sleep - 24h volumeMounts: - mountPath: /test name: test-volume
Now we are going to be allowed to create a file on the Volume:
$ kubectl exec -it sts-test-volume-runasuser-fsgroup-0 -n test -- touch /test/permissions $ kubectl exec -it sts-test-volume-runasuser-fsgroup-0 -n test -- ls -l /test/permissions -rw-r--r-- 1 1000 1000 0 Feb 18 04:50 /test/permissions
We can check how the /test Volume group's is the to securityContext.fsGroup:
$ kubectl exec -it sts-test-volume-runasuser-fsgroup-0 -n test -- ls -ld /test drwxrwsr-x 3 root 1000 4096 Feb 18 04:50 /test
Posted on 18/02/2022