在 Pod 中使用用户命名空间

特性状态: Kubernetes v1.30 [beta] (默认启用:否)

此页面展示了如何为 Pod 配置用户命名空间。这使你可以将容器内运行的用户与主机上的用户隔离开来。

作为 root 在容器中运行的进程,可以在主机中作为不同的(非 root)用户运行;换句话说,该进程在用户命名空间内执行操作时拥有完全权限,但在命名空间外部执行操作时则为非特权用户。

你可以使用此功能来减少被攻陷的容器对主机或同一节点中其他 Pod 的破坏。当用户命名空间启用时,有一些评级为 HIGHCRITICAL安全漏洞是无法被利用的。用户命名空间也有望缓解未来的一些漏洞。

如果不使用用户命名空间,一个以 root 身份运行的容器,在容器逃逸的情况下,在节点上拥有 root 权限。而且,如果为容器授予了某些权能(capability),这些权能在主机上也是有效的。当使用用户命名空间时,所有这些都不会发生。

准备工作

你需要有一个 Kubernetes 集群,并且 kubectl 命令行工具被配置为与你的集群通信。建议在至少有两个非控制平面主机的节点组成的集群上运行本教程。如果你还没有集群,可以使用 minikube 创建一个,或者使用以下 Kubernetes 演练场之一:

你的 Kubernetes 服务器版本必须是 v1.25 或更高版本。

要检查版本,请输入 kubectl version

  • 节点操作系统需要是 Linux
  • 你需要在主机上执行命令
  • 你需要能够 exec 进入 Pod
  • 你需要启用 UserNamespacesSupport Feature Gate

你正在使用的集群必须包含至少一个满足通过用户命名空间使用 Pod 的要求的节点。

如果你的节点混合使用,并且只有部分节点支持 Pod 的用户命名空间,你还需要确保使用用户命名空间的 Pod 被调度到合适的节点上。

运行使用用户命名空间的 Pod

通过将 .spec 中的 hostUsers 字段设置为 false 来为 Pod 启用用户命名空间。例如:

apiVersion: v1
kind: Pod
metadata:
  name: userns
spec:
  hostUsers: false
  containers:
  - name: shell
    command: ["sleep", "infinity"]
    image: debian
  1. 在你的集群上创建 Pod

    kubectl apply -f https://k8s.io/examples/pods/user-namespaces-stateless.yaml
    
  2. 添加一个调试容器并连接到它,然后运行 readlink /proc/self/ns/user

    kubectl debug userns -it --image=busybox
    

运行此命令

readlink /proc/self/ns/user

输出类似于

user:[4026531837]

也运行

cat /proc/self/uid_map

输出类似于

0  833617920      65536

然后,在主机中打开一个 shell 并运行相同的命令。

readlink 命令显示进程运行在哪个用户命名空间中。在主机中运行和在容器内运行时的输出应该不同。

容器内的 uid_map 文件的最后一个数字必须是 65536,在主机上必须是一个更大的数字。

如果你在用户命名空间内运行 kubelet,你需要将 Pod 中运行命令的输出与主机中运行命令的输出进行比较

readlink /proc/$pid/ns/user

$pid 替换为 kubelet 的 PID。

本页面中的条目引用了为 Kubernetes 提供所需功能的第三方产品或项目。Kubernetes 项目作者对这些第三方产品或项目不负责。有关详细信息,请参阅 CNCF 网站指南

在提议添加额外第三方链接的更改之前,应阅读内容指南

上次修改时间 2024 年 11 月 10 日下午 4:01 (PST): 在用户命名空间示例中更改调试 CLI 命令的 attach 方式 (21b6e349da)