小开发板crontab重启容器报错bug
Podman 容器网络 IP 分配冲突问题排查与解决笔记
一、问题现象
1. 手动启动容器报错
执行 podman start clash adguardhome 时出现以下错误:
ERRO[0000] Error adding network: failed to allocate for range 0: 172.16.16.8 has been allocated to bd03adf84621... duplicate allocation is not allowed
ERRO[0000] Error while adding pod to CNI network "podman": failed to allocate for range 0: 172.16.16.8 has been allocated to ...2. 定时任务(Cron)重启容器时同样出现 IP 分配冲突
- 计划任务执行
podman restart clash adguardhome - 容器重启后网络短暂断开,但服务实际可用
- Cron 输出被丢弃(
No MTA installed, discarding output)
3. 后续启动时冲突 IP 变化
- 从
172.16.16.8变为10.88.2.6/10.88.2.7 - 错误信息显示:容器自己占用了自己的 IP(自冲突)
二、环境信息
| 项目 | 信息 |
|---|---|
| Podman 版本 | 3.0.1 |
| API 版本 | 3.0.0 |
| 架构 | ARM(linux/arm) |
| 运行时配置 | runc(已从默认的 crun 切换) |
| 容器镜像 | dreamacro/clash:dev、adguard/adguardhome:edge |
三、问题根本原因
1. Podman 3.0.1 在 ARM 上的已知 Bug
- CNI 网络 IP 分配记录存在竞态条件
- 容器停止后,IP 分配文件(如
/var/lib/cni/networks/podman/10.88.2.6)未被正确删除 - 重启时 CNI 读取残留文件,发现 IP 已被“占用”
- 即使占用者是自己,也拒绝分配 → 死锁
2. 网络命名空间残留
/var/run/netns/cni-*文件中积累了大量未被清理的网络命名空间- 执行
rm -rf /var/run/netns/cni-*时出现Device or resource busy - 说明有进程仍在使用这些命名空间
3. 其他潜在因素
- 之前使用
systemctl restart podman可能导致残留 - 容器频繁重启但清理机制不完善
- Cron 环境变量缺失(PATH 等)可能导致命令找不到
四、解决方案
✅ 方案一:使用 Host 网络模式(推荐,最简单)
# 删除旧容器
podman rm -f clash adguardhome
# 使用 host 网络重新创建
podman run -d \
--name clash \
--network host \
--restart unless-stopped \
docker.io/dreamacro/clash:dev
podman run -d \
--name adguardhome \
--network host \
--restart unless-stopped \
docker.io/adguard/adguardhome:edge优点:完全绕过 CNI 网络,无 IP 分配问题,网络性能最好
缺点:容器与宿主机共享网络栈,端口不能冲突
✅ 方案二:清理 CNI 残留并重建桥接网络
# 1. 停止并删除容器
podman stop clash adguardhome
podman rm clash adguardhome
# 2. 清理 CNI 分配记录
sudo rm -rf /var/lib/cni/networks/podman/*
# 3. 清理网络命名空间(如遇 busy,需重启系统)
sudo rm -rf /var/run/netns/cni-* # 可能报 busy
sudo umount /var/run/netns/cni-* 2>/dev/null
sudo ip netns del <namespace> # 逐个删除
# 4. 创建新网络(不同子网)
podman network create --subnet 10.89.0.0/24 clash-net
# 5. 重建容器
podman run -d \
--name clash \
--network clash-net \
--ip 10.89.0.10 \
docker.io/dreamacro/clash:dev✅ 方案三:彻底清理(终极方案)
# 1. 删除所有容器
podman rm -f $(podman ps -aq)
# 2. 停止 Podman 服务
systemctl --user stop podman.socket podman.service
sudo systemctl stop podman.socket podman.service
# 3. 清理所有 CNI 和网络命名空间
sudo rm -rf /var/lib/cni/networks/*
sudo rm -rf /var/run/netns/cni-*
sudo rm -rf /etc/cni/net.d/podman*
# 4. 重启系统(最彻底)
sudo reboot五、关于 kill -HUP 1 的澄清
| 问题 | 答案 |
|---|---|
| 是否所有容器都支持? | ❌ 不是,只有支持 SIGHUP 热重载的程序(如 Nginx)才有效 |
| Clash 是否支持? | ❌ 不支持,会忽略信号或无反应 |
| AdGuardHome 是否支持? | ❌ 不支持 |
| 对不支持的程序怎么办? | 使用 podman restart 或通过应用自身 API 重载 |
六、定时重启的正确配置
方式一:Cron(简单)
# 编辑 crontab
crontab -e
# 添加定时任务(每天凌晨 4:00 重启)
0 4 * * * /usr/bin/podman restart clash adguardhome >> /var/log/podman-restart.log 2>&1方式二:Systemd Timer(推荐生产环境)
# 生成 service 文件
podman generate systemd --name --new --files --restart-policy=always clash
# 移动到用户目录
mv container-clash.service ~/.config/systemd/user/
# 启用服务
systemctl --user daemon-reload
systemctl --user enable container-clash.service
# 创建 timer 文件
cat > ~/.config/systemd/user/restart-clash.timer << EOF
[Unit]
Description=Timer to restart Clash daily
[Timer]
OnCalendar=*-*-* 04:00:00
Persistent=true
[Install]
WantedBy=timers.target
EOF
# 启用 timer
systemctl --user enable restart-clash.timer
systemctl --user start restart-clash.timer七、containers.conf 优化配置
文件位置:/etc/containers/containers.conf
[engine]
# 使用更稳定的 runc(代替 crun)
runtime = "runc"
cgroup_manager = "cgroupfs"
[containers]
# 共享宿主机 cgroup 命名空间,简化资源管理
cgroupns = "host"作用:
runc:解决老版本 Podman(3.0.1)在 ARM 上的网络资源残留问题cgroupns = "host":降低容器因资源限制被异常关闭的风险
八、常见问题速查
| 问题 | 解决方法 |
|---|---|
duplicate allocation | 清理 /var/lib/cni/networks/podman/* 或改用 host 网络 |
Device or resource busy | 重启系统,或 umount 后 ip netns del |
| Cron 任务不执行 | 检查 PATH:which podman,使用绝对路径 |
| Cron 输出丢失 | 重定向到文件:>> /var/log/xxx.log 2>&1 |
| 容器重启后网络闪断 | 正常现象,restart 会重建网络;如需平滑重载,使用应用 API |
九、操作记录摘要
| 时间 | 操作 | 结果 |
|---|---|---|
| 首次 | podman start clash | ❌ IP 172.16.16.8 冲突 |
| 配置 | containers.conf 添加 runtime = "runc" | 部分改善 |
| 清理 | rm -f /var/lib/cni/networks/podman/* | 临时解决 |
| 重启 | 系统 reboot | ✅ 彻底清理网络命名空间 |
| 最终 | 改用 --network host | ✅ 完全规避问题 |
十、建议与总结
- 短期方案:使用
--network host模式,彻底绕过 CNI 网络问题 - 中期方案:保持
runc+cgroupns = "host"配置 - 长期方案:升级 Podman 到 4.x 或更高版本(ARM 支持更完善)
- 监控:定期检查
/var/run/netns/cni-*数量,避免残留堆积 - 日志:为定时任务配置日志输出,便于排查问题