在允许没有root权限的用户运行Podman之前,管理员必须安装或构建Podman并完成以下配置。
有关安装Podman的内容,请参阅安装说明。
关于构建Podman,请参阅构建说明。
要让Podman在无root权限环境中运行,必须在机器上安装一个用于非特权网络命名空间的用户模式网络工具。
Podman支持两种无 root 权限网络工具:pasta(由 passt 提供)和 slirp4netns。
自Podman 5.0起,pasta 成为默认工具,而在之前的版本中,slirp4netns 是默认工具。Passt 是 SLIRP的一种更现代化的替代工具,它除了其他功能外,还完全支持IPv6,并且在架构上更安全(在单独的进程中运行,使用现代Linux隔离机制等)。
Passt 可在大多数 Linux 发行版上通过其软件包分发软件(如yum、dnf、apt、zypper等)获取,软件包名称为passt。如果该软件包不可用,你可以从其上游代码构建并安装 passt。
或者,slirp4netns 也可以通过相同的方式安装,要么从你的发行版仓库中获取,要么按照其 GitHub 上提供的说明进行操作。
两者之间主要的面向用户的差异在这篇博客文章中有所概述,并在 podman-network(1) 中进行了详细阐述。
注意:
pasta默认情况下无法在容器和主机之间进行通信的问题已在 Podman 5.3 中得到修复:请参阅 Podman 5.3的变化为pasta带来了更好的网络体验。
默认的无 root 权限网络工具可以在 containers.conf 中的 [network] 部分通过 default_rootless_network_cmd 进行选择,该选项可以设置为 pasta(默认值)或 slirp4netns。
Rootless Podman要求运行它的用户在/etc/subuid和/etc/subgid文件中拥有指定范围的UID。shadow-utils 或 newuid 软件包在不同发行版中提供这些文件,且必须安装在系统中。向这些文件添加或更新条目需要 root 权限。以下内容摘自 Dan Walsh 在 opensource.com 发表的 Rootless Podman 如何工作?一文。
对于每个允许创建容器的用户,请更新其对应的/etc/subuid和/etc/subgid文件,字段格式如下所示。请注意每个用户的值必须唯一。若存在重复,则可能导致用户使用其他用户的命名空间并造成损坏。
# cat /etc/subuid johndoe:100000:65536 test:165536:65536
此文件的格式为 USERNAME:UID:RANGE
用户名,如 /etc/passwd 中所列或 getpwent 的输出所示。
为用户分配的初始 UID。
为用户分配的 UID 范围大小。
这意味着用户 johndoe 在 /etc/passwd 文件中被分配了 UID 100000-165535 以及其标准UID。注意:当前网络安装不支持此功能;这些文件必须在主机本地可用。无法通过 LDAP 或 Active Directory 进行此配置。
无需直接更新这些文件,而是可以使用usermod程序为用户分配用户标识符(UID)和组标识符(GID)。
# usermod --add-subuids 100000-165535 --add-subgids 100000-165535 johndoe grep johndoe /etc/subuid /etc/subgid /etc/subuid:johndoe:100000:65536 /etc/subgid:johndoe:100000:65536
若更新 /etc/subuid 或 /etc/subgid 文件,需停止所有由该用户拥有的运行中容器,并终止系统中该用户的暂停进程。可通过以该用户身份运行 podman system migrate 命令实现自动处理。
如果这些组隶属于用户,用户可以将额外的组完全映射到容器命名空间:
# usermod --add-subgids 2000-2000 johndoe grep johndoe /etc/subgid
这意味着用户johndoe可以在容器内“模拟”组2000。请注意,通常不建议将活动用户ID从属于其他用户,因为这会导致用户身份冒充。
johndoe 可以使用 --group-add keep-groups 选项保留额外组,并通过 --gidmap=“+g102000:@2000” 将主机中的组 2000 映射到容器中的组 102000:
$ podman run \ --rm \ --group-add keep-groups \ --gidmap="+g102000:@2000" \ --volume "$PWD:/data:ro" \ --workdir /data \ alpine ls -lisa
(在现代发行版上,你很可能不需要这样做)
在非特权容器中运行的用户可能无法从该容器中使用 ping 工具。
如果需要这样做,管理员必须验证该用户的 UID 是否属于 /proc/sys/net/ipv4/ping_group_range 文件中的范围。要更改其值,管理员可以使用类似如下的命令:sysctl -w "net.ipv4.ping_group_range=0 2000000"。
为使这一更改持久生效,管理员需要在 /etc/sysctl.d 目录中添加一个扩展名为.conf的文件,该文件应包含 net.ipv4.ping_group_range=0 $MAX_GID,其中 $MAX_GID 是运行容器的用户可分配的最高GID。
在无 root 权限环境中运行 Podman 所需的大部分工作都由机器管理员承担。
一旦管理员在机器上完成初始设置,并在 /etc/subuid 和 /etc/subgid 中完成用户配置后,用户即可直接使用任何所需的 Podman 命令。
Podman 的 root 配置文件位于 /usr/share/containers,覆盖配置存放于 /etc/containers。在无 root 环境中,这些配置文件存放于 ${XDG_CONFIG_HOME}/containers,并由每个用户单独拥有。
注意:在未设置 XDG 环境变量的环境中,Podman 内部会设置以下默认值:
$XDG_CONFIG_HOME = $HOME/.config
$XDG_DATA_HOME = $HOME/.local/share
$XDG_RUNTIME_DIR =
/run/user/$UID 在 systemd 环境中
$TMPDIR/podman-run-$UID 否则
三个主要的配置文件分别是 containers.conf、storage.conf 和 registries.conf。用户可以根据自己的意愿修改这些文件。
Podman 会读取:
/usr/share/containers/containers.conf
/etc/containers/containers.conf
${XDG_CONFIG_HOME}/containers/containers.conf
如果这些文件存在,会按照这个顺序读取。每个文件都可以在特定字段上覆盖前一个文件的设置。
对于 storage.conf 其顺序为:
/etc/containers/storage.conf
${XDG_CONFIG_HOME}/containers/storage.conf
在无 root 权限的 Podman 中,/etc/containers/storage.conf 中的某些字段会被忽略。这些字段包括:
graphroot="" container storage graph dir (default: "/var/lib/containers/storage") Default directory to store all writable content created by container storage programs. runroot="" container storage run dir (default: "/run/containers/storage") Default directory to store all temporary writable content created by container storage programs.
在无 root 权限的 Podman 中,这些字段的默认值为:
graphroot="${XDG_DATA_HOME}/containers/storage"
runroot="${XDG_RUNTIME_DIR}/containers"$XDG_RUNTIME_DIR 在大多数系统上默认设置为 /run/user/$UID。
注册表配置按此顺序读取:
/etc/containers/registries.conf
/etc/containers/registries.d/*
${XDG_CONFIG_HOME}/containers/registries.conf
用户主目录中的文件应用于配置无 root 权限 Podman 以满足个人需求。这些文件默认不会创建。用户可从 /usr/share/containers 或 /etc/containers 目录复制文件并进行修改。
podman login 和 podman logout 命令使用的默认授权文件是 ${XDG_RUNTIME_DIR}/containers/auth.json。
无 root 权限的 Podman 并非且永远不会成为 root 用户;它不是 setuid 二进制文件,运行时不会获得任何特权。相反,Podman 利用用户命名空间来转换其在主机上被授予访问权限的用户组(通过 newuidmap 和 newgidmap 可执行文件)以及 Podman 创建的容器内您自身用户的 UID 和 GID。
若容器以 root 用户运行,则容器内的 root 用户实际上就是主机上的您本人。UID/GID 1 是用户映射中 /etc/subuid 和 /etc/subgid 等文件中指定的首个 UID/GID。若以非 root 用户身份将主机目录挂载至容器,并在容器内以 root 身份创建文件,你会发现该文件实际归属主机上的用户。
例如:
host$ whoami john # 一个空文件夹 host$ ls /home/john/folder host$ podman run -it -v /home/john/folder:/container/volume mycontainer /bin/bash # 现在我在容器里 root@container# whoami root root@container# touch /container/volume/test root@container# ls -l /container/volume total 0 -rw-r--r-- 1 root root 0 May 20 21:47 test root@container# exit # 我再检查一遍 host$ ls -l /home/john/folder total 0 -rw-r--r-- 1 john john 0 May 20 21:47 test
我们确实意识到这与许多人期望的无 root 权限 Podman 使用方式并不完全吻合 —— 他们希望容器内外用户ID保持一致。因此我们提供了 --userns=keep-id参数,该参数可确保用户在容器内映射到其专属的 UID 和 GID。
区分以无 root 权限用户身份运行 Podman 与构建为无 root 权限运行的容器也很有帮助。若您尝试运行的容器其 USER 属性非 root 用户,则挂载卷时必须使用 --userns=keep-id 参数。这是因为容器用户无法提升至 root 权限来访问已挂载的卷。
关于卷的另一个注意事项:
在提供要绑定挂载的目录路径时,该路径必须以绝对路径或以点(.)开头的相对路径形式提供,否则该字符串将被解释为命名卷的名称。
如果您在无root权限环境中运行Podman时仍遇到问题,请参考 无root权限Podman的局限性 页面,该页面列出了此环境中的已知问题及对应的解决方法。
有关Podman及其子命令的更多信息,请访问主 README.md 页面上的链接或 podman.io 网站。
原文地址:https://github.com/containers/podman/blob/main/docs/tutorials/rootless_tutorial.md