目录

Podman 重启后容器无法启动:CNI 网络损坏与 cgroup.subtree_control 错误完整修复

Podman 重启后容器无法启动:CNI 网络损坏 & cgroup.subtree_control 错误完整解决方案

在某些云服务器或 VPS 环境中(特别是 systemd 不完整、使用 LXC、或 systemd-logind 不存在的系统),Podman 在服务器重启后可能出现以下问题:

  • 容器无法启动
  • CNI 网络损坏导致 iptables 链残留
  • OCI runtime 报错:writing file /sys/fs/cgroup/cgroup.subtree_control: Invalid argument
  • root 用户创建的容器 rootless 用户无法操作
  • Podman 自动 fallback 失败

本文总结了一个真实案例的完整分析过程,并提供 100% 可复现的修复流程


🧩 一、问题现象

重启服务器后,执行:

podman start nginx-proxy-manager

报错:

unable to start container ... writing file `/sys/fs/cgroup/cgroup.subtree_control`: Invalid argument

同时伴随:

error tearing down CNI namespace configuration
iptables CHAIN_USER_DEL failed

root 用户 podman ps -a 显示:

Created / Exited(0)
无法进入 Running 状态

而普通用户 ubuntu 运行 Podman 则提示:

no systemd user session available
Falling back to cgroupfs

甚至:

Error validating CNI config file ...

🧩 二、问题根因分析

问题分为三个层面:


1. CNI 网络损坏导致 iptables 残留

典型报错:

CHAIN_USER_DEL failed (Device or resource busy)

说明 Podman 想清理 CNI 链,但链仍被引用,导致容器网络无法正常创建。


2. crun 与 cgroup2 不兼容

最关键的错误:

writing file `/sys/fs/cgroup/cgroup.subtree_control`: Invalid argument

这是 crun 的已知问题:

  • 在某些 kernel + cgroup2 + 非 systemd 环境中
  • crun 会尝试写入 subtree_control
  • 结果触发错误
  • 导致所有容器无法启动

3. 系统缺少 systemd session,Podman 无法使用 systemd cgroup driver

Podman 提示:

no systemd user session available
Falling back to cgroupfs

这表示:

  • VPS 可能使用 LXC、本身没有完整 systemd
  • 或 root 登录不是 systemd-logind session
  • 系统不支持 systemd 作为 cgroup 管理方式

因此:

👉 Podman 必须使用 cgroupfs,而不能用 systemd

但默认配置未正确切换,因此仍然报错。


🧩 三、完整修复步骤

以下操作全部以 root 用户执行。


第一步:安装 runc(必须)

Podman 默认使用 crun,但 crun 会导致 subtree_control 报错。

安装 runc:

apt update
apt install -y runc

确认安装成功:

which runc
runc --version

第二步:修改 Podman 运行时为 runc

编辑配置:

nano /etc/containers/containers.conf

设置:

[engine]
runtime = "runc"

保存退出。


第三步:设置 cgroup manager = cgroupfs

在同一文件中添加或修改:

cgroup_manager = "cgroupfs"

这是关键!

因为你的服务器没有 systemd session,必须使用 cgroupfs,否则 subtree_control 错误无法消失。


第四步:迁移 Podman 环境

podman system migrate

应无报错。


第五步:清理损坏 CNI 网络

删除残留 CNI 配置:

rm -f /etc/cni/net.d/*.conf
rm -f /etc/cni/net.d/*.conflist

清空 NAT 链(不会破坏系统防火墙规则,仅清空 Podman 链):

iptables -t nat -F
iptables -t nat -X

清理残留 filter 链:

iptables -t filter -F
iptables -t filter -X

第六步:重新创建 Podman 默认网络

podman network create podman

第七步:尝试启动容器

podman start nginx-proxy-manager

如果输出正常,则问题完全解决。


🧩 四、验证

查看 runtime:

podman info | grep -i runtime -A3

应显示:

name: runc

查看 cgroup manager:

podman info | grep -i cgroup -A6

应显示:

cgroupManager: cgroupfs

🧩 五、为什么必须这么做?(架构层解释)

✦ crun 在某些 VPS 环境崩溃

因为它会写 subtree_control,而某些 VPS 的 cgroup2 层级不允许写该文件。

✦ systemd cgroup driver 依赖完整 systemd session

许多云服务器实际上没有 logind,因此:

→ systemd cgroup driver 必然失败 → 必须改用 cgroupfs

✦ CNI 网络在重启后容易损坏

Podman 依赖 NF_TABLES,在一些系统重启后链未清理,导致网络无法恢复。


🧩 六、总结(TL;DR)

容器无法启动的真正原因:

问题 说明
crun 与 cgroup2 不兼容 导致 subtree_control 错误
系统没有 systemd session Podman 使用 systemd cgroup driver 会失败
CNI 网络损坏 iptables 链残留阻塞网络分配

最终解决方案:

✔ 安装 runc ✔ 设置 runtime=runc ✔ 设置 cgroup_manager=cgroupfs ✔ 清理 CNI 网络与 iptables ✔ 重新 migrate Podman ✔ 重建网络并启动容器

修复后所有容器可以正常启动。