Incus 脚本审阅与验收 · 第 3 / 8 篇
容器已经 Running,里面却不能更新软件源。遇到这种现象,直接重装 Incus 或更换 DNS,常常只是换了一种方式重复故障。更有价值的做法,是先判断报文停在哪一层。

先把问题拆成五层
建议先执行只读或低影响诊断:
incus exec vps1 -- ip -4 addr
incus exec vps1 -- ip -4 route
incus exec vps1 -- getent ahostsv4 deb.debian.org
incus exec vps1 -- timeout 8 bash -c 'echo >/dev/tcp/1.1.1.1/443'
sysctl net.ipv4.ip_forward
ip -4 route show default
iptables -L FORWARD -n -v
iptables -L DOCKER-USER -n -v
ping 失败也可能是 ICMP 被限制,不能单独宣布“断网”;而 TCP 443 成功只是对该地址的连接证据,仍需要实际软件源或业务请求确认。
为什么宿主机有 Docker 时值得检查 FORWARD
Docker 与 Incus 都会使用宿主机网络功能。Incus 官方文档记录了二者共存时的一种常见问题:Docker 设置全局转发丢弃策略,影响 Incus 实例出站。现存部署脚本中的兼容补丁,就是针对这类路径设计的。Incus 官方共存说明
这只是候选原因。如果当前使用原生 nftables 后端、没有 DOCKER-USER,或者丢包发生在另一套防火墙中,不能继续机械套用 iptables 补丁。iptables-nft 兼容工具也不等同于 Docker 原生 nftables 后端,必须先辨认实际规则系统。
补丁为什么只放行两类流量
脚本检测默认 IPv4 出口与网桥网段,在 DOCKER-USER 中加入定向规则:一条允许网桥网段向出口发送;另一条只允许返回网桥的 ESTABLISHED,RELATED 流量。它试图恢复实例主动访问外网及其返回路径,而不把全局 FORWARD 一律改成 ACCEPT。Docker 的用户自定义规则链说明
每次添加前执行 iptables -C,是为了避免同一规则重复堆积。接口和网段通过本机查询获得,优于硬编码 eth0 和固定的 10.x 网段。但如果有多出口、策略路由、VPN 或 IPv6,单一默认 IPv4 出口模型就不够了。
这个补丁不是业务入站开放器,也不是容器间隔离策略。其他 nftables 基链仍可能丢弃流量;某一条 ACCEPT 不能证明整条路径一定放行。不要因此清空防火墙,更不要关闭 Docker 的规则维护来“试试看”。Docker 防火墙说明
systemd 持久化为什么仍需要测试
脚本安装一个 oneshot 单元,设置在 Docker 与 Incus 之后执行,并启用开机运行。同时立即直接执行一次修复脚本,让当前部署能够继续。
这里有一个容易忽略的边界:After=docker.service 规定的是启动顺序,不代表“Docker 每次重启,都自动再次运行这个 oneshot”。原注释也提醒,单独重启 Docker 后必要时需重新应用。完整验收必须分别测试宿主机重启、Docker 重启和规则是否仍存在,不能只看单元已 enabled。
systemctl cat incus-docker-forward-fix.service
systemctl is-enabled incus-docker-forward-fix.service
iptables -S DOCKER-USER
最后一条用于列出规则,应逐项核对已检测到的出口、规范化网段和连接状态条件。若用 iptables -C 精确查询,也应使用相同条件,不能拿一条不同的宽规则查不到,就误判为本方案没有配置。
下一轮演进应该如何记录
保留修复前的路由、规则与失败命令;应用最小变更;用同一请求重新测试;再验证 Docker 原有业务。只有前后证据对应,才能写“这一规则修复了本次出站故障”。现有材料能证明补丁的设计和调用位置,尚不能替代特定服务器上的故障归因与重启回归。