Podman 容器启动卡住?可能是 Network-Online.target 在作祟

问题现象

您是否遇到过在使用 podman 启动容器时,命令长时间卡住没有任何输出,也无法进入下一步的情况?尤其是在使用 systemdQuadlet 来管理容器生命周期时,例如执行 systemctl --user start my-container.service,命令卡住直到 90 秒超时。

这个问题在社区中时有讨论,例如在 Podman GitHub Issue #24796 中提到的相关网络问题,都可能导致类似的现象。

根本原因

这个问题的根源通常不在于 podman 本身,而在于 podmansystemd 的交互机制,特别是关于网络依赖的部分。

当您使用 Quadlet (后缀为 .container, .kube, .volume 等文件) 创建 systemd 服务来管理容器时,生成的服务单元通常会包含一个依赖项:After=network-online.target

network-online.targetsystemd 中一个特殊的目标(target),它表示系统的网络已经完全配置好并且可以访问。很多需要网络连接的服务(比如数据库、Web 服务,以及我们的容器)都会等待这个目标达成后再启动,以确保网络是可用的。

然而,在某些 Linux 发行版或特定的网络配置下,负责管理网络的组件(如 NetworkManagersystemd-networkd)可能没有正确地通知 systemd 网络已经“在线”。这导致 network-online.target 永远不会被激活,而所有依赖于它的服务(包括您的 Podman 容器服务)也将永远地等待下去,从而造成了“卡住”的假象。

解决方案

针对这个问题,目前有两种有效的解决方案,您可以根据自己的情况选择。

方法一:修改 Quadlet 文件

如果您确认您的容器不需要等待网络完全就绪即可启动(例如,容器不立即对外提供服务,或者服务本身有重试机制),您可以直接在您的 .container 文件中禁用默认的网络依赖。

在对应的 Quadlet 文件(如 ~/.config/containers/systemd/my-container.container)中,添加以下区段:

[Quadlet]
DefaultDependencies=false

这个配置会告诉 Quadlet 在生成 systemd 服务文件时,不要自动添加 After=network-online.target 这个依赖项。

修改后,需要重新加载 systemd 配置以使更改生效:

systemctl --user daemon-reload

之后,您就可以正常启动您的容器服务了,它将不再等待 network-online.target

这个方法的好处是它只针对特定的容器生效,并且是持久化的,不需要每次重启都手动干预。

方法二:手动触发 network-online.target

如果您急需启动容器,或者不想修改 Quadlet 文件,可以手动触发 network-online.target。在终端中运行以下命令:

sudo systemctl start network-online.target

这个命令会手动将 network-online.target 标记为已激活状态,从而解除所有等待该目标的服务的阻塞状态,您的 Podman 容器服务也就能顺利启动了。

但这只是一个临时措施,每次重启系统后您可能都需要再次手动执行。

关于全局解决方案的讨论

一些用户尝试通过启用 NetworkManager-wait-online.service 来自动处理这个依赖,命令如下:

# 注意:此方法在社区反馈中并不可靠
sudo systemctl enable NetworkManager-wait-online.service

然而,根据相关 GitHub Issue 中的持续讨论,这种方法并不稳定,在很多场景下问题依旧存在。因此,podman 社区仍未关闭相关议题,还在积极寻找更可靠的根本性解决方案。

总结

Podman 容器启动卡住通常是由于其 systemd 服务依赖的 network-online.target 未被激活。在官方给出更完美的全局解决方案之前,这两种方法是最可靠的选择。希望这篇文章能帮助您解决这个令人困惑的问题。

0%