,

无根 Podman 用户命名空间通俗易懂

在我个人看来,用户命名空间是无根容器中最令人费解的概念之一。可以说,与 Kubernetes 一样,学习曲线相当陡峭。在本文中,我将尝试为新的 Podman 用户(以及转换者)降低这个坡度,用一个易于理解的比喻。希望这将有助于防止任何重要的脑浆从你的耳朵里流出来。

我假设你刚接触容器(一般而言),特别是 无根 Podman(即作为普通、普通、非特权用户操作)。虽然从技术上来说,你使用 Podman 的方式并不重要——直接在 命令行 上、通过 podman-remote 远程访问、podman-machine、在像 podman-desktop 这样的 GUI 中,或者在像 Cockpit 这样的 WebUI 中。我将要说明的基本概念基本上是普遍适用的。

首先,关于命名空间的一些背景信息。与 容器镜像cgroups 一样,命名空间是容器的基本组成部分。有几种不同的命名空间,涵盖了网络、存储和进程树等方面。你可以将命名空间想象成房子里的基础设施。一栋房子有自己的电力系统、管道、排水系统等。它们都是独立的、单用途的,但由国家或某些公用事业公司提供和管理。

继续这个类比,房屋基础设施以受控的方式与公用事业服务交互。换句话说,从一栋房子到另一栋房子,存在着某种程度的核算和隔离。例如,电表分别记录用量,一栋房子的故障不会影响另一栋房子。在公用事业之间也存在有用的隔离,这样,排水管堵塞不会导致熔断器(或断路器)失效。

每项公用事业服务代表一种不同的命名空间,(如果还不明显)房屋代表容器。公用事业公司(或国家)对服务的监督和管理代表了主机系统的命名空间交互。为了帮助理解用户命名空间,让我们将这个类比扩展到人类居住者及其不断表达想法的需求。由于从出生起每个人现在都有一部手机,每个人都可以轻松地彼此沟通。然而,孩子们很难记住长号码。因此,为了进行跨家庭的通信,让我们发明一个快捷系统,其中每个人都被分配了一个短号码,与他们的手机号码分开。

作为进一步的便利,让我们使用号码零作为快速联系电话公司(房屋外部)的方式。而拨打房屋内部的零则连接到负责支付电话费的人。例如,小比利可以拨打零给妈妈打电话,妈妈可以拨打零要求对比利过多的短信发送进行限制。

如果你仍然能理解,你会意识到我们现在已经创建了一些主要的麻烦:人们的手机号码和快捷号码可能会重叠。换句话说,手机号码 123 和快捷号码 123 之间没有明显的区别,但结果可能因一个房子与另一个房子的人数而大不相同。更糟糕的是,拨打零来投诉垃圾邮件,你会在快捷号码和手机号码上得到截然不同的结果。说到这里,让我们通过简单地将所有家庭电话限制为只能拨打快捷号码来解决垃圾邮件问题,完全阻止房屋内部访问更广泛的蜂窝网络。

至于号码歧义问题,一个可能显而易见的解决方案似乎是有一本电话簿记录每个人的姓名、手机号码和快捷号码。然而,电话簿实际上会使问题更糟,因为不同房屋中可能有人共享相同的姓名和快捷号码。相反,让我们为每个房屋保留一个记录,该记录保留一组独占的(未使用的)手机号码。然后,每个房屋可以使用一个简单的转换方案将快捷号码转换为这些保留的手机号码,从而使电话公司满意。此外,如果一个房屋成员以某种方式设法破解了系统并在更广泛的蜂窝网络上拨打电话,他们将被阻止,因为他们的手机号码属于未使用的范围。

这一切都变得有点抽象,所以让我们用一个简单的例子。位于贝克街 221B 的房子可能会获得 1000-1999 的保留(未使用的)手机号码来支持快捷号码。在房子里,如果华生有快捷号码 3,它将在房子外面转换为(未使用的)手机号码 1002。此外,这栋房子的快捷号码零将直接转换为分配给夏洛克的手机号码(同样,在房子外面)。这样,电话公司就可以完全模仿用于其他公用事业的隔离和隔离类型。通信局限于每个房屋内部,所有房屋之间存在高度隔离。

回到主机和容器的现实世界,你可以将这个手机和快捷方式的类比直接应用于无根用户命名空间。你在 /etc/subuid/etc/subgid 中看到的三个值描述了主机上未使用的 ID 的保留范围,这些范围将被分配用于在容器内部进行转换。每个 subuid/subgid 行上的第一个项目是将在容器内部转换为 ID 零的用户(或组)的名称。第二个数字是主机上未使用的 ID 范围的起始位置,后面跟着分配的范围的长度。

因此,根据上面的贝克街示例,这些主机文件中的一个条目(一个是用于 UID,另一个是用于 GID)可能是 sherlock:1000:999。这意味着由夏洛克启动的容器将拥有一个根用户(UID/GID 零),该用户由主机上的夏洛克 ID(无论它是什么)表示。容器内部的后续 UID/GID(例如华生)将简单地(按顺序)转换为从 1000 开始的主机上的未使用范围。由于华生在容器中的 ID 是 3,所以他在容器外部被分配了 ID 1002。如果容器中的 ID 试图超过 999,系统将简单地抛出错误——因为主机端的 ID 分配在 1999 处停止。再次强调,这里关键是 UID(和/或 GID)1000-1999 没有被主机上的任何东西使用——保持系统上所有用户命名空间的隔离。

在真实主机上,你通常会在 /etc/subuid/etc/subgid 中找到更大的值。通常,范围长度将设置为 65536,因为大多数 Linux 容器镜像将需要该最小值。无论如何,请记住这些类比,你将能够很好地理解容器命名空间的概念。特别是,快捷方式到手机号码的转换方案完全反映了用户命名空间的工作原理。当你准备好进一步巩固这些概念时,我强烈推荐 Dan Walsh 关于控制用户命名空间访问的博客文章。之后,为了获得更实际的示例,Dan 的文章 在无根容器上处理用户命名空间和 SELinux 也非常好。

发表评论

订阅

使用您的电子邮件地址注册,以便从本网站接收电子邮件更新。


类别


搜索