用户命名空间:对运行有状态 Pod 的支持进入 Alpha 阶段!

2023年 9月 21日 55.4k 0

作者: Rodrigo Campos Catelin (Microsoft), Giuseppe Scrivano (Red Hat), Sascha Grunert (Red Hat)

译者: Xin Li (DaoCloud)

Kubernetes v1.25 引入用户命名空间(User Namespace)特性,仅支持无状态(Stateless)Pod。
Kubernetes 1.28 在 1.27 的基础上中进行了一些改进后,取消了这一限制。

此特性的精妙之处在于:

  • 使用起来很简单(只需在 Pod 规约(spec)中设置一个 bool)
  • 大多数应用程序不需要任何更改
  • 通过大幅度加强容器的隔离性以及应对评级为高(HIGH)和关键(CRITICAL)的 CVE 来提高安全性。

这篇文章介绍了用户命名空间的基础知识,并展示了:

  • 最近的 Kubernetes v1.28 版本中出现的变化
  • 一个评级为高(HIGH)的漏洞的演示(Demo),该漏洞无法在用户命名空间中被利用
  • 使用此特性的运行时要求
  • 关于用户命名空间的未来版本中可以期待的内容

用户命名空间是什么?

用户命名空间是 Linux 的一项特性,它将容器的用户和组标识符(UID 和 GID)与宿主机上的标识符隔离开来。
容器中的标识符可以映射到宿主机上的标识符,其中用于不同容器的主机 UID/GID 从不重叠。
更重要的是,标识符可以映射到宿主机上的非特权、非重叠的 UID 和 GID。这基本上意味着两件事:

  • 由于不同容器的 UID 和 GID 映射到宿主机上不同的 UID 和 GID,因此即使它们逃逸出了容器的边界,也很难相互攻击。
    例如,如果容器 A 在宿主机上使用与容器 B 不同的 UID 和 GID 运行,则它可以对容器 B
    的文件和进程执行的操作受到限制:只能读/写允许其他人使用的文件,
    因为它永远不会拥有所有者或组的权限(宿主机上的 UID/GID 保证对于不同的容器是不同的)。
  • 由于 UID 和 GID 映射到宿主机上的非特权用户,如果容器逃逸出了容器边界,
    即使它在容器内以 root 身份运行,它在宿主机上也没有特权。
    这极大地保护了它可以读/写哪些宿主机文件、可以向哪个进程发送信号等。

此外,所授予的权能(Capability)仅在用户命名空间内有效,而在宿主机上无效。

在不使用用户命名空间的情况下,以 root 身份运行的容器在发生逃逸的情况下会获得节点上的
root 权限。如果某些权能被授予容器,那么这些权能在主机上也有效。
当使用用户命名空间时,这些情况都会被避免(当然,除非存在漏洞 🙂)。

1.28 版本的变化

正如之前提到的,从 1.28 版本开始,Kubernetes 支持有状态的 Pod 的用户命名空间。
这意味着具有用户命名空间的 Pod 可以使用任何类型的卷,不再仅限于以前的部分卷类型。

从 1.28 版本开始,用于激活此特性的特性门控已被重命名,不再是 UserNamespacesStatelessPodsSupport
而应该使用 UserNamespacesSupport。此特性经历了许多更改,
对节点主机的要求也发生了变化。因此,Kubernetes 1.28 版本将该特性标志重命名以反映这一变化。

演示

Rodrigo 创建了一个利用 CVE 2022-0492 的演示,
用以展现如何在没有用户命名空间的情况下利用该漏洞。
他还展示了在容器使用了此特性的 Pod 中无法利用此漏洞的情况。

此漏洞被评为高危,允许一个没有特殊特权的容器读/写宿主机上的任何路径,并在宿主机上以 root 身份启动进程。

如今,容器中的大多数应用程序都以 root 身份运行,或者以半可预测的非 root
用户身份运行(用户 ID 65534 是一个比较流行的选择)。
当你运行某个 Pod,而其中带有使用用户名命名空间(userns)的容器时,Kubernetes
以非特权用户身份运行这些容器,无需在你的应用程序中进行任何更改。

这意味着两个以用户 65534 身份运行的容器实际上会被映射到宿主机上的不同用户,
从而限制了它们在发生逃逸的情况下能够对彼此执行的操作,如果它们以 root 身份运行,
宿主机上的特权也会降低到非特权用户的权限。

节点系统要求

要使用此功能,对 Linux 内核版本以及容器运行时有一定要求。

在 Linux上,你需要 Linux 6.3 或更高版本。这是因为该特性依赖于一个名为
idmap mounts 的内核特性,而 Linux 6.3 中合并了针对 tmpfs 使用 idmap mounts 的支持

如果你使用 CRI-O 与 crun,这一特性在 CRI-O 1.28.1 和 crun 1.9 或更高版本中受支持。
如果你使用 CRI-O 与 runc,目前仍不受支持。

containerd 对此的支持目前设定的目标是 containerd 2.0;不管你是否与 crun 或 runc 一起使用,或许都不重要。

请注意,containerd 1.7 添加了对用户命名空间的实验性支持,正如在 Kubernetes 1.25
和 1.26 中实现的那样。1.27 版本中进行的重新设计不受 containerd 1.7 支持,
因此它在用户命名空间支持方面仅适用于 Kubernetes 1.25 和 1.26。

containerd 1.7 存在的一个限制是,在 Pod 启动期间需要更改容器镜像中每个文件和目录的所有权。
这意味着它具有存储开销,并且可能会显著影响容器启动延迟。containerd 2.0
可能会包括一个实现,可以消除增加的启动延迟和存储开销。如果计划在生产中使用
containerd 1.7 与用户命名空间,请考虑这一点。

这些 Containerd 限制均不适用于 [CRI-O 1.28][CRIO 版本]。

接下来?

展望 Kubernetes 1.29,计划是与 SIG Auth 合作,将用户命名空间集成到 Pod 安全标准(PSS)和 Pod 安全准入中。
目前的计划是在使用用户命名空间时放宽 Pod 安全标准(PSS)策略中的检查。这意味着如果使用用户命名空间,那么字段
spec[.*].securityContextrunAsUserrunAsNonRootallowPrivilegeEscalation和capabilities
将不会触发违规,此行为可能会通过使用 API Server 特性门控来控制,比如 UserNamespacesPodSecurityStandards 或其他类似的。

我该如何参与?

你可以通过以下方式与 SIG Node 联系:

  • Slack:#sig-node
  • Mailing list
  • Open Community Issues/PRs

你还可以直接联系我们:

  • GitHub:@rata @giuseppe @saschagrunert
  • Slack:@rata @giuseppe @sascha

相关文章

KubeSphere 部署向量数据库 Milvus 实战指南
探索 Kubernetes 持久化存储之 Longhorn 初窥门径
征服 Docker 镜像访问限制!KubeSphere v3.4.1 成功部署全攻略
那些年在 Terraform 上吃到的糖和踩过的坑
无需 Kubernetes 测试 Kubernetes 网络实现
Kubernetes v1.31 中的移除和主要变更

发布评论