eBPF 性能诊断实战:10 分钟定位 Linux 系统 CPU/IO/网络瓶颈
适用场景 & 前置条件
适用场景:生产环境/测试环境下 CPU 飙升、内存泄漏、磁盘 IO 慢、网络丢包/重传等性能问题排查;适合中大规模业务(日 PV 百万级+)。
前置条件:
-
• Linux 内核 4.9+(推荐 5.4+);生产环境建议 5.10+ LTS -
• ROOT 权限或 CAP_BPF + CAP_PERFMON 能力(内核 5.8+) -
• 2C4G 最低配置;生产环境建议 4C8G+ -
• 网络无限制(需安装软件包) -
• 基础 Linux 系统调优经验(熟悉 top/iostat/ss 等工具)
环境与版本矩阵
测试环境:CentOS Stream 9 (内核 5.14.0), Ubuntu 22.04 (内核 5.15.0), BCC 0.28, bpftrace 0.17 | 测试于 2025-10
快速清单 (Checklist)
-
1. ✅ 检查内核版本与 eBPF 支持( uname -r+/boot/config-*验证 CONFIG_BPF) -
2. ✅ 安装 BCC/bpftrace 工具链(区分 RHEL/Ubuntu 包管理器) -
3. ✅ 验证工具可用性( bpftrace -l列出可用探针) -
4. ✅ 诊断 CPU 瓶颈(profile 火焰图 + execsnoop 进程启动 + runqlat 调度延迟) -
5. ✅ 诊断内存瓶颈(memleak 泄漏检测 + slabratetop 内核对象分配) -
6. ✅ 诊断磁盘 IO 瓶颈(biolatency 延迟分布 + biotop 进程 IO 排名) -
7. ✅ 诊断网络瓶颈(tcplife 连接生命周期 + tcpretrans 重传 + tcptop 流量排名) -
8. ✅ 综合案例实战(MySQL 慢查询引发系统负载飙升的全链路诊断) -
9. ✅ 配置监控告警(eBPF exporter + Prometheus 规则) -
10. ✅ 制定回滚方案(安全卸载工具 + 内核参数恢复)
实施步骤
Step 1: 内核检查与 eBPF 支持验证
目标:确认当前内核版本与 eBPF 必需配置项已启用。
1.1 检查内核版本
uname -r
# 预期输出示例(CentOS Stream 9): 5.14.0-362.8.1.el9_3.x86_64
# 预期输出示例(Ubuntu 22.04): 5.15.0-91-generic
要求:版本 >= 4.9;建议 5.4+;生产环境推荐 5.10 LTS 或 5.15 LTS。
1.2 验证 eBPF 内核配置
# RHEL/CentOS
grep CONFIG_BPF /boot/config-$(uname -r)
# Ubuntu
grep CONFIG_BPF /boot/config-$(uname -r)
# 必需配置项输出示例:
# CONFIG_BPF=y
# CONFIG_BPF_SYSCALL=y
# CONFIG_BPF_JIT=y
# CONFIG_HAVE_EBPF_JIT=y
# CONFIG_BPF_EVENTS=y
验证要点:
-
• CONFIG_BPF_SYSCALL=y:eBPF 系统调用支持(必需) -
• CONFIG_BPF_JIT=y:JIT 编译加速(强烈推荐) -
• CONFIG_BPF_EVENTS=y:事件跟踪支持(必需)
1.3 检查 debugfs/tracefs 挂载
mount | grep -E 'debugfs|tracefs'
# 预期输出:
# debugfs on /sys/kernel/debug type debugfs (rw,relatime)
# tracefs on /sys/kernel/tracing type tracefs (rw,relatime)
如未挂载则手动挂载:
mount -t debugfs debugfs /sys/kernel/debug
mount -t tracefs tracefs /sys/kernel/tracing
幂等性保障:写入 /etc/fstab 永久生效
echo"debugfs /sys/kernel/debug debugfs defaults 0 0" >> /etc/fstab
echo"tracefs /sys/kernel/tracing tracefs defaults 0 0" >> /etc/fstab
Step 2: 安装 BCC/bpftrace 工具链
2.1 RHEL/CentOS 安装(通过 EPEL)
# CentOS Stream 8/9 或 RHEL 8/9
dnf install -y epel-release
dnf install -y bcc-tools python3-bcc bpftrace
# 验证安装路径
ls /usr/share/bcc/tools/ # BCC 工具集
which bpftrace # /usr/bin/bpftrace
可选编译安装(需要最新特性时):
dnf install -y cmake make gcc-c++ llvm-devel clang-devel elfutils-libelf-devel
git clone https://github.com/iovisor/bcc.git && cd bcc
mkdir build && cd build
cmake .. -DCMAKE_INSTALL_PREFIX=/usr
make -j$(nproc) && make install
2.2 Ubuntu/Debian 安装
# Ubuntu 20.04/22.04
apt update
apt install -y bpfcc-tools linux-headers-$(uname -r) bpftrace
# 工具路径
ls /usr/sbin/*-bpfcc # BCC 工具(带 -bpfcc 后缀)
which bpftrace # /usr/bin/bpftrace
Ubuntu 注意事项:BCC 工具命名带 -bpfcc 后缀(如 execsnoop-bpfcc),建议创建软链接:
cd /usr/local/bin
for tool in /usr/sbin/*-bpfcc; do
ln -sf $tool $(basename$tool -bpfcc);
done
2.3 验证工具可用性
# 列出可用内核探针(kprobe/tracepoint)
bpftrace -l | head -20
# 预期输出示例(部分):
# kprobe:tcp_sendmsg
# kprobe:tcp_recvmsg
# tracepoint:syscalls:sys_enter_read
# tracepoint:sched:sched_switch
# 快速测试 BCC 工具
/usr/share/bcc/tools/execsnoop -h # RHEL 路径
execsnoop-bpfcc -h # Ubuntu 路径
前后对比验证:
# 安装前
bpftrace -l | wc -l
# 输出: bash: bpftrace: command not found
# 安装后
bpftrace -l | wc -l
# 输出: 5000+ (具体数量取决于内核版本)
Step 3: CPU 瓶颈诊断
3.1 采样 CPU 火焰图(profile)
场景:定位高 CPU 占用的函数调用链。
# 采样 60 秒,频率 99Hz(避免与常见定时器共振)
/usr/share/bcc/tools/profile -adf 99 60 > profile.txt
# 关键参数:
# -a : 采样所有 CPU
# -d : 显示进程/线程 ID
# -f : 显示完整调用栈(含用户态+内核态)
# 99 : 采样频率 Hz
# 60 : 持续时间秒
输出示例(简化):
PID COMM FUNC
2345 mysqld [k] __lock_acquire
[k] mutex_lock
[u] pthread_mutex_lock
[u] my_hash_search
[u] open_table (12345 samples, 23%)
分析要点:
-
• [k]:内核态函数,[u]:用户态函数 -
• 百分比高的调用链即为热点 -
• 配合 FlameGraph 工具生成 SVG 火焰图
# 生成火焰图(需安装 FlameGraph)
git clone https://github.com/brendangregg/FlameGraph
./FlameGraph/flamegraph.pl profile.txt > cpu-flamegraph.svg
3.2 跟踪进程启动(execsnoop)
场景:排查频繁 fork/exec 导致 CPU 抖动。
# 实时监控所有新进程启动
/usr/share/bcc/tools/execsnoop
# 预期输出(示例):
# PCOMM PID PPID RET ARGS
# sh 12345 1234 0 /bin/sh -c /usr/local/bin/check.sh
# python3 12346 12345 0 /usr/bin/python3 /opt/app/monitor.py
关键字段解释:
-
• PCOMM:父进程名称 -
• PID/PPID:进程 ID 与父进程 ID -
• RET:exec 系统调用返回值(0 成功) -
• ARGS:完整命令行参数
故障案例:如发现某脚本每秒启动数十次 → 检查 crontab/systemd timer 配置错误。
3.3 测量调度延迟(runqlat)
场景:CPU 利用率不高但响应慢,可能是调度队列等待时间长。
# 统计 10 秒内调度延迟分布(微秒级直方图)
/usr/share/bcc/tools/runqlat 10 1
# 输出示例:
# usecs : count distribution
# 0 -> 1 : 1234 |********* |
# 2 -> 3 : 5678 |****************************************|
# 4 -> 7 : 2345 |***************** |
# 8 -> 15 : 890 |****** |
# 16 -> 31 : 234 |** |
# 32 -> 63 : 67 | |
# 64 -> 127 : 12 | |
分析要点:
-
• 延迟中位数(P50)应 < 10µs;P99 应 < 100µs -
• 若大量任务延迟 > 1ms → 检查 CPU 核数/超线程/中断绑定 -
• 配合 mpstat -P ALL 1验证各核负载是否均衡
Step 4: 内存瓶颈诊断
4.1 检测内存泄漏(memleak)
场景:应用程序内存持续增长且不释放。
# 跟踪 PID 12345 的内存分配/释放,每 5 秒统计一次
/usr/share/bcc/tools/memleak -p 12345 5
# 输出示例:
# 8192 bytes in 64 allocations from stack
# malloc+0x28 [libc.so.6]
# _Znwm+0x1c [libstdc++.so.6]
# app::BufferPool::allocate+0x45 [myapp]
# app::handleRequest+0x123 [myapp]
关键参数:
-
• -p PID:指定进程(不指定则跟踪整个系统) -
• -t:显示线程 ID -
• -a:显示每次分配详情(数据量大,慎用)
验证前后:
# 观察前
ps aux | awk 'NR==1 || /myapp/ {print $6}'
# 输出: 204800 (RSS KB)
# 运行 memleak 5 分钟后再次观察
# 输出: 307200 (RSS KB, 增长 100MB)
# memleak 输出显示某函数未释放 → 修复代码后重启应用
# 修复后观察: 205000 (RSS KB, 稳定)
4.2 内核内存分配热点(slabratetop)
场景:内核 slab 内存增长快,排查内核对象泄漏。
# 实时显示 slab 分配速率(每秒刷新)
/usr/share/bcc/tools/slabratetop 1
# 输出示例:
# CACHE ALLOCS BYTES
# kmalloc-512 123456 63234048
# inode_cache 45678 29393920
# dentry 34567 8863744
分析要点:
-
• ALLOCS持续增长无回落 → 可能泄漏 -
• 对比 slabtop静态视图确认总量 -
• 重点关注 kmalloc-*(通用分配)和dentry/inode_cache(文件系统)
Step 5: 磁盘 IO 瓶颈诊断
5.1 IO 延迟分布(biolatency)
场景:磁盘 IO 慢,定位是设备层面还是应用层面。
# 统计 10 秒内块 IO 延迟(毫秒级直方图)
/usr/share/bcc/tools/biolatency -m 10 1
# 输出示例(-m 表示毫秒单位):
# msecs : count distribution
# 0 -> 1 : 12345 |****************************************|
# 2 -> 3 : 3456 |*********** |
# 4 -> 7 : 890 |*** |
# 8 -> 15 : 234 |* |
# 16 -> 31 : 67 | |
# 32 -> 63 : 12 | |
关键指标:
-
• SSD 应 < 5ms (P99);HDD 应 < 20ms (P99) -
• 若大量 IO > 100ms → 检查磁盘健康度(smartctl)或队列深度
前后对比验证:
# 优化前(RAID 5 机械盘)
# P99 延迟: 64-127ms
# 优化后(换 SSD + 调整 IO 调度器为 none)
echo none > /sys/block/nvme0n1/queue/scheduler
# P99 延迟: 2-3ms
5.2 进程 IO 排名(biotop)
场景:定位哪个进程产生大量 IO。
# 每 5 秒刷新一次,显示 Top 10 进程
/usr/share/bcc/tools/biotop 5
# 输出示例:
# PID COMM D MAJ MIN DISK I/O Kbytes AVGms
# 12345 mysqld R 259 0 nvme0n1 8912 356480 2.3
# 23456 rsync W 8 0 sda 4567 912340 18.7
关键字段:
-
• D:方向(R 读/W 写) -
• I/O:操作次数 -
• Kbytes:总数据量 -
• AVGms:平均延迟
故障案例:发现某日志进程每秒写入 100MB → 调整日志级别或异步刷盘。
5.3 IO 大小分布(bitesize)
场景:分析 IO 请求大小是否合理(小 IO 频繁 vs 大 IO 稀疏)。
/usr/share/bcc/tools/bitesize
# 输出(简化):
# Process Name = mysqld
# Kbytes : count distribution
# 0 -> 1 : 0 | |
# 2 -> 3 : 0 | |
# 4 -> 7 : 1234 |*********** |
# 8 -> 15 : 3456 |********************************* |
# 16 -> 31 : 4567 |****************************************|
优化建议:
-
• 大量 4KB 小 IO → 考虑启用 Readahead 或增大应用 buffer -
• 全是 16KB IO → 检查 InnoDB 页大小或文件系统块大小配置
Step 6: 网络瓶颈诊断
6.1 TCP 连接生命周期(tcplife)
场景:排查短连接过多或连接异常关闭。
/usr/share/bcc/tools/tcplife
# 输出示例:
# PID COMM LADDR LPORT RADDR RPORT TX_KB RX_KB MS
# 1234 nginx 192.168.1.10 80 192.168.1.100 54321 12 456 1234
# 2345 curl 192.168.1.10 54322 8.8.8.8 443 0.5 2.3 89
关键字段:
-
• TX_KB/RX_KB:发送/接收流量 -
• MS:连接持续时间(毫秒) -
• MS < 100且大量出现 → 短连接风暴,建议连接池/长连接
验证前后:
# 优化前(PHP-FPM 短连接 MySQL)
# MS 平均 50ms,每秒 500 条新连接
# 优化后(启用持久连接)
# MS 平均 30000ms(30秒),每秒 20 条新连接
6.2 TCP 重传监控(tcpretrans)
场景:网络质量差或拥塞导致丢包重传。
/usr/share/bcc/tools/tcpretrans
# 输出示例:
# TIME PID IP LADDR:LPORT T> RADDR:RPORT STATE
# 12:34:56 1234 4 192.168.1.10:80 R> 192.168.1.100:54321 ESTABLISHED
# 12:34:58 1234 4 192.168.1.10:80 R> 192.168.1.100:54321 ESTABLISHED
关键标识:
-
• T>后面的R表示重传 -
• 高频出现 → 检查网络链路( mtr/ethtool -S查看丢包)、拥塞窗口、MTU
配合验证:
# 查看网卡错误统计
ethtool -S eth0 | grep -E 'tx_errors|rx_errors|retrans'
# 查看 TCP 重传计数器
netstat -s | grep -i retrans
# 优化前: 12345 segments retransmitted
# 优化后: 123 segments retransmitted (降低 100 倍)
6.3 TCP 流量排名(tcptop)
场景:定位哪些连接/进程占用带宽。
/usr/share/bcc/tools/tcptop 5
# 输出示例(每 5 秒刷新):
# PID COMM LADDR LPORT RADDR RPORT RX_KB TX_KB
# 12345 nginx 192.168.1.10 80 192.168.1.100 54321 12340 4567
# 23456 python3 192.168.1.10 8080 10.0.0.5 9000 890 23450
分析要点:
-
• 单连接占用 > 网卡带宽 50% → 考虑 QoS 限流 -
• 进程 TX_KB远大于RX_KB→ 上传型服务(备份/CDN 回源)
Step 7: 综合案例 - MySQL 慢查询引发系统负载飙升
故障现象:
-
• 系统 Load Average 从 2 飙升至 50+ -
• MySQL 响应时间 P99 从 10ms 增至 5000ms -
• CPU iowait 从 5% 升至 40%
诊断流程(5 步定位根因):
7.1 确认 CPU 瓶颈来源
# 采样火焰图
/usr/share/bcc/tools/profile -p $(pidof mysqld) -f 30 > mysql-profile.txt
# 发现热点: InnoDB 行锁等待(row_lock_wait)占比 60%
7.2 检查磁盘 IO 是否饱和
/usr/share/bcc/tools/biotop 5
# 输出显示 mysqld 每秒读取 50000 IOPS,延迟 P99 = 120ms
# 磁盘: SATA SSD,理论 IOPS 上限 80000(接近饱和)
7.3 定位慢查询 SQL
# 使用 MySQL 慢查询日志(非 eBPF,配合使用)
tail -f /var/log/mysql/slow.log
# 发现: SELECT * FROM orders WHERE status='pending' (全表扫描 500 万行)
7.4 跟踪锁等待调用链
# 自定义 bpftrace 脚本跟踪 InnoDB mutex
bpftrace -e '
kprobe:mutex_lock /comm == "mysqld"/ {
@start[tid] = nsecs;
}
kretprobe:mutex_lock /comm == "mysqld" && @start[tid]/ {
$lat = nsecs - @start[tid];
if ($lat > 10000000) { // > 10ms
printf("TID %d lock latency: %d ms\n", tid, $lat/1000000);
}
delete(@start[tid]);
}
'
# 输出: 大量线程锁等待 > 100ms
7.5 验证索引优化效果
# 前: 无索引,全表扫描
EXPLAIN SELECT * FROM orders WHERE status='pending'\G
# rows: 5000000, Extra: Using where
# 添加索引
ALTER TABLE orders ADD INDEX idx_status (status);
# 后: 索引扫描
# rows: 12340, Extra: Using index condition
# 再次观察 biolatency
/usr/share/bcc/tools/biolatency -m 10 1
# P99 延迟降至 8ms(优化前 120ms)
效果对比:
Step 8: 数据导出与可视化(Prometheus + Grafana)
8.1 安装 eBPF Exporter
# 下载二进制(示例版本 v2.3.0)
wget https://github.com/cloudflare/ebpf_exporter/releases/download/v2.3.0/ebpf_exporter-2.3.0.linux-amd64.tar.gz
tar xf ebpf_exporter-2.3.0.linux-amd64.tar.gz
cp ebpf_exporter /usr/local/bin/
# 创建配置文件 /etc/ebpf_exporter/config.yaml
mkdir -p /etc/ebpf_exporter
cat > /etc/ebpf_exporter/config.yaml <<'EOF'
programs:
- name: biolatency
metrics:
histograms:
- name: bio_latency_seconds
help: Block I/O latency histogram
table: dist
bucket_type: exp2
bucket_multiplier: 0.000001 # 转换为秒
labels:
- name: device
size: 32
decoders:
- name: string
kprobes:
blk_account_io_done: trace_block_io_done
code: |
// 简化示例,完整代码见官方仓库
BPF_HISTOGRAM(dist, u64);
EOF
# 启动服务(监听 9435 端口)
ebpf_exporter --config.file=/etc/ebpf_exporter/config.yaml &
8.2 Prometheus 抓取配置
# prometheus.yml 新增 scrape_configs
scrape_configs:
-job_name:'ebpf'
static_configs:
-targets: ['localhost:9435']
labels:
instance:'prod-server-01'
8.3 Grafana 面板示例查询
# 磁盘 IO P99 延迟(毫秒)
histogram_quantile(0.99,
sum(rate(bio_latency_seconds_bucket[5m])) by (le, device)
) * 1000
# TCP 重传率(每秒)
rate(tcpretrans_total[5m])
# 内存泄漏趋势(堆内存未释放 MB)
sum(memleak_bytes{pid="12345"}) / 1024 / 1024
Grafana 面板建议:
-
• Panel 1: 磁盘 IO 延迟热力图(Heatmap) -
• Panel 2: TCP 重传/连接数时序图(Graph) -
• Panel 3: CPU 火焰图集成(需插件 grafana-piechart-panel)
监控与告警
Prometheus 告警规则示例
groups:
-name:ebpf_alerts
interval:30s
rules:
# 磁盘 IO P99 延迟 > 100ms
-alert:HighDiskLatency
expr:|
histogram_quantile(0.99,
sum(rate(bio_latency_seconds_bucket[5m])) by (le, device)
) > 0.1
for:2m
labels:
severity:warning
annotations:
summary:"磁盘 {{ $labels.device }} 延迟过高"
description:"P99 延迟 {{ $value | humanizeDuration }}"
# TCP 重传率 > 1%
-alert:HighTCPRetrans
expr:|
rate(tcpretrans_total[5m]) / rate(tcp_segments_sent[5m]) > 0.01
for:5m
labels:
severity:critical
annotations:
summary:"TCP 重传率异常"
# 内存泄漏检测(进程 RSS 持续增长 > 10% /小时)
-alert:MemoryLeak
expr:|
(process_resident_memory_bytes - process_resident_memory_bytes offset 1h)
/ process_resident_memory_bytes offset 1h > 0.1
for:30m
labels:
severity:warning
原生命令监控(无 Prometheus)
# 每分钟记录磁盘 IO 延迟到日志
whiletrue; do
/usr/share/bcc/tools/biolatency -m 10 1 | grep -A20 'msecs' >> /var/log/biolatency.log
sleep 60
done &
# 定时检查 TCP 重传
watch -n 10 'netstat -s | grep retrans'
性能与容量
eBPF 工具开销基准测试
测试环境:4C8G 虚拟机,CentOS Stream 9,无业务负载
容量规划建议:
-
• 单机同时运行 ≤ 5 个 eBPF 工具 -
• profile/memleak 仅在故障排查时启用(开销大) -
• 采样频率折中选择(99Hz vs 999Hz,性能 vs 精度) -
• 日志轮转:eBPF 输出重定向时需配置 logrotate
生产环境限流策略
# 限制 profile 仅采样 10 秒(避免长时间占用)
timeout 10s /usr/share/bcc/tools/profile -f 99 > profile.txt
# 限制 memleak 仅跟踪特定内存分配大小(过滤噪音)
/usr/share/bcc/tools/memleak -p 12345 -o 1048576 # 仅跟踪 ≥1MB 分配
# cgroup 限制 eBPF 工具 CPU 使用(内核 5.x+)
cgcreate -g cpu:/ebpf_tools
cgset -r cpu.cfs_quota_us=50000 ebpf_tools # 限制 50% 单核
cgexec -g cpu:ebpf_tools /usr/share/bcc/tools/profile -f 99 60
安全与合规
权限最小化(内核 5.8+ 推荐)
# 传统方式: 需要 root(风险大)
sudo /usr/share/bcc/tools/execsnoop
# 细粒度权限(推荐): 仅授予 CAP_BPF + CAP_PERFMON
setcap cap_bpf,cap_perfmon=ep /usr/share/bcc/tools/execsnoop
# 普通用户即可运行
/usr/share/bcc/tools/execsnoop
验证权限:
getcap /usr/share/bcc/tools/execsnoop
# 输出: cap_bpf,cap_perfmon=ep
审计日志记录
# 记录所有 eBPF 程序加载事件(需 auditd)
auditctl -a always,exit -F arch=b64 -S bpf -k ebpf_load
# 查看审计日志
ausearch -k ebpf_load
# 输出示例:
# type=SYSCALL msg=audit(1697123456.789:12345): arch=c000003e syscall=321 success=yes pid=23456 comm="bpftrace"
内核兼容性矩阵
兼容性测试命令:
# 检查 BTF 支持(CO-RE 依赖)
ls /sys/kernel/btf/vmlinux
# 存在则支持;不存在则需编译时启用 CONFIG_DEBUG_INFO_BTF
# 检查 bpf() syscall
strace -e bpf bpftrace -e 'BEGIN { exit(); }' 2>&1 | grep 'bpf('
# 输出包含 'bpf(' 则支持
常见故障与排错
关键错误码速查
# EPERM (Operation not permitted)
# 原因: 权限不足
# 解决: sudo 或 setcap cap_bpf,cap_perfmon=ep
# ENOSPC (No space left on device)
# 原因: BPF map 空间耗尽
# 解决: 调整 map 大小或增大 RLIMIT_MEMLOCK
# EINVAL (Invalid argument)
# 原因: 内核版本不支持某 BPF 特性
# 解决: 升级内核或使用兼容版本工具
变更与回滚剧本
维护窗口建议
-
• 测试环境:无限制,可随时安装/卸载 -
• 生产环境:建议在业务低峰期(凌晨 2-6 点)首次部署;常驻工具(execsnoop/biolatency)可在线启用
灰度策略
# 阶段 1: 单台测试服务器验证 7 天
# 阶段 2: 10% 生产节点部署(监控 CPU/内存开销)
# 阶段 3: 全量部署(保留 1-2 台回滚对照组)
健康检查脚本
#!/bin/bash
# ebpf_health_check.sh
# 检查工具是否正常响应
timeout 5s bpftrace -e 'BEGIN { exit(); }' || exit 1
# 检查内核日志无 BPF 错误
dmesg | tail -100 | grep -i 'bpf.*error' && exit 1
# 检查 CPU 开销 < 5%
ebpf_cpu=$(ps aux | grep -E 'bpftrace|bcc' | awk '{sum+=$3} END {print sum}')
(( $(echo "$ebpf_cpu > 5" | bc -l) )) && exit 1
echo"eBPF tools healthy"
exit 0
回滚条件与命令
触发条件:
-
• CPU 开销 > 10% 持续 5 分钟 -
• 内核日志出现 BPF verifier error -
• 业务监控指标(P99 延迟/错误率)突增 > 20%
立即回滚:
# 停止所有 eBPF 工具进程
pkill -9 bpftrace
pkill -9 python3 # BCC 工具是 Python 脚本
killall profile execsnoop biolatency
# 卸载 eBPF exporter
systemctl stop ebpf_exporter
systemctl disable ebpf_exporter
# 验证无残留 BPF 程序
bpftool prog show | wc -l
# 输出应为 0 或仅剩系统默认程序
数据/配置备份:
# 备份配置
tar czf /backup/ebpf-config-$(date +%F).tar.gz \
/etc/ebpf_exporter/ \
/usr/local/bin/ebpf_exporter \
/etc/systemd/system/ebpf_exporter.service
# 恢复配置
tar xzf /backup/ebpf-config-2025-10-20.tar.gz -C /
最佳实践
-
1. 采样频率权衡:profile 使用 49/99 Hz(避免与 100 Hz 定时器共振);生产环境避免 > 999 Hz -
2. 工具组合原则:CPU 瓶颈用 profile + runqlat;IO 瓶颈用 biolatency + biotop;内存用 memleak + slabratetop -
3. 符号表必备:安装 debuginfo 包( debuginfo-installRHEL /apt install *-dbgsymUbuntu) -
4. CO-RE 优先:内核 5.2+ 使用 libbpf-tools(一次编译到处运行),避免每台机器装内核头文件 -
5. 权限最小化:生产环境使用 CAP_BPF + CAP_PERFMON 替代 root(内核 5.8+) -
6. 日志轮转:eBPF 输出重定向时配置 logrotate(避免磁盘占满) -
7. 限流保护:memleak/profile 使用 timeout 限制运行时间;cgroup 限制 CPU 使用 -
8. 监控工具本身:通过 ps aux | grep bpf定期检查工具 CPU/内存占用 -
9. 内核版本统一:生产环境统一使用 LTS 内核(5.10/5.15),避免工具兼容性问题 -
10. 回滚预案:保留 1-2 台未部署 eBPF 的对照服务器;准备一键停止脚本
附录
A. BCC 工具速查表(Top 20)
B. bpftrace 一行脚本集合
# 跟踪所有 TCP 连接建立
bpftrace -e 'kprobe:tcp_connect { printf("%s -> %s\n", comm, ntop(2, ((struct sock *)arg0)->__sk_common.skc_daddr)); }'
# 统计系统调用耗时 Top 10
bpftrace -e 'tracepoint:raw_syscalls:sys_enter { @start[tid] = nsecs; } tracepoint:raw_syscalls:sys_exit /@start[tid]/ { @[comm] = hist(nsecs - @start[tid]); delete(@start[tid]); }'
# 跟踪文件删除操作
bpftrace -e 'kprobe:vfs_unlink { printf("%s deleted %s\n", comm, str(((struct dentry *)arg1)->d_name.name)); }'
# 统计内存页分配来源
bpftrace -e 'kprobe:__alloc_pages_nodemask { @[kstack] = count(); }'
# 监控 MySQL 查询(需编译时保留符号)
bpftrace -e 'usdt:/usr/sbin/mysqld:mysql:query__start { printf("%s\n", str(arg0)); }'
C. Prometheus eBPF Exporter 完整配置示例
# /etc/ebpf_exporter/config.yaml
programs:
-name:bio_latency
metrics:
histograms:
-name:bio_latency_seconds
help:BlockI/Olatencyhistogram
table:dist
bucket_type:exp2
bucket_min:0
bucket_max:100
bucket_multiplier:0.000001
labels:
-name:device
size:32
decoders:
-name:string
-name:operation
size:8
decoders:
-name:uint
-name:bucket
size:8
decoders:
-name:uint
kprobes:
blk_account_io_done:trace_done
code:|
#include <linux/blkdev.h>
BPF_HISTOGRAM(dist, struct hist_key, 512);
struct hist_key {
char device[32];
u64 slot;
};
int trace_done(struct pt_regs *ctx, struct request *req) {
struct hist_key key = {};
bpf_probe_read_kernel_str(&key.device, sizeof(key.device), req->rq_disk->disk_name);
u64 delta = bpf_ktime_get_ns() - req->start_time_ns;
key.slot = bpf_log2l(delta / 1000);
dist.increment(key);
return 0;
}
-name:tcp_retrans
metrics:
counters:
-name:tcp_retrans_total
help:TCPretransmitcount
table:counts
labels:
-name:saddr
size:4
decoders:
-name:inet_ip
-name:daddr
size:4
decoders:
-name:inet_ip
kprobes:
tcp_retransmit_skb:trace_retrans
code:|
BPF_HASH(counts, u64);
int trace_retrans(struct pt_regs *ctx, struct sock *sk) {
u64 key = sk->__sk_common.skc_daddr;
counts.increment(key);
return 0;
}
D. Nginx/MySQL 典型配置与 eBPF 集成
Nginx 访问日志关联 eBPF:
# nginx.conf
log_format ebpf_trace '$remote_addr - $remote_user [$time_local] "$request" '
'$status$body_bytes_sent "$http_referer" '
'"$http_user_agent" rt=$request_time pid=$pid';
access_log /var/log/nginx/access.log ebpf_trace;
配合 bpftrace 跟踪高延迟请求:
bpftrace -e '
tracepoint:syscalls:sys_exit_write /comm == "nginx"/ {
$lat = (nsecs - @start[tid]) / 1000000;
if ($lat > 100) { // > 100ms
printf("PID %d slow write: %d ms\n", pid, $lat);
}
}
'
MySQL 慢查询与 biolatency 联动:
-- my.cnf
[mysqld]
slow_query_log =1
slow_query_log_file =/var/log/mysql/slow.log
long_query_time =0.1 # 100ms
实时关联分析:
# 终端 1: 监控磁盘 IO
/usr/share/bcc/tools/biolatency -m 1
# 终端 2: 解析慢查询日志
tail -f /var/log/mysql/slow.log | grep 'Query_time'
# 关联发现: 慢查询峰值时刻,biolatency P99 从 5ms 升至 80ms
文档版本:v1.0 | 测试环境:RHEL 9 (5.14), Ubuntu 22.04 (5.15), BCC 0.28, bpftrace 0.17 | 更新日期:2025-10
文末福利
网络监控是保障网络系统和数据安全的重要手段,能够帮助运维人员及时发现并应对各种问题,及时发现并解决,从而确保网络的顺畅运行。
谢谢一路支持,给大家分享6款开源免费的网络监控工具,并准备了对应的资料文档,建议运维工程师收藏(文末一键领取)。

100%免费领取
一、zabbix
二、Prometheus
内容较多,6款常用网络监控工具(zabbix、Prometheus、Cacti、Grafana、OpenNMS、Nagios)不再一一介绍, 需要的朋友扫码备注【监控合集】,即可100%免费领取。
以上所有资料获取请扫码

100%免费领取
(后台不再回复,扫码一键领取)

