Kubernetes 1.27:高效的 SELinux 卷重新标记(Beta 版)

作者:Jan Šafránek (Red Hat)

译者:Wilson Wu (DaoCloud)

问题

在启用了 Security-Enhancled Linux(SELinux)系统上,传统做法是让容器运行时负责为 Pod 及所有卷应用 SELinux 标签。 Kubernetes 仅将 SELinux 标签从 Pod 的 securityContext 字段传递给容器运行时。

然后,容器运行时以递归的方式更改 Pod 容器可见的所有文件上的 SELinux 标签。 如果卷上有许多文件,这一过程可能会非常耗时,尤其是当卷位于远程文件系统上时。

如果 Pod 没有从 Kubernetes API 中获得任何 SELinux 标签,则容器运行时会分配一个唯一的随机标签, 因此可能逃离容器边界的进程将无法访问主机上任何其他容器的数据。 容器运行时仍然使用此随机 SELinux 标签递归地重新标记所有 Pod 卷。

使用挂载选项进行改进

如果 Pod 及其卷满足以下所有条件,Kubernetes 将直接使用正确的 SELinux 标签挂载该卷。 这种挂载将在确定时间内完成,容器运行时不需要递归地重新标记其上的任何文件。

  1. 操作系统必须支持 SELinux。

    如果没有检测到 SELinux 支持,kubelet 和容器运行时不会对 SELinux 执行任何操作。

  1. 必须启用特性门控 ReadWriteOncePodSELinuxMountReadWriteOncePod。这些特性门控在 Kubernetes 1.27 中是 Beta 版,在 1.25 中是 Alpha 版。

    禁用这些功能中任何一个后,SELinux 标签将始终由容器运行时通过递归遍历卷(或其 subPath)来应用。

  1. Pod 必须在其 Pod 安全上下文中至少设置 seLinuxOptions.level,或者所有 Pod 容器必须在安全上下文中对其进行设置。 否则 Kubernetes 将从操作系统默认值(通常是 system_usystem_rcontainer_t)中读取默认的 userroletype

    如果 Kubernetes 不了解任何 SELinux level,容器运行时将在卷挂载为其分配一个随机级别。 在这种情况下,容器运行时仍会递归地对卷进行重新标记。

  1. 存储卷必须是访问模式ReadWriteOncePod 的持久卷。

    这是最初的实现的限制。如上所述,两个 Pod 可以具有不同的 SELinux 标签,但仍然使用相同的卷, 只要它们使用不同的 subPath 即可。对于已挂载的带有 SELinux 标签的卷,此场景是无法支持的, 因为整个卷已挂载,并且大多数文件系统不支持使用不同的 SELinux 标签多次挂载同一个卷。

    如果在你的环境中需要使用两个不同的 SELinux 上下文运行两个 Pod 并使用同一卷的不同 subPath, 请在 KEP 问题中发表评论(或对任何现有评论进行投票 - 最好不要重复)。 当此特性扩展到覆盖所有卷访问模式时,这类 Pod 可能无法运行。

  1. 卷插件或负责卷的 CSI 驱动程序支持使用 SELinux 挂载选项进行挂载。

    这些树内卷插件支持使用 SELinux 挂载选项进行挂载:fciscsirbd

    支持使用 SELinux 挂载选项挂载的 CSI 驱动程序必须通过设置 seLinuxMount 字段在其 CSIDriver 实例中声明这一点。

    由其他未设置 seLinuxMount: true 的卷插件或 CSI 驱动程序管理的卷将由容器运行时递归地重新标记。

使用 SELinux 上下文挂载

当满足所有上述条件时,kubelet 会将 -o context=<SELinux label> 挂载选项传递给卷插件或 CSI 驱动程序。 CSI 驱动程序提供者必须确保其 CSI 驱动程序支持此安装选项,并且如有必要,CSI 驱动程序要附加 -o context 所需的其他安装选项。

例如,NFS 可能需要 -o context=<SELinux label>,nosharecache,这样来自同一 NFS 服务器的多个卷被挂载时可以具有不同的 SELinux 标签值。 类似地,CIFS 可能需要 -o context=<SELinux label>,nosharesock

在 CSIDriver 实例中设置 seLinuxMount: true 之前,CSI 驱动程序提供者需要在启用 SELinux 的环境中测试其 CSI 驱动程序。

如何了解更多?

容器中的 SELinux:请参阅 Daniel J Walsh 撰写的可视化 SELinux 指南(英文)。 请注意,该指南早于 Kubernetes,它以虚拟机为例描述了多类别安全(MCS)模式,但是,类似的概念也适用于容器。

请参阅以下系列博客文章,详细了解容器运行时如何将 SELinux 应用于容器:

阅读 KEP:使用挂载加速 SELinux 卷重新标记