eBPF 网络排障最佳实践¶
业务报告“连接不上”“偶尔卡住”或“流量突然下降”时,可以先用节点指标发现异常,再用 netflow 缩小到进程和对端,最后查看异常摘要中的连接样本。下面的实践展示如何把这些观测转成下一步检查,而不是只展示流量曲线。
选择排查场景¶
| 现象 | 阅读实践 | 可以缩小到的范围 |
|---|---|---|
| 连接被拒绝、不可达、建立慢,服务接不进连接 | 连接失败与监听压力 | 连接阶段、发起进程、目标端点、监听队列 |
| 发请求卡住、吞吐下降、接收处理慢、连接长期不清理 | TCP 传输与连接清理 | 对端接收窗口、未发送/未确认/未读队列、ACK 推进、半关闭 |
| 域名解析失败、DNS 无响应、UDP 发送失败 | DNS 与 UDP 排障 | DNS 事务、返回码、命名空间、UDP socket 错误 |
| 流量变少但业务没有变化,map 压力或发送积压 | 采集可信度与资源控制 | 采集来源、能力和覆盖、map、上报队列与预算 |
这些实践适用于包含网络诊断功能的 eBPF 采集器,配置与完整字段表见 eBPF 采集器。文中的实测来自 Linux 6.1 amd64、无 BTF、4 CPU 的故障注入测试,持续约 145 秒。fixture 是测试进程,地址和域名是测试环境;这些不是客户生产事故。补充的假设数据均标为“教学示例”。实验结果用于说明证据如何解释,不能当作生产吞吐、延迟或漏采率保证。
普通连接线索现在按 日志收敛规则 筛选:偶发重传、reset、短暂接收积压等继续计数,达到重复或持续观测门槛才出日志;同组后续合格线索最多每 5 分钟更新一次。以下历史故障注入样本用于解释证据,不表示单次注入在当前规则下一定生成日志。
三类数据如何配合¶
| 数据 | 用途 | 维度与注意事项 |
|---|---|---|
netflow,Network |
谁与谁通信、收发量、连接结果及角色 | 按进程、命名空间、端点等聚合;比较同一观测侧与同一采样配置 |
ebpf_network,Metric |
持续发现节点异常及采集缺口 | 默认 40 个固定字段,仅节点及稳定全局标签;累计值需要看区间增量 |
ebpf_network_event,Logging |
查看异常的具体证据 | problem_type 分类;message 的 JSON 含实体、阶段和最多 3 个代表样本;不是逐包或每连接日志 |
默认节点指标和日志的 service=ebpf 表示采集器服务。异常日志中,业务服务看 message.entity.service,进程看 pid/process_name,所在网络环境看 netns。监听端点和 DNS 事务可能没有 PID;命名空间、网卡事件也不能直接归属某个进程。
下面是实测 TCP 正常短连接的标签节选:
{
"host": "(none)",
"service": "ebpf",
"process_name": "fixture",
"netns": "4026531840",
"transport": "tcp",
"family": "IPv4",
"conn_side": "client",
"direction": "outgoing",
"src_ip": "10.23.0.1",
"src_port": "*",
"dst_ip": "10.23.0.1",
"dst_port": "18080",
"dst_nat_ip": "N/A"
}
host=(none) 是该测试环境的主机标签,生产查询请替换成实际主机名。客户端临时端口聚合成 *;异常样本仍保留可用的具体端口。dst_nat_ip=N/A 表示没有可用的 DNAT 关联,不能据此认定通信没有经过 NAT。conn_side 保留兼容推断行为;需要确认主动/被动角色时,优先使用 tcp_role_observed 字符串字段及日志的 role_source。
从一组正常数据建立基线¶
以下是同一客户端观测侧、同一服务端口的实测字段节选。测试程序发起 1000 次连接,每次写 115 B,读取 146 B;IPv6 用相同负载也得到对应连接数和字节量。下表按当前可选字段规则展示:没有增量的追加计数字段省略,不再填充零值。
| 字段 | 实测值 | 解释 |
|---|---|---|
tcp_connect_attempts |
1000 | 观测到的连接尝试 |
tcp_connect_result_success |
1000 | 该批尝试均有成功结果;其余结果计数字段省略 |
tcp_role_observed |
client |
本窗口首次角色观测均为主动发起连接;这是字符串属性,不是次数 |
bytes_written / bytes_read |
115000 / 146000 B | 与测试负载的应用收发量一致 |
tcp_connect_success_duration_count |
1000 | 可用建立耗时样本数 |
tcp_connect_success_duration_sum_us / max_us |
241721 / 1087 μs | 平均约 0.242 ms,最大约 1.087 ms |
retransmits |
0 | 原有字段保留零值;未观测到 RTO 调用时省略追加字段 tcp_rto_timer_fires |
tcp_closed / tcp_close_wait |
1000 / 536 | 关闭次数与状态进入次数;不是当前存量或故障数 |
1000 次关闭符合正常短连接负载;536 次进入 CLOSE_WAIT 也不表示有 536 条连接长期滞留。判断清理慢应查具体连接的状态和年龄。建立耗时平均值必须用 sum_us / count,它不是业务请求响应时间,也不能计算 P99。
同一逻辑连接两端都部署采集器时,客户端发送和服务端接收描述的是同一批业务数据。先固定 host/conn_side/process_name 和通信端点再比较,避免两端相加。内核段计数还受 GRO/GSO 等 offload 影响,不能用收发段数差直接计算线路丢包率,参见 Linux 网络计数器说明。
从平台查询开始¶
先选故障发生前后的一段时间,查询节点诊断指标,再按问题类型查日志,最后查对应进程的 netflow。下面采用 DQL 基本查询语法;替换 node-a、进程和端点,并按日志所在索引调整查询。查询示例未在客户工作空间执行。
M::ebpf_network:(connection_evidence_complete, connect_refused_total, connect_timeout_total, capture_loss_total, netflow_queue_oldest_age_seconds) {host='node-a'} [15m]
L::ebpf_network_event:(host, problem_type, pid, process_name, netns, scope, message) {host='node-a', problem_type='connect_refused'} [15m] ORDER BY time DESC LIMIT 20
N::netflow:(bytes_written, bytes_read, tcp_connect_attempts, tcp_connect_result_success, tcp_connect_result_failure) {host='node-a', process_name='fixture', conn_side='client', dst_ip='10.23.0.1', dst_port='18080'} [15m]
日志的 message 实际是 JSON 字符串。各篇 JSON 示例展示的是解析后的关键字段节选,不代表完整线协议或日志体。可先在日志详情中读取;工作空间启用 JSON 识别后,才使用 JSON 子字段查询 做进一步过滤。
ebpf_network 的 *_total 是采集器累计观测,不能将连续点求和当作这 15 分钟的事件数。例如同一计数从 12 增至 17,区间新增是 5;采集器重启或来源重建导致回落时应重建基线。netflow 的区间聚合与诊断累计值也不能混用。
设置日常发现规则¶
先建立正常业务时段和发布时段的基线,再调整平台告警窗口。下面是平台监控建议,不改变采集器内置取样阈值。
| 规则 | 建议关注的数据 | 触发后的动作 |
|---|---|---|
| 连接失败增加 | 同侧失败数、成功数、取消与未知结果,及拒绝/超时/不可达分类 | 查异常日志中的进程、端点和阶段;未结束尝试会跨窗口,不能把简单比例当成严格请求失败率 |
| 传输持续受阻 | 重传/RTO 增量,结合零窗口、ACK 停滞或未读积压样本 | 区分对端接收压力、本地消费压力和路径候选问题 |
| DNS 异常增加 | 错误响应、慢响应、未匹配响应,结合抓包能力与损失 | 区分明确返回错误与缺少响应证据,再检查解析器 |
| 证据不完整或延迟 | connection_evidence_complete、能力、损失增量、队列年龄 |
同步提示采集缺口,避免把缺数据解释成业务恢复 |
单条信息级线索不适合直接分页告警。可以采用“连续两个窗口出现,且与业务失败或延迟同时增加”作为初始升级条件;业务允许的 RTT、连接耗时和半关闭时间仍应由业务基线决定。采集器只对已确认的 connect 硬错误,在连续两个完整安静窗口均有成功连接时报告恢复;其余类型没有日志更新不代表恢复。
排障记录最终应保存:故障时间范围、主机和命名空间、受影响进程/服务/端点、代表样本、采集可信度、已经确认的事实、待验证假设以及修复后的同口径对比。单端观测通常能缩小范围,不能确定链路上具体哪一跳丢包。