--- title: 为 Pod 配置 user 名字空间 reviewers: content_type: task weight: 210 min-kubernetes-server-version: v1.25 --- {{< feature-state feature_gate_name="UserNamespacesSupport" >}} 本页展示如何为 Pod 配置 user 名字空间。可以将容器内的用户与主机上的用户隔离开来。 在容器中以 root 用户运行的进程可以以不同的(非 root)用户在宿主机上运行;换句话说, 进程在 user 名字空间内部拥有执行操作的全部特权,但在 user 名字空间外部并没有执行操作的特权。 你可以使用这个特性来减少有害的容器对同一宿主机上其他容器的影响。 [有些安全脆弱性问题][KEP-vulns]被评为 **HIGH** 或 **CRITICAL**,但当 user 名字空间被启用时, 它们是无法被利用的。相信 user 名字空间也能减轻一些未来的漏洞影响。 在不使用 user 名字空间的情况下,对于以 root 用户运行的容器而言,发生容器逃逸时, 容器将拥有在宿主机上的 root 特权。如果容器被赋予了某些权限,则这些权限在宿主机上同样有效。 当使用 user 名字空间时这些都不可能发生。 [KEP-vulns]: https://github.com/kubernetes/enhancements/tree/217d790720c5aef09b8bd4d6ca96284a0affe6c2/keps/sig-node/127-user-namespaces#motivation ## {{% heading "prerequisites" %}} {{< include "task-tutorial-prereqs.md" >}} {{< version-check >}} {{% thirdparty-content single="true" %}} * 节点的操作系统必须为 Linux * 你需要在宿主机上执行命令 * 你需要能够通过 exec 操作进入 Pod * 你需要启用 `UserNamespacesSupport` [特性门控](/zh-cn/docs/reference/command-line-tools-reference/feature-gates/) {{< note >}} 在 user 名字空间原来仅支持无状态的 Pod 时,启用 user 名字空间的特性门控先前被命名为 `UserNamespacesStatelessPodsSupport`。 只有 Kubernetes v1.25 到 v1.27 才能识别 `UserNamespacesStatelessPodsSupport`。 {{}} 你所使用的集群**必须**包括至少一个符合 [要求](/zh-cn/docs/concepts/workloads/pods/user-namespaces/#before-you-begin) 的节点,以便为 Pod 配置 user 名字空间。 如果你有混合节点,并且只有部分节点支持为 Pod 配置 user 名字空间, 你还需要确保配置了 user 名字空间的 Pod 被[调度](/zh-cn/docs/concepts/scheduling-eviction/assign-pod-node/)到合适的节点。 ## 运行一个使用 user 名字空间的 Pod {#create-pod} 为一个 Pod 启用 user 名字空间需要设置 `.spec` 的 `hostUsers` 字段为 `false`。例如: {{% code_sample file="pods/user-namespaces-stateless.yaml" %}} 1. 在你的集群上创建 Pod: ```shell kubectl apply -f https://k8s.io/examples/pods/user-namespaces-stateless.yaml ``` 2. 挂接到容器上并执行 `readlink /proc/self/ns/user`: ```shell kubectl attach -it userns bash ``` 运行这个命令: ```shell readlink /proc/self/ns/user ``` 输出类似于: ```shell user:[4026531837] ``` 还运行: ```shell cat /proc/self/uid_map ``` 输出类似于: ```shell 0 833617920 65536 ``` 然后,在主机中打开一个 Shell 并运行相同的命令。 `readlink` 命令显示进程运行所在的用户命名空间。在主机上和容器内运行时应该有所不同。 容器内 `uid_map` 文件的最后一个数字必须是 65536,在主机上它必须是更大的数字。 如果你在 user 名字空间中运行 kubelet,则需要将在 Pod 中运行命令的输出与在主机中运行的输出进行比较: ```shell readlink /proc/$pid/ns/user ``` 使用 kubelet 的进程号代替 `$pid`。