在 Pod 中使用用户命名空间
Kubernetes v1.33 [beta]
(默认启用:true)本页面展示了如何为 Pod 配置用户命名空间。这允许你将容器内部运行的用户与主机上的用户隔离开来。
以 root 用户身份在容器中运行的进程,可以在主机上以不同的(非 root)用户身份运行;换句话说,该进程对用户命名空间内的操作拥有完全权限,但对命名空间外的操作没有特权。
你可以使用此功能来减少受损容器对主机或同一节点中的其他 Pod 造成的损害。有 几项安全漏洞 被评为高危或严重,在用户命名空间激活时是无法利用的。预计用户命名空间在未来也能缓解一些漏洞。
如果不使用用户命名空间,以 root 身份运行的容器在发生容器逃逸时,将对节点拥有 root 权限。如果容器被授予某些功能,这些功能在主机上也是有效的。当使用用户命名空间时,这些都不成立。
准备工作
你需要拥有一个 Kubernetes 集群,并且 kubectl 命令行工具已配置为与你的集群通信。建议在至少有两个不作为控制平面主机的节点的集群上运行本教程。如果你还没有集群,可以使用 minikube 创建一个,或者使用以下 Kubernetes 演练场之一
你的 Kubernetes 服务器版本必须是 v1.25 或更高版本。要检查版本,请输入 kubectl version
。
- 节点操作系统需要是 Linux。
- 你需要在主机中执行命令。
- 你需要能够 exec 进入 Pod。
- 你需要启用
UserNamespacesSupport
特性门控。
注意
此前,当只支持无状态 Pods 时,用于启用用户命名空间的特性门控名为UserNamespacesStatelessPodsSupport
。只有 Kubernetes v1.25 到 v1.27 版本识别 UserNamespacesStatelessPodsSupport
。你正在使用的集群必须包含至少一个满足为 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
在你的集群上创建 Pod
kubectl apply -f https://k8s.io/examples/pods/user-namespaces-stateless.yaml
进入 Pod 并运行
readlink /proc/self/ns/user
kubectl exec -ti userns -- bash
运行此命令
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 网站指南。
在提议添加额外第三方链接的更改之前,你应该阅读内容指南。