了解Podman如何利用用户名称空间在无根模式下运行。
在上一篇有关用户名称空间和Podman的文章中,我讨论了如何使用Podman命令来启动具有不同用户名称空间的不同容器,从而更好地分隔容器。Podman还利用用户名称空间来以无根模式运行。基本上,当非特权用户运行Podman时,该工具将设置并加入用户名称空间。在Podman成为用户名称空间内的root用户后,允许Podman挂载某些文件系统并设置容器。请注意,除了用户可用的其他UID之外,此处没有特权升级,如下所述。
当前大多数Linux发行版都包含一个Shadow-utils版本,该版本使用/ etc / subuid和/ etc / subgid文件来确定用户名称空间中用户可以使用哪些UID和GID。
$ cat /etc/subuid
dwalsh:100000:65536
test:165536:65536
$ cat /etc/subgid
dwalsh:100000:65536
test:165536:65536
添加用户程序自动为添加到系统中的每个用户分配65536个UID。如果系统上已有用户,则需要自己分配UID。这些文件的格式为用户名:STARTUID:TOTALUIDS。在我的情况下,这意味着为dwalsh分配了100000至165535的UID以及我的默认UID,该ID恰好是在/etc/passwd中定义的3265。分配这些UID范围时,请注意它们与系统上的任何实际UID都不重叠。如果您有一个列为UID100001的用户,那么我(dwalsh)将能够成为此UID并可能读取/写入/执行该UID拥有的文件。
Shadow-utils还添加了两个setuid程序(或setfilecap)。在Fedora上,我有:
$ getcap /usr/bin/newuidmap
/usr/bin/newuidmap = cap_setuid+ep
$ getcap /usr/bin/newgidmap
/usr/bin/newgidmap = cap_setgid+ep
Podman执行这些文件以设置用户名称空间。通过在无根容器内部检查/proc/self/uid映射和/proc/self/gid映射,可以看到映射。
$ podman run alpine cat /proc/self/uid_map /proc/self/gid_map
0 3267 1
1 100000 65536
0 3267 1
1 100000 65536
如上所示,Podman默认将容器中的root映射到当前UID(3267),然后在/etc/subuid和/etc/subgid中映射分配的UID/gid范围,从1开始。在我的示例中,容器中的UID1是UID100000,UID2是UID100001,一直到65536,也就是165535。
任何来自用户名称空间之外、由UID或GID拥有、但没有映射到用户名称空间的项目似乎都属于kernel.overflowuidsysctl中配置的用户,默认值为35534,my/etc/passwd文件称该用户没有名称nobody。由于您的进程不能作为未映射的ID运行,所以不应用所有者和组权限,因此您只能基于它们的“其他”权限访问这些文件。这包括运行容器的系统上真实root拥有的所有文件,因为root没有映射到用户名称空间。
Buildah命令具有一个很酷的功能,buildah unshare。这使您处于Podman运行时所处的用户命名空间中,但无需输入容器的文件系统,因此您可以列出主目录的内容。
请注意,当在用户名称空间之外列出home dir属性时,内核将所有权报告为dwalsh,而在用户名称空间内部,内核将目录报告为root拥有。这是因为主目录归3267所有,并且在用户名称空间内,我们将该UID视为根目录。
Podman使用容器/存储来提取容器映像,并且容器/存储足够智能,可以将映像中root拥有的所有文件映射到用户名称空间的根,以及不同uid拥有的任何其他文件映射到用户名称空间uid。默认情况下,此内容被写入~/.local/share/containers/storage。容器存储在无根模式下工作,无论是vfs模式还是Overlay模式。注意:只有在安装了fuse-overlayfs可执行文件时才支持Overlay。
内核仅允许用户名称空间root挂载某些类型的文件系统。目前,它允许挂载procfs,sysfs,tmpfs,fusefs和绑定挂载(只要源和目标归运行Podman的用户所有。虽然内核团队正在努力允许挂载OverlayFS,但尚不支持OverlayFS)。
然后,如果使用fuse-overlayfs,Podman将挂载容器的存储;如果存储驱动程序使用vfs,则不需要挂载。不过,vfs上的Podman需要很大的空间,因为每个容器都会复制整个底层文件系统。
紧接着Podman会与一些tmpfs一起装载/proc和/sys,并在容器中创建设备。
为了使用主机网络以外的网络,Podman使用slirp4netns程序为无特权的网络名称空间设置用户模式网络。Slirp4netns允许Podman将容器内的端口暴露给主机。注意,内核仍然不允许非特权进程绑定到小于1024的端口。需要Podman-1.1或更高版本才能绑定到端口。
无根Podman可以使用用户名称空间进行容器分离,但您只能访问/etc/subuid文件中定义的uid。
Podman工具使人们能够在不牺牲系统安全性的情况下构建和使用容器。 您可以授予开发人员所需的访问权限,而无需授予他们root权限。
而且,当您将容器投入生产时,您可以利用用户名称空间提供的额外安全性,以使工作负载彼此隔离。
本文系外文翻译,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文系外文翻译,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。