虚拟机通过 nbd 秒级启动,但 nbd-server 连接总被误清理。根因是新版本 nbd-server 默认用 tcp6 双栈监听,而清理代码用 netstat -4 只过滤 tcp4,把 tcp6 上的连接误判为"无连接"而误清理。
现象
虚拟机通过 nbd 可以实现秒级启动,之前跑的好好的。 最近一个测试环境,总是会出现 nbd 连接丢失的情况。
排查是 base img 的 nbd-server 进程被 kill。 且通过日志看,就是我们的程序给 kill 的。
但是我们的程序是正常的清理,会判断这个 nbd-server 没有连接,才会去 kill。 到底是哪里的问题?是真没有连接了,还是哪里判断有问题。
排查
代码会先检查已经有连接的,这些是肯定不会去 kill:
exec_cmd("netstat -4 --tcp -p -n | grep ESTABLISHED | grep nbd-server | awk '{print $4}' | awk -F':' '{print $2}' | sort -u > %s" % tmp_file)
代码已经十年了,看着也很完善,没出过类似问题。
后发现是 tcp6 和 tcp4 的原因,和 nbd-server 的版本有关系:
- 以前部署的是
This is nbd-server version 3.9.1 - 现在部署的是
This is nbd-server version 3.23
看起来新版本默认用的是 tcp6 双栈,老版本默认是 tcp4。
新版本 nbd-server 的监听是这样:
root@:~# netstat -tpln |grep nbd-server
tcp6 0 0 :::43403 :::* LISTEN 2468990/nbd-server
老版本 nbd-server 的监听是这样:
root@host:~# netstat -tpln |grep nbd-server
tcp 0 0 0.0.0.0:43403 0.0.0.0:* LISTEN 2468990/nbd-server
关键区别在于,开头的 tcp6 和 tcp,还有 ::: 和 0.0.0.0。
根因
查看内核参数 net.ipv6.bindv6only 是 0,也就是说默认是开启双栈的。内核参数就不改了。
- 双栈兼容处理:当一个程序在 IPv6 套接字(
AF_INET6)上监听时,如果未显式启用IPV6_V6ONLY选项,这个监听套接字就可以同时接收 IPv4 和 IPv6 的传入连接。 - 协议栈隐式转换:当纯 IPv4 客户端连接进来时,Linux 内核会自动将该 IPv4 地址转换为 IPv6 格式(例如将
10.0.0.10在内部表示为::ffff:10.0.0.10),并通过 IPv6 的套接字来处理这个连接。 - netstat 展示机制:因为这个连接在系统内核层面被归类在
tcp6套接字下处理,所以netstat读取/proc/net/tcp6时就会把它显示为tcp6,即便输出界面上渲染出的远端 IP 依然是 IPv4 的格式。
解决办法
现在有两种方式:
- 修改代码,netstat 不加
-4,这样 tcp 和 tcp6 都能过滤到; - 应该有配置,约束 nbd-server 的行为,让其和老版本一样,只启动 tcp4 的连接。
调整配置:各种 AI 都是这个结论:
/etc/nbd-server/config
[generic]
bindaddr = 0.0.0.0
一顿折腾猛如虎,回头一看原地杵。后查看手册发现正解:
man 5 nbd-server
listenaddr = 0.0.0.0
一点思考
虽然 2026 年了,虽然 AI 很强了,但是这个问题依然需要人去解决。 前面各种 AI 给的解法都是:一直不行,AI 说各种格式问题,疯狂尝试。 结果可想而知,从源头参数就是错的,围绕错误的开头,AI 做再多都是徒劳,浪费算力和时间。 从这个角度看,AI 是个很强的智能工具,依然需要人去驾驭。
有些时候,这取舍啊,真是理解不了。
这里为啥要用 netstat -4 呢?是怕匹配到非我们平台的 nbd,导致我们漏清理了吗?
但是漏清理就是多占用个进程,而误清理,直接影响虚拟机运行,这是要直接中断业务的呀。
这两个结果,怎么能选择规避漏清理,而埋下误清理的选择呢,不能理解!
小结
- 新版本 nbd-server 默认用 tcp6 双栈监听,老版本默认 tcp4;
- 清理代码用
netstat -4只过滤 tcp4,导致 tcp6 上的连接被误判为"无连接"而误清理; - 双栈下 IPv4 连接也会被归类到 tcp6 套接字,
netstat -4会漏掉; - 正解是
listenaddr = 0.0.0.0(不是bindaddr); - 排查问题要从源头参数入手,AI 再强也需要人去驾驭。