本文发表于一年多前。旧文章可能包含过时内容。请检查页面中的信息自发布以来是否已变得不正确。
Kubernetes 1.27:高效的 SELinux 卷重新标记(Beta)
问题所在
在启用了安全增强型 Linux(SELinux)的 Linux 系统上,传统上是由容器运行时为 Pod 及其所有卷应用 SELinux 标签。Kubernetes 只是将 Pod 的 securityContext 字段中的 SELinux 标签传递给容器运行时。
然后,容器运行时会递归地更改 Pod 容器可见的所有文件上的 SELinux 标签。如果卷上有大量文件,这可能会非常耗时,特别是当卷位于远程文件系统上时。
说明
如果容器使用卷的subPath,则只有整个卷的那个 subPath 会被重新打上标签。这允许两个拥有不同 SELinux 标签的 Pod 使用同一个卷,只要它们使用不同的子路径即可。如果一个 Pod 在 Kubernetes API 中没有分配任何 SELinux 标签,容器运行时会分配一个唯一的随机标签,这样,一个可能逃逸出容器边界的进程就无法访问主机上任何其他容器的数据。容器运行时仍然会用这个随机的 SELinux 标签递归地重新标记所有 Pod 卷。
使用挂载选项进行改进
如果一个 Pod 及其卷满足以下**所有**条件,Kubernetes 将直接使用正确的 SELinux 标签来**挂载**该卷。这样的挂载将在恒定时间内完成,容器运行时将无需递归地为卷上的任何文件重新打标签。
操作系统必须支持 SELinux。
如果未检测到 SELinux 支持,kubelet 和容器运行时不会执行任何与 SELinux 相关的操作。
特性门控
ReadWriteOncePod和SELinuxMountReadWriteOncePod必须被启用。这些特性门控在 Kubernetes 1.27 中是 Beta 版,在 1.25 中是 Alpha 版。如果这些特性门控中的任何一个被禁用,SELinux 标签将总是由容器运行时通过递归遍历卷(或其 subPath)来应用。
Pod 必须在其 Pod Security Context 中至少分配了
seLinuxOptions.level,或者所有 Pod 容器必须在其 Security Contexts 中设置了它。Kubernetes 将从操作系统的默认值(通常是system_u、system_r和container_t)中读取默认的user、role和type。如果 Kubernetes 不知道至少 SELinux 的
level,容器运行时将在卷挂载**后**分配一个随机的 level。在这种情况下,容器运行时仍将递归地为卷重新打标签。该卷必须是访问模式为
ReadWriteOncePod的 Persistent Volume。这是初始实现的限制。如上所述,两个 Pod 可以拥有不同的 SELinux 标签,并且仍然使用同一个卷,只要它们使用不同的
subPath即可。当卷是以 SELinux 标签**挂载**时,这种用例是不可能的,因为整个卷都被挂载了,而且大多数文件系统不支持使用多个 SELinux 标签多次挂载同一个卷。如果在你的部署中,必须运行两个具有不同 SELinux 上下文的 Pod 并使用同一卷的不同
subPath,请在 KEP issue 中发表评论(或对任何现有评论点赞——最好不要重复)。当该特性扩展到所有卷访问模式时,这样的 Pod 可能无法运行。负责该卷的卷插件或 CSI 驱动程序支持使用 SELinux 挂载选项进行挂载。
这些树内(in-tree)卷插件支持使用 SELinux 挂载选项进行挂载:
fc、iscsi和rbd。支持使用 SELinux 挂载选项的 CSI 驱动程序必须在其 CSIDriver 实例中通过设置
seLinuxMount字段来声明这一点。由其他卷插件或未设置
seLinuxMount: true的 CSI 驱动程序管理的卷,将由容器运行时进行递归的重新打标签。
使用 SELinux 上下文挂载
当满足所有上述条件时,kubelet 会将 -o context=<SELinux 标签> 挂载选项传递给卷插件或 CSI 驱动程序。CSI 驱动程序供应商必须确保其 CSI 驱动程序支持此挂载选项,并且在必要时,CSI 驱动程序会附加其他使 -o context 生效所需的挂载选项。
例如,NFS 可能需要 -o context=<SELinux 标签>,nosharecache,这样从同一个 NFS 服务器挂载的每个卷都可以有不同的 SELinux 标签值。类似地,CIFS 可能需要 -o context=<SELinux 标签>,nosharesock。
CSI 驱动程序供应商有责任在启用 SELinux 的环境中测试其 CSI 驱动程序,然后再在 CSIDriver 实例中设置 seLinuxMount: true。
我如何了解更多信息?
容器中的 SELinux:请参阅 Daniel J Walsh 撰写的优秀的 SELinux 可视化指南。请注意,该指南比 Kubernetes 更早,它以虚拟机为例描述了**多类别安全**(MCS)模式,然而,类似的概念也用于容器。
请参阅一系列博客文章,了解容器运行时如何精确地将 SELinux 应用于容器的详细信息
阅读 KEP:使用挂载加速 SELinux 卷的重新打标签