真泄漏netns需同时满足:/var/run/netns/xxx存在、find /proc/*/ns/net -samefile无匹配、名称含临时标识且创建久远;安全清理须先dry-run预览,再ip netns delete优先执行,失败才unlink符号链接。

网络命名空间(netns)泄漏不是“删不掉”,而是“不该删的被删了”或“该删的没识别出来”。直接 ip netns delete 批量执行大概率失败,甚至引发网络中断。关键在判断:哪个是真泄漏?哪个还在被进程、容器或内核子系统引用?
怎么确认一个 netns 是否真的泄漏了
仅看 /var/run/netns/xxx 文件存在 ≠ 可删。必须验证它是否被任何进程的网络命名空间句柄引用:
- 执行
find /proc/[0-9]*/ns/net -samefile /var/run/netns/xxx 2>/dev/null | head -n1,无输出才说明无进程引用 - 注意路径:有些系统用
/run/netns/而非/var/run/netns/(/var/run是/run的符号链接,但部分容器运行时会绕过) - 不要依赖
ip netns list输出——它只列挂载点,不反映实际使用状态 - 白名单必须包含你明确知道在用的名称,比如
default、host、eni-prod(Terway 场景下)
为什么 ip netns delete 经常失败
失败不是命令错了,而是内核拒绝释放——因为该 netns 仍有活跃引用。常见原因:
Linux 安全审计工具,检查 SSH 配置、开放/监听端口、防火墙规则(ufw/iptables/nftables)、失败登录尝试、sudoers 权限...
- 某个进程刚 fork 出来还没 exec,其
/proc/PID/ns/net仍指向该 netns(即使进程已退出,内核可能未立即回收) - 容器运行时(如 Podman)异常退出,留下 bind mount 但未清理挂载点
- 脚本中用了
unshare --net启动临时网络环境,但没配ip netns delete或没等子进程退出就返回 -
ip netns delete本质是umount+ 清理挂载点,若挂载点被其他 mount tree 引用(如mount --bind嵌套),会报Device or resource busy
安全清理必须分两步:预览 + 分离
跳过预览直接删,等于拿锤子砸电路板——修不好还冒烟。正确流程:
- 先跑 dry-run:
./safe-netns-cleanup.sh --dry-run,结果输出到/tmp/netns-to-delete.log,人工核对前 10 行 - 真正执行时,脚本对每个候选 netns 先尝试
ip netns delete $ns;失败则 fallback 到rm -f /var/run/netns/$ns(仅 unlink 符号链接,不碰内核对象) - unlink 不等于释放内存,只是让
ip netns list看不见它;真正的内核对象会在最后一个引用消失后由内核自动回收 - 建议搭配 cron 每 6 小时跑一次 dry-run,并把日志发到告警群——突然多出 50+ 待删项,大概率是某批测试脚本又崩了
最易被忽略的一点:netns 泄漏往往不是孤立事件,而是上游容器或自动化脚本异常退出的副产品。查清 stat /var/run/netns/xxx 里的 Modify 时间,再翻对应时间段的 journalctl -u podman 或 /var/log/messages,才能堵住源头。单纯清理,治标不治本。

















