Write permissions on volume mount with security context fsgroup option

6/22/2021

I'm trying to run a tomcat container in K8S with a non-root user, to do so I set User 'tomcat' with the appropriate permission in Docker Image. I have a startup script that creates a directory in /opt/var/logs (during container startup) and also starts tomcat service.

#steps in Dockerfile
#adding tomcat user and group and permission to /opt directory
addgroup tomcat -g 1001 && \
adduser -D -u 1001 -G tomcat tomcat && \
chown -R tomcat:tomcat /opt

#switch user
User tomcat

The pod runs fine in K8S when deployed using deployment without any volume mapped.

But I get a permission denied error (permission denied: creating directory /opt/var/logs/docker/<appname>) from the startup script, which fails to create a directory when I map the deployment with the persistent volume claim, even though I set the fsgroup as explained here, https://kubernetes.io/docs/tasks/configure-pod-container/security-context/.

I have a persistent volume of type hostPath.

The deployment definition is as below.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: ms-tomcat
  namespace: ms-ns
  labels:
    app: tomcat
spec:
  selector:
    matchLabels:
      app: tomcat
  template:
    metadata:
      labels:
        app: tomcat
    spec:
      securityContext:
          fsGroup: 2000
          runAsUser: 1001
          runAsGroup: 1001
      containers:
      - name: tomcat
        image: docker-registry.test.com/tomcat:1.2
        volumeMounts:
        - name: logging-volume
          mountPath: /opt/var/logs/docker
      imagePullSecrets:
      - name: test
      volumes:
      - name: logging-volume
        persistentVolumeClaim:
          claimName: nonroot-test-pvc

PVC

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name:  nonroot-test-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 2Gi
  storageClassName: local-node-sc
  volumeName: nonroot-test-pv
-- mansing shinde
kubernetes

1 Answer

6/22/2021

You need to set the fsGroup to 1001 which is the runAsGroup.

When any volume mount in any path, by default the owner of the mounted directory is root. you can't change the owner of the mounted path in K8s world. But In k8S You have permission to set the group ID with FsGroup. With FsGroup you actually give the permission for a certain user group.

As your current user UID is 1001 and GID is 1001 so you need to give the permission for current GID 1001.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: ms-tomcat
  namespace: ms-ns
  labels:
    app: tomcat
spec:
  selector:
    matchLabels:
      app: tomcat
  template:
    metadata:
      labels:
        app: tomcat
    spec:
      securityContext:
          fsGroup: 1001 #<--- change here
          runAsUser: 1001
          runAsGroup: 1001
      containers:
      - name: tomcat
        image: docker-registry.test.com/tomcat:1.2
        volumeMounts:
        - name: logging-volume
          mountPath: /opt/var/logs/docker
      imagePullSecrets:
      - name: test
      volumes:
      - name: logging-volume
        persistentVolumeClaim:
          claimName: nonroot-test-pvc
-- Emon46
Source: StackOverflow