2.14. 在 Linux 用户命名空间中运行 pod
Linux 用户命名空间允许管理员隔离容器用户和组标识符 (UID 和 GID),以便容器可以在用户命名空间中拥有与它运行的主机系统不同的权限集。这允许容器在用户命名空间中以完全特权运行容器,但对主机上的操作可以以非特权运行这些进程。
默认情况下,容器在主机系统的 root 用户命名空间中运行。当容器需要仅在该用户命名空间中可用的功能时,在主机用户命名空间中运行容器很有用。但是,这会引入一些安全问题,如容器逃逸问题(container breakout)- 容器中的一个进程会逃逸到主机中,这个进程将可以访问或修改主机上的文件。
在独立用户命名空间中运行容器可以缓解容器逃逸的问题,以及其他可能会被破坏的容器对其他 pod 和节点本身造成影响的安全漏洞。
您可以通过将 pod 规格中的 hostUsers
参数设置为 false
来配置 Linux 用户命名空间,如以下步骤所示。
对 Linux 用户命名空间的支持只是一个技术预览功能。技术预览功能不受红帽产品服务等级协议(SLA)支持,且功能可能并不完整。红帽不推荐在生产环境中使用它们。这些技术预览功能可以使用户提早试用新的功能,并有机会在开发阶段提供反馈意见。
有关红帽技术预览功能支持范围的更多信息,请参阅技术预览功能支持范围。
2.14.1. 配置 Linux 用户命名空间支持
先决条件
您可以通过编辑名为
cluster
的FeatureGate
CR 为集群启用所需的技术预览功能:$ oc edit featuregate cluster
FeatureGate
CR 示例apiVersion: config.openshift.io/v1 kind: FeatureGate metadata: name: cluster spec: featureSet: TechPreviewNoUpgrade 1
- 1
- 启用所需的
UserNamespacesSupport
和ProcMountType
功能。
警告在集群中启用
TechPreviewNoUpgrade
功能集无法撤消,并会阻止次版本更新。此功能集允许您在测试集群中启用这些技术预览功能,您可以在测试集群中完全测试它们。不要在生产环境集群中启用此功能。保存更改后,会创建新的机器配置,然后更新机器配置池,并在应用更改时在每个节点上调度。
您在 worker 节点上启用了 crun 容器运行时。crun 是目前发布的唯一一个支持用户命名空间的 OCI 运行时。
apiVersion: machineconfiguration.openshift.io/v1 kind: ContainerRuntimeConfig metadata: name: enable-crun-worker spec: machineConfigPoolSelector: matchLabels: pools.operator.machineconfiguration.openshift.io/worker: "" 1 containerRuntimeConfig: defaultRuntime: crun 2
流程
运行以下命令,编辑部署 pod 的 OpenShift Container Platform 命名空间的默认用户 ID (UID) 和组 ID (GID) 范围:
$ oc edit ns/<namespace_name>
命名空间示例
apiVersion: v1 kind: Namespace metadata: annotations: openshift.io/description: "" openshift.io/display-name: "" openshift.io/requester: system:admin openshift.io/sa.scc.mcs: s0:c27,c24 openshift.io/sa.scc.supplemental-groups: 1000/10000 1 openshift.io/sa.scc.uid-range: 1000/10000 2 # ... name: userns # ...
注意范围 1000/10000 代表以 ID 1000 开始的 10,000 个值,因此它指定了从 1000 到 10,999 的 ID 范围。
通过创建一个配置为使用
restricted
配置集运行,并将hostUsers
参数设置为false
的 pod 来启用 Linux 用户命名空间。创建一个类似以下示例的 YAML 文件:
pod 规格示例
apiVersion: v1 kind: Pod metadata: name: userns-pod # ... spec: containers: - name: userns-container image: registry.access.redhat.com/ubi9 command: ["sleep", "1000"] securityContext: capabilities: drop: ["ALL"] allowPrivilegeEscalation: false 1 runAsNonRoot: true 2 seccompProfile: type: RuntimeDefault runAsUser: 1000 3 runAsGroup: 1000 4 hostUsers: false 5 # ...
运行以下命令来创建 pod:
$ oc create -f <file_name>.yaml
验证
检查您创建的 pod 容器中使用的 pod 用户和组 ID。pod 位于 Linux 用户命名空间中。
使用您的 pod 中的容器启动一个 shell 会话:
$ oc rsh -c <container_name> pod/<pod_name>
示例命令
$ oc rsh -c userns-container_name pod/userns-pod
显示在容器内使用的用户和组 ID:
sh-5.1$ id
输出示例
uid=1000(1000) gid=1000(1000) groups=1000(1000)
显示容器用户命名空间中使用的用户 ID:
sh-5.1$ lsns -t user
输出示例
NS TYPE NPROCS PID USER COMMAND 4026532447 user 3 1 1000 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 1000 1
- 1
- 进程的 UID 是
1000
,这与您在 pod 规格中设置的相同。
检查创建 pod 的节点上使用的 pod 用户 ID。节点位于 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-q8sh9
将
/host
设置为 debug shell 中的根目录:sh-5.1# chroot /host
显示节点用户命名空间中使用的用户 ID:
sh-5.1# lsns -t user
示例命令
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 1
- 1
- 进程的 UID 是
2908816384
,它与您在容器集规格中设置的不同。