2.17. 在 Linux 用户命名空间中运行 pod
Linux 用户命名空间允许管理员隔离容器用户和组标识符 (UID 和 GID),以便容器可以在用户命名空间中拥有与它运行的主机系统不同的权限集。这允许容器在用户命名空间中以完全特权运行容器,但对主机上的操作可以以非特权运行这些进程。
默认情况下,容器在主机用户命名空间中运行。当容器需要一个只在主机命名空间中可用的功能时,在主机用户命名空间中运行容器会很有用。但是,这会引入一些安全问题,如容器逃逸问题(container breakout)- 容器中的一个进程会逃逸到主机中,这个进程将可以访问或修改主机上的文件。
在独立用户命名空间中运行容器可以缓解容器逃逸的问题,以及其他可能会被破坏的容器对其他 pod 和节点本身造成影响的安全漏洞。
当在隔离的用户命名空间中运行 pod 时,pod 容器中的 UID/GID 不再与主机上的 UID/GID 匹配。为了文件系统所有权正常工作,Linux 内核使用 ID 映射挂载,它会在虚拟文件系统(VFS)层中转换容器和主机之间的用户 ID。
并非所有文件系统目前都支持 ID 映射挂载,如网络文件系统(NFS)和其他网络/分布式文件系统。任何从不支持 ID 映射挂载的供应商使用 NFS 支持的持久性卷的 pod 可能会在用户命名空间中运行时遇到访问或权限问题。此行为不特定于 OpenShift Container Platform。它适用于 Kubernetes v1.33 以后的所有 Kubernetes 发行版。
2.17.1. 配置 Linux 用户命名空间支持 复制链接链接已复制到粘贴板!
您可以通过在 pod spec 中将 hostUsers 参数设置为 false 来配置 Linux 用户命名空间,以及一些其他配置,如以下步骤所示。
在用户命名空间中运行工作负载时,可以安全地为安全上下文约束(SCC)字段配置 RunAsAny,如 fsGroup、runAsGroup、runAsUser 和 supplementalGroups,因为容器外部的 UID 或 GID 与内部的不同,由这些字段表示。
为获得额外的安全性,您可以使用 restricted-v3 或 nested-container SCC,这专门为 Linux 用户命名空间中的工作负载设计。SCC 中的 userNamespaceLevel: RequirePodLevel 字段要求工作负载在用户命名空间中运行。如需有关 SCC 的更多信息,请参阅"管理安全性上下文约束"。
要请求特定的 SCC 用于工作负载,您可以使用 oc adm policy add-scc-to-user 或 oc adm policy add-scc-to-group 命令将 SCC 添加到特定的用户或组。如需更多信息,请参阅"OpenShift CLI 管理员命令参考"。
另外,您还可以选择使用 pod 规格中的 procMount 参数将 pod 中的 /proc 文件系统配置为 unmasked。将 /proc 设置为 unmasked,这通常被视为是安全的,绕过容器运行时的默认掩码行为,并且仅与 hostUsers 设为 false 的 SCC 一起使用。
流程
运行以下命令,编辑部署 pod 的 OpenShift Container Platform 命名空间的默认用户 ID (UID) 和组 ID (GID) 范围:
oc edit ns/<namespace_name>
$ oc edit ns/<namespace_name>Copy to Clipboard Copied! Toggle word wrap Toggle overflow 命名空间示例
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 注意范围 1000/10000 代表以 ID 1000 开始的 10,000 个值,因此它指定了从 1000 到 10,999 的 ID 范围。
通过创建配置为使用适当的 SCC 运行的工作负载来启用 Linux 用户命名空间,并将
hostUsers参数设置为false。创建一个类似以下示例的 YAML 文件:
pod 规格示例
Copy to Clipboard Copied! Toggle word wrap Toggle overflow - 1
- 指定要用于此工作负载的 SCC。
- 2
- 指定 pod 是否在用户命名空间中运行。如果为
false,则 pod 在为 pod 创建的新用户命名空间中运行。如果为true,则 pod 在主机用户命名空间中运行。默认值是true。 - 3
capabilities允许特权操作,而不提供完整的 root 访问权限。从技术上讲,在用户命名空间内设置功能比设置它们更安全,因为能力的范围受用户命名空间的限制,通常被视为安全。但是,为任何不受信任的工作负载提供CAP_SYS_ADMIN等 pod 功能可能会增加容器化进程可访问的潜在内核面区域,并可以发现利用这个漏洞。因此,在 pod 安全准入中的baseline级别允许用户命名空间中的功能。- 4
- 指定进程在容器内运行,带有 UID 不是 0 的用户。
- 5
- 可选:指定用于容器的 proc 挂载类型。
unmasked值可确保容器的/proc文件系统被容器进程以读写模式挂载。默认值为Default。 - 6
- 指定在容器内运行的进程的用户 ID。这必须属于您在
namespace对象中设置的范围。 - 7
- 指定在容器内运行的进程的组 ID。这必须属于您在
namespace对象中设置的范围。
运行以下命令来创建对象:
oc create -f <file_name>.yaml
$ oc create -f <file_name>.yamlCopy to Clipboard Copied! Toggle word wrap Toggle overflow
验证
检查您创建的 pod 中容器使用的用户和组 ID。pod 位于 Linux 用户命名空间中。
使用您的 pod 中的容器启动一个 shell 会话:
oc rsh -c <container_name> pod/<pod_name>
$ oc rsh -c <container_name> pod/<pod_name>Copy to Clipboard Copied! Toggle word wrap Toggle overflow 示例命令
oc rsh -c userns-container_name pod/userns-pod
$ oc rsh -c userns-container_name pod/userns-podCopy to Clipboard Copied! Toggle word wrap Toggle overflow 显示在容器内使用的用户和组 ID:
id
sh-5.1$ idCopy to Clipboard Copied! Toggle word wrap Toggle overflow 输出示例
uid=1000(1000) gid=1000(1000) groups=1000(1000)
uid=1000(1000) gid=1000(1000) groups=1000(1000)1 Copy to Clipboard Copied! Toggle word wrap Toggle overflow - 1
- 容器的 UID 和组应当与您在 pod 规格中设置的相同。
显示容器用户命名空间中使用的用户 ID:
lsns -t user
sh-5.1$ lsns -t userCopy to Clipboard Copied! Toggle word wrap Toggle overflow 输出示例
NS TYPE NPROCS PID USER COMMAND 4026532447 user 3 1 1000 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 1000
NS TYPE NPROCS PID USER COMMAND 4026532447 user 3 1 1000 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 10001 Copy to Clipboard Copied! Toggle word wrap Toggle overflow - 1
- 进程的 UID 应与您在 pod 规格中设置的相同。
检查节点使用的 UID。节点位于 Linux 用户命名空间之外。此用户 ID 应该与容器中使用的 UID 不同。
为该节点启动一个 debug 会话:
oc debug node/ci-ln-z5vppzb-72292-8zp2b-worker-c-q8sh9
$ oc debug node/ci-ln-z5vppzb-72292-8zp2b-worker-c-q8sh9Copy to Clipboard Copied! Toggle word wrap Toggle overflow 示例命令
oc debug node/ci-ln-z5vppzb-72292-8zp2b-worker-c-q8sh9
$ oc debug node/ci-ln-z5vppzb-72292-8zp2b-worker-c-q8sh9Copy to Clipboard Copied! Toggle word wrap Toggle overflow 将
/host设置为 debug shell 中的根目录:chroot /host
sh-5.1# chroot /hostCopy to Clipboard Copied! Toggle word wrap Toggle overflow 显示节点使用的 UID:
lsns -t user
sh-5.1# lsns -t userCopy to Clipboard Copied! Toggle word wrap Toggle overflow 示例命令
NS TYPE NPROCS PID USER COMMAND 4026531837 user 233 1 root /usr/lib/systemd/systemd --switched-root --system --deserialize 28 4026532447 user 1 4767 2908816384 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 1000
NS TYPE NPROCS PID USER COMMAND 4026531837 user 233 1 root /usr/lib/systemd/systemd --switched-root --system --deserialize 28 4026532447 user 1 4767 2908816384 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 10001 Copy to Clipboard Copied! Toggle word wrap Toggle overflow - 1
- UID 应该与您在 pod 规格中设置的内容不同。
使用以下命令退出 debug 会话:
exit
sh-5.1# exitCopy to Clipboard Copied! Toggle word wrap Toggle overflow exit
sh-5.1# exitCopy to Clipboard Copied! Toggle word wrap Toggle overflow
检查
/proc文件系统是否作为unmasked挂载到容器中,如以下命令输出中的读/写权限(rw):oc exec <pod_name> -- mount | grep /proc
$ oc exec <pod_name> -- mount | grep /procCopy to Clipboard Copied! Toggle word wrap Toggle overflow 输出示例
proc on /proc type proc (rw,nosuid,nodev,noexec,relatime)
proc on /proc type proc (rw,nosuid,nodev,noexec,relatime)Copy to Clipboard Copied! Toggle word wrap Toggle overflow