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