Kubernetes v1.36:Kubernetes 中的用户命名空间终于正式可用

原文链接:https://kubernetes.io/blog/2026/04/23/kubernetes-v1-36-userns-ga/

经过数年的开发,Kubernetes 中的用户命名空间(User Namespaces)支持在 v1.36 版本中达到正式发布(GA)阶段。这是一个仅适用于 Linux 的功能。

对于从事底层容器运行时和无根(rootless)技术的我们来说,这是一个期待已久的里程碑。我们终于达到了可以为 Kubernetes 工作负载使用“无根”安全隔离的阶段。

该功能还启用了一种关键模式:以特权运行工作负载,同时仍被限制在用户命名空间内。当设置 hostUsers: false 时,像 CAP_NET_ADMIN 这样的能力(capability)会变成命名空间化的,这意味着它们授予对容器本地资源的管理权限,而不会影响宿主机。这实际上开启了之前无法实现的新用例,而无需运行完全特权的容器。

UID 0 的问题

在容器内以 root 身份运行的进程,在内核看来也是宿主机上的 root。如果攻击者设法逃逸出容器(无论是通过内核漏洞还是配置错误的挂载),他们在宿主机上就是 root。

虽然运行容器有许多安全措施,但这些措施并不会改变进程的底层身份,它仍然具有 root 的某些“部分”。

引擎:ID 映射挂载

走向 GA 的过程不仅仅是关于 Kubernetes API,更是关于让内核为我们工作。在早期阶段,最大的障碍之一是卷的所有权。如果你将容器映射到一个高 UID 范围,Kubelet 必须递归地对附加卷中的每个文件执行 chown,以便容器能够读取/写入它们。对于大型卷来说,这是一个非常昂贵的操作,会严重破坏启动性能。

关键推动因素是 ID 映射挂载(ID-mapped mounts)(在 Linux 5.12 中引入,并在后续版本中完善)。内核不是在磁盘上重写文件所有权,而是在挂载时进行重映射。

当卷被挂载到启用了用户命名空间的 Pod 中时,内核会对 UID(用户 ID)和 GID(组 ID)进行透明转换。对于容器来说,文件看起来是由 UID 0 拥有的。在磁盘上,文件所有权保持不变——无需 chown。这是一个 O(1) 操作,即时且高效。

在 Kubernetes v1.36 中使用

使用用户命名空间很简单:你只需要在 Pod 规范中设置 hostUsers: false。无需更改容器镜像,也无需复杂配置。接口与 Alpha 阶段引入的相同。在 Pod(或 PodTemplate)的 spec 中,你明确选择退出宿主机用户命名空间:

apiVersion: v1
kind: Pod
metadata:
  name: isolated-workload
spec:
  hostUsers: false
  containers:
  - name: app
    image: fedora:42
    securityContext:
      runAsUser: 0

关于用户命名空间(user namespaces)在实际中的工作原理以及被评为 HIGH 严重等级的 CVE 缓解演示的更多详细信息,请参阅之前的博客文章:用户命名空间 alpha用户命名空间有状态 Pod alpha用户命名空间 beta 以及用户命名空间默认启用

参与贡献

如果你对用户命名空间感兴趣或希望贡献代码,以下是一些有用的链接:

致谢

这一特性历经多年才得以实现:首个 KEP 由其他贡献者在 10 年前提出,而我们在过去 6 年中一直积极推动。我们要感谢所有在 SIG Node、容器运行时以及 Linux 内核中做出贡献的人。特别感谢那些在多个 alpha 和 beta 周期中帮助塑造设计的审阅者和早期采用者