使用 pasta 的 –map-guest-addr 选项
从 Podman 5.0 开始,我们将 “pasta” 作为无根网络应用程序的默认选项,为无根容器提供网络连接。与我们之前的默认选项 slirp4netns 相比,pasta 的工作方式略有不同。例如,pasta 默认不使用网络地址转换 (NAT)。这意味着它也会将主机地址复制到容器中,这意味着主机和容器命名空间都使用相同的 IP 地址。这反过来意味着,如果您尝试从容器连接到主机 IP,它将指向自身,而不是主机。许多用户对这种情况下主机和容器之间缺乏连接感到困惑。
此外,在很长一段时间内,Podman 在容器中提供了 host.containers.internal 主机条目,以允许容器访问主机。Podman 试图足够智能,不添加容器命名空间中已使用的相同主机 IP,以避免此问题。然而,在许多情况下,主机只有一个 IP 地址(不包括 localhost),因此在这种情况下,Podman 无法为 host.containers.internal
提供合适的 IP 地址;因此,该条目未被添加。
由于这是一个常见用例,pasta 开发人员添加了一个新的 pasta 选项 --map-guest-addr <ip>
,允许用户选择命名空间内的一个给定 IP 地址来引用主机命名空间中的实际主机 IP。从 Podman 5.3 开始,我们将默认使用此选项:地址 169.254.1.2 将被映射到主机。
我们还确保 host.containers.internal 条目将设置为此 IP,这将使主机名再次工作,即使没有可用的辅助 IP;因此,请不要硬编码 IP,而应使用 host.containers.internal
。
还可以选择使用另一个 IP,就像任何其他 pasta 选项一样,您可以直接将其传递给 Podman,Podman 会将其添加到 pasta 命令行中。在这种情况下,主机名也将正确更新以使用新的正确 IP,例如:
$ podman run --network pasta:--map-guest-addr,10.0.0.1 quay.io/libpod/testimage:20241011 \
grep host.containers.internal /etc/hosts
10.0.0.1 host.containers.internal host.docker.internal
要使用 --map-guest-addr
,需要 passt 版本 2024_08_14 或更高版本,因此请确保您已安装它。如果存在旧版本,Podman 将保留旧行为,并且不会出错,除非用户明确设置 --map-guest-addr
。
Quadlet 无根容器启动
另一个常见问题是使用 quadlet 创建的无根 systemd 单元在启动时无法启动。这会发生,因为 pasta 需要网络完全启动后才能启动;否则,如果您的网络设置花费的时间足够长,您很可能会在单元日志中收到“外部接口不可用”错误,并且容器不会启动。
尽管生成的 systemd 单元使用了 After=network-online.target
,但事实证明这没有任何作用,因为 systemd 用户会话无法看到系统单元,例如 network-online.target。因此,systemd 忽略了 After=
行,并且容器单元在网络准备好之前启动得太早,导致启动时随机失败。
在 Podman 5.3 中,我现在为此实现了一个变通方案。打包者需要确保将新的 podman-user-wait-network-online.service
单元放置在用户(而非系统)目录中,以便可以在所有用户会话中使用。该单元通过每半秒通过 systemctl is-active network-online.target 轮询状态,等待系统 network-online.target 单元变为活动状态。通过此方式,quadlet 不再为用户单元添加 After=network-online.target
,而是添加 After=podman-user-wait-network-online.service
,这保证了容器单元会等待直到网络准备就绪且 pasta 正确启动。手动实现了类似此变通方案的用户应该可以再次将其删除。
如果出于某种原因,您不需要或不希望您的单元等待网络准备就绪,那么您可以在 quadlet 文件中新添加的 [Quadlet]
部分下使用新的 DefaultDependencies=false
选项。
回复 Graeme取消回复