大厂的内部工具居然开源了! 一窥百度物理网络秒级监控定位的秘密

目前顶尖的云服务商都包含百万台服务器、数十甚至上百个机房、上万台网络设备、百万级网络链路。单单一个GPU集群,就有上万卡的级别。对这些网络和服务器的监控,一个分钟级别的故障,可能就是上百万资产的损失。

这不是一个ping能解决的问题。

今天,我们将百度物理网络黑盒监控方向的工具集 nettools 开源了(https://github.com/baidu/nettools),第一批放出的是 bitflip 和 bitflip6,用于检测网络丢包和比特翻转,在百度内部跑了很长时间了。

后续还有更多工具和SDK正在整理中,包括骨干网fullmesh监控、网关设备监控、连接客户内部机房设备的监控、定位工具等等,还有对巨量监控数据的处理。百度物理网络黑盒监控团队积累了一大批经验、产品和工具,后续逐步整理开源出来,欢迎关注。

为什么不是一个ping?

在大规模物理网络中,ping几乎没有用。

下面是一个集群简化的示意图。实际上层级比这更多,同一层级的网络设备数量远远大于图中画的,一个交换机有几十个端口而不是图中的几根连线,一个ToR交换机可能连接几十台服务器……两台服务器之间可走的链路有很多种可能。

bitflip用4种salt填充模式来覆盖各种跳变场景:

模式 作用
全1 0xFF 检测 1→0 跳变
全0 0x00 检测 0→1 跳变
固定 0x5A 检测混合模式跳变
互补交替 0xAAAA/0x5555 专门检测checksum盲区的互补跳变

每个包按序列号选择一种模式,服务端用相同模式验证,精确到哪个字节、哪个bit翻转了。

这个场景非常讨厌。可能一年就遇到一次,遇到了就特别麻烦,影响还大,错误数据被当成正常数据保存了。客户发现还算容易,因为除了能绕过checksum的那部分,大部分坏包会被服务器的checksum校验drop掉,通过采集监控服务器的checksum指标,理论上容易发现(实际还有一些坏包干扰)。

但定位起来就头疼了。客户报过来说好几个机房有改包现象,到底是哪个机房哪一层设备的哪个板卡?

这时候用bitflip工具,如果能复现,就可以通过找改包五元组的共同路径,定位到故障的设备和端口。这要靠单向监控,双向的话就像前面说的,有可能误导。

工程细节:raw socket + BPF

在百度的规模下,每秒要发送数千甚至上万个探测包。普通的UDP socket不够用:

  • 需要自由构造IP头(设置TOS/DSCP等网络参数)
  • 需要用极少的socket覆盖上百个端口对
  • 需要精确控制发包速率

bitflip客户端用raw socket直接构造IP+UDP包,通过BPF过滤收包,只接收目标端口范围内、特定TOS值的回包。读侧按端口范围切分为最多8个goroutine,每个绑定独立的BPF过滤器。

1
2
3
4
5
6
7
8
9
10
11
12
13
func portRangeBPF(minPort, maxPort, tos int) []bpf.Instruction {
return []bpf.Instruction{
bpf.LoadIndirect{Off: 9, Size: 1},
bpf.JumpIf{Cond: bpf.JumpEqual, Val: uint32(17), SkipFalse: 4},
bpf.LoadIndirect{Off: 1, Size: 1},
bpf.JumpIf{Cond: bpf.JumpEqual, Val: uint32(tos), SkipFalse: 4},
bpf.LoadAbsolute{Off: 22, Size: 2},
bpf.JumpIf{Cond: bpf.JumpGreaterOrEqual, Val: uint32(minPort), SkipFalse: 2},
bpf.JumpIf{Cond: bpf.JumpLessOrEqual, Val: uint32(maxPort), SkipFalse: 1},
bpf.RetConstant{Val: 0xffff},
bpf.RetConstant{Val: 0x0},
}
}

双向对比判断故障方向

bitflip同时支持客户端和服务端两侧统计。对比两侧丢包:

  • 仅服务端有丢包:故障在正向路径(Client → Server)
  • 仅客户端有丢包,服务端正常:故障在回程路径(Server → Client)
  • 两端都有丢包:需要进一步分析

结合traceroute获取的链路拓扑,分析丢包五元组的公共端口/设备,就能定位到具体哪台设备、哪个板卡、哪个端口。

快速体验

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 克隆并编译
git clone https://github.com/baidu-sys/nettools.git
cd nettools && make build

# 在远端启动服务端(自动检测IP,自动注册客户端)
./bitflip

# 在本地启动客户端
sudo ./bitflip -r client -s <server_ip>

# 以每秒10000包的速率探测60秒
sudo ./bitflip -r client -s <server_ip> --rate 10000 --duration 60s

# 开启详细模式,丢包时输出具体五元组
sudo ./bitflip -r client -s <server_ip> --verbose

IPv6环境使用 bitflip6,用法一致。

使用手册查看:bitflip使用指南

后续规划

nettools 目前开源的是 bitflip/bitflip6。后续还有更多工具和SDK在整理中:

  • 更多探测场景的工具
  • 通用的网络探测SDK
  • 定位分析相关的工具

写在最后

在百度这种体量的物理网络中做监控和定位,不是写几个socket程序就能搞定的。为什么用UDP不用ICMP和TCP?为什么有时候又采用TCP syn探测?为什么需要单向探测?为什么协议头要带上一个窗口的发送信息?为什么salt要用4种模式?每个选择背后都有对应的故障场景和教训。

这些东西以前都在内部,现在开源出来了。

项目地址:https://github.com/baidu/nettools

欢迎Star、试用、提Issue和PR。