How to mount HostPath Volume in Kubernetes with SELinux

6/23/2018

I am trying to mount a hostPath volume into a Kubernetes Pod. An example of a hostPath volume specification is shown below, which is taken from the docs. I am deploying to hosts that are running RHEL 7 with SELinux enabled.

apiVersion: v1
kind: Pod
metadata:
  name: test-pd
spec:
  containers:
  - image: k8s.gcr.io/test-webserver
    name: test-container
    volumeMounts:
    - mountPath: /test-pd
      name: test-volume
  volumes:
  - name: test-volume
    hostPath:
      # directory location on host
      path: /data
      # this field is optional
      type: Directory

When my Pod tries to read from a file that has been mounted from the underlying host, I get a "Permission Denied" error. When I run setenforce 0 to turn off SELinux, the error goes away and I can access the file. I get the same error when I bind mount a directory into a Docker container.

The issue is described here and, when using Docker, can be fixed by using the z or Z bind mount flag, described in the Docker docs here.

Whilst I can fix the issue by running

chcon -Rt svirt_sandbox_file_t /path/to/my/host/dir/to/mount

I see this as a nasty hack, as I need to do this on every host in my Kubernetes cluster and also because my deployment of Kubernetes as described in the YAML spec is not a complete description of what it is that needs to be done to get my YAML to run correctly. Turning off SELinux is not an option.

I can see that Kubernetes mentions SELinux security contexts in the docs here, but I haven't been able to successfully mount a hostPath volume into a pod without getting the permission denied error.

What does the YAML need to look like to successfully enable a container to mount a HostPath volume from an underlying host that is running SELinux?

Update:

The file I am accessing is a CA certificate that has these labels:

system_u:object_r:cert_t:s0

When I use the following options:

securityContext:
  seLinuxOptions:
    level: "s0:c123,c456"

and then check the access control audit errors via ausearch -m avc -ts recent, I can see that there is a permission denied error where the container has a level label of s0:c123,c456, so I can see that the level label works. I have set the label to be s0.

However, if I try to change the type label to be cert_t, the container doesn't even start, there's an error :

container_linux.go:247: starting container process caused "process_linux.go:364: container init caused \"write /proc/self/task/1/attr/exec: invalid argument\""

I don't seem to be able to change the type label of the container.

-- John
docker
kubernetes
rhel
selinux

2 Answers

6/25/2018

You can assign SELinux labels using seLinuxOptions:

apiVersion: v1
kind: Pod
metadata:
  name: test-pd
spec:
  containers:
  - image: k8s.gcr.io/test-webserver
    name: test-container
    volumeMounts:
    - mountPath: /test-pd
      name: test-volume
    securityContext:
      seLinuxOptions:
        level: "s0:c123,c456"
  volumes:
  - name: test-volume
    hostPath:
      # directory location on host
      path: /data
      # this field is optional
      type: Directory

According to documentation:

  • seLinuxOptions: Volumes that support SELinux labeling are relabeled to be accessible by the label specified under seLinuxOptions. Usually you only need to set the level section. This sets the Multi-Category Security (MCS) label given to all Containers in the Pod as well as the Volumes.
-- VAS
Source: StackOverflow

6/23/2018

You could try with full permissions:

 ...
 image: k8s.gcr.io/test-webserver
 securityContext:
   privileged: true
 ...
-- suren
Source: StackOverflow