【问题标题】:How to mount HostPath Volume in Kubernetes with SELinux如何使用 SELinux 在 Kubernetes 中挂载 HostPath 卷
【发布时间】:2018-12-02 16:34:02
【问题描述】:

我正在尝试将 hostPath volume 挂载到 Kubernetes Pod 中。下面显示了hostPath 卷规范的示例,该示例取自文档。我正在部署到运行 RHEL 7 并启用 SELinux 的主机。

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

当我的 Pod 尝试读取从底层主机挂载的文件时,我收到“权限被拒绝”错误。当我运行 setenforce 0 关闭 SELinux 时,错误消失了,我可以访问该文件。当我将目录绑定到 Docker 容器时,我得到了同样的错误。

here 中描述了该问题,并且在使用 Docker 时,可以通过使用 Docker 文档here 中描述的zZ 绑定挂载标志来修复。

虽然我可以通过运行来解决问题

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

我认为这是一个令人讨厌的 hack,因为我需要在我的 Kubernetes 集群中的每台主机上执行此操作,还因为我在 YAML 规范中描述的 Kubernetes 部署并没有完整描述它需要做什么完成以使我的 YAML 正确运行。关闭 SELinux 不是一种选择。

我可以看到 Kubernetes 在文档 here 中提到了 SELinux 安全上下文,但我无法成功地将 hostPath 卷挂载到 pod 中而不会出现权限被拒绝错误。

YAML 需要什么样的外观才能成功使容器能够从运行 SELinux 的底层主机挂载 HostPath 卷?

更新:

我正在访问的文件是具有以下标签的 CA 证书:

system_u:object_r:cert_t:s0

当我使用以下选项时:

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

然后通过ausearch -m avc -ts recent检查访问控制审计错误,我可以看到容器的级别标签为s0:c123,c456的权限被拒绝错误,因此我可以看到级别标签有效。我已将标签设置为s0

但是,如果我尝试将type 标签更改为cert_t,则容器甚至无法启动,出现错误:

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

我似乎无法更改容器的类型标签。

【问题讨论】:

    标签: docker kubernetes rhel selinux


    【解决方案1】:

    您可以尝试使用完全权限:

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

    【讨论】:

    • 这确实有效,谢谢,但它现在涉及强制我的容器作为特权容器运行,就安全性而言,这远非理想。 seLinuxOptions 周围有没有一个选项可以在不使容器特权的情况下工作?
    • 是的,我知道。我相信这与 SELinux 配置有关。您是否考虑到以下限制?:Note: To assign SELinux labels, the SELinux security module must be loaded on the host operating system.
    • 是的 - 所以如果我在seLinuxOptions 中设置一个level 并通过ausearch -m abc -ts recent 查看访问错误,我可以看到我可以更改容器的级别,但我看不到更改容器的type。我想我需要同时做这两件事才能获得访问权限。
    • @John 我看到了与您的观察相似(如果不相同)的东西,即虽然我可以让我的容器在特定的 SELinux 类型下运行。我安装的卷没有重新标记为这种类型。现在看这有点道理,因为这些将是进程类型而不是文件类型。
    【解决方案2】:

    您可以使用seLinuxOptions 分配 SELinux 标签:

    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: # it may don’t have the desired effect
            level: "s0:c123,c456"
      securityContext:
        seLinuxOptions:
          level: "s0:c123,c456"
      volumes:
      - name: test-volume
        hostPath:
          # directory location on host
          path: /data
          # this field is optional
          type: Directory
    

    根据documentation

    感谢Phil 指出这一点。根据issue comment,它似乎只在Pod.spec.securityContext 中工作

    • seLinuxOptions:支持 SELinux 标签的卷被重新标记为可以通过 seLinuxOptions 下指定的标签访问。通常您只需要设置级别部分。这会设置多类别安全 (MCS) 标签赋予 Pod 中的所有容器以及卷

    【讨论】:

    • 这对我不起作用,我收到一个 Permission denied 错误,这可归因于 SELinux。是否需要配置其他内容才能使其正常工作?
    • 这将设置 SELinux 上下文级别。但我无法将此解决方案扩展到还包括seLinuxOptions.type。虽然容器进程正确地假定了这个type。卷不会用这种类型重新标记。
    • 我已经提供了an answer,它更详细地描述了这一点
    【解决方案3】:

    扩展 the answer from VAS,因为它部分正确:

    在重新标记hostPath 卷指向的路径目标时,您只能指定 SELinux 标签的级别部分。这是由securityContext 中指定的seLinuxOptions.level 属性自动完成的。

    但是,seLinuxOptions.type 等属性目前对卷重新标记没有影响。在撰写本文时,这仍然是open issue within Kubernetes

    【讨论】:

      猜你喜欢
      • 2018-01-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-25
      • 1970-01-01
      • 2020-03-17
      • 2017-07-24
      • 2018-10-04
      相关资源
      最近更新 更多