news 2026/2/25 17:07:15

eBPF技术入门与实战:Linux内核黑科技

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
eBPF技术入门与实战:Linux内核黑科技

前言

三年前第一次听说eBPF,觉得这玩意离我太远——内核开发?那是神仙干的事。

直到前段时间排查一个诡异的网络延迟问题,传统工具都定位不到根因,同事甩给我一个bpftrace脚本,几秒钟就抓到了问题。那一刻我才意识到,eBPF已经不是什么高深莫测的东西,而是实打实能解决问题的生产力工具。

这篇文章是我学习和使用eBPF的一些记录,不讲太多底层原理,主要聊聊怎么用它解决实际问题。

eBPF是什么

简单说,eBPF(extended Berkeley Packet Filter)让你可以在内核里安全地运行自定义程序,而不需要修改内核源码或加载内核模块。

传统的做法要观测内核行为,要么改内核重新编译,要么写个内核模块。两个方案都很重,风险也大。eBPF相当于在内核里开了个"沙盒",你的程序在里面跑,既能访问内核数据,又不会把系统搞崩。

能干什么

  • 网络:高性能负载均衡、DDoS防护、流量过滤
  • 安全:系统调用审计、入侵检测、容器安全
  • 观测:性能分析、延迟追踪、资源监控
  • 调试:内核函数追踪、用户态程序分析

Cloudflare用eBPF扛DDoS,Facebook用它做负载均衡,Cilium用它搞容器网络。这东西已经在生产环境大规模使用了。

环境准备

eBPF需要内核版本支持,最低4.x,建议5.x以上。Ubuntu 20.04/22.04都没问题。

# 检查内核版本uname-r# 5.15.0-91-generic# 安装BCC工具集(最常用的eBPF工具集)aptupdateaptinstall-y bpfcc-tools linux-headers-$(uname-r)# 安装bpftrace(高级追踪语言)aptinstall-y bpftrace# 验证安装bpftrace --version# bpftrace v0.14.0

实战一:追踪系统调用延迟

前几天遇到一个问题:某个Java服务响应变慢,但CPU、内存、IO看着都正常。

用bpftrace追踪一下read系统调用的延迟分布:

# 追踪read调用延迟(按进程名过滤)bpftrace -e' tracepoint:syscalls:sys_enter_read /comm == "java"/ { @start[tid] = nsecs; } tracepoint:syscalls:sys_exit_read /comm == "java" && @start[tid]/ { @usecs = hist((nsecs - @start[tid]) / 1000); delete(@start[tid]); } '

输出:

@usecs: [0] 156 |@@@@@@@@@@@@@@@ | [1] 489 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@| [2, 4) 234 |@@@@@@@@@@@@@@@@@@@@@@@ | [4, 8) 67 |@@@@@@ | [8, 16) 23 |@@ | [16, 32) 12 |@ | [32, 64) 8 | | [64, 128) 3 | | [128, 256) 156 |@@@@@@@@@@@@@@@ | <-- 异常

128-256微秒这个区间的调用数量异常偏多,正常应该是单峰分布。进一步追踪发现是读取某个配置文件时,文件系统有锁竞争。

这种问题用传统工具(strace会拖慢进程太多)很难快速定位,eBPF几乎零开销。

实战二:网络延迟分析

生产环境有台机器TCP延迟偶发飙高,网络组说线路没问题。用tcpretrans追踪重传:

# BCC工具:追踪TCP重传/usr/share/bcc/tools/tcpretrans# 输出TIME PID IP LADDR:LPORT T>RADDR:RPORT STATE14:23:150410.0.1.5:443 R>10.0.2.8:52341 ESTABLISHED14:23:150410.0.1.5:443 R>10.0.2.8:52341 ESTABLISHED14:23:160410.0.1.5:443 R>10.0.2.8:52341 ESTABLISHED

同一个连接连续重传,问题缩小到10.0.2.x这个网段。最后查出来是那个机房的交换机有问题。

更进一步,看TCP连接延迟分布:

# 追踪TCP连接建立延迟/usr/share/bcc/tools/tcpconnlat# 输出PID COMM IP SADDR DADDR DPORT LAT(ms)1892curl410.0.1.510.0.2.8443245.121893curl410.0.1.510.0.2.8443312.451894curl410.0.1.510.0.3.94431.23

对比很明显,连10.0.2网段延迟高了两个数量级。

实战三:进程级资源监控

有个容器CPU用量一直很高,但top里看不出哪个函数在消耗。用profile工具:

# CPU采样火焰图数据/usr/share/bcc/tools/profile -p$(pgrep -f myapp)-f30>profile.out# 生成火焰图(需要安装FlameGraph)gitclone https://github.com/brendangregg/FlameGraph ./FlameGraph/flamegraph.pl profile.out>cpu.svg

火焰图一目了然,发现某个JSON解析函数占了40%的CPU。原来是每次请求都在重复解析同一个大配置文件,加个缓存解决。

实战四:自定义追踪点

有时候需要追踪特定的内核函数。比如想知道文件打开操作的分布:

bpftrace -e' kprobe:do_sys_openat2 { @files[str(arg1)] = count(); } interval:s:5 { print(@files); clear(@files); } '

输出每5秒打印一次文件打开统计:

@files[/etc/ld.so.cache]: 234 @files[/lib/x86_64-linux-gnu/libc.so.6]: 156 @files[/proc/self/status]: 89 @files[/app/config.json]: 67 ...

这种方式对排查"到底谁在频繁读写某个文件"特别有用。

写个简单的eBPF程序

BCC提供Python接口,写起来比较方便。追踪所有的execve调用(新进程启动):

#!/usr/bin/env python3frombccimportBPF# eBPF程序(C语言)prog=""" #include <linux/sched.h> struct data_t { u32 pid; char comm[TASK_COMM_LEN]; }; BPF_PERF_OUTPUT(events); int trace_execve(struct pt_regs *ctx) { struct data_t data = {}; data.pid = bpf_get_current_pid_tgid() >> 32; bpf_get_current_comm(&data.comm, sizeof(data.comm)); events.perf_submit(ctx, &data, sizeof(data)); return 0; } """b=BPF(text=prog)b.attach_kprobe(event="__x64_sys_execve",fn_name="trace_execve")print("追踪新进程启动,Ctrl+C退出...")defprint_event(cpu,data,size):event=b["events"].event(data)print(f"PID:{event.pid}, COMM:{event.comm.decode()}")b["events"].open_perf_buffer(print_event)whileTrue:b.perf_buffer_poll()

运行效果:

追踪新进程启动,Ctrl+C退出... PID: 12345, COMM: bash PID: 12346, COMM: ls PID: 12347, COMM: grep

这对安全审计很有价值——谁在服务器上执行了什么命令,一清二楚。

生产环境使用建议

性能开销

eBPF的开销很低,但不是零。几个原则:

  1. 过滤要前置:在eBPF程序里做过滤,而不是全量采集再在用户态过滤
  2. 采样而非全量:profile用采样,不要每个事件都追踪
  3. 控制输出频率:用interval聚合,不要每个事件都输出

常用工具速查

# 性能分析profile# CPU火焰图offcputime# Off-CPU时间分析runqlat# 运行队列延迟# 网络tcplife# TCP连接生命周期tcpretrans# TCP重传追踪tcpconnlat# TCP连接延迟# 磁盘IObiolatency# 块设备IO延迟biosnoop# 块设备IO追踪ext4slower# ext4慢操作# 内存memleak# 内存泄漏检测cachestat# 缓存命中率# 系统调用execsnoop# 进程启动追踪opensnoop# 文件打开追踪

多机器批量排查

遇到跨多台服务器的问题时,需要同时在多个节点运行eBPF工具做对比分析。这种场景下我会用星空组网先把各个网段的机器串起来,统一管理后再批量跑诊断脚本,比逐台SSH效率高很多。

进阶学习资源

  • 《BPF Performance Tools》by Brendan Gregg - 这本书是圣经级别的
  • bcc官方仓库:github.com/iovisor/bcc - 大量现成工具和示例
  • bpftrace参考:github.com/iovisor/bpftrace - 追踪语言文档
  • Cilium eBPF教程:docs.cilium.io - 网络方向的最佳实践

总结

eBPF不再是内核黑客的专属玩具。对于运维和后端开发来说,它是一个威力巨大的问题排查工具:

  1. 低开销:生产环境可用
  2. 高精度:内核级别的观测能力
  3. 灵活:可以自定义追踪逻辑
  4. 安全:内核保证程序不会搞崩系统

从BCC工具集入手,遇到问题先试试现成工具,熟练后再尝试写自定义追踪程序。这个学习路径比较平滑。

说实话,用惯了eBPF再回头看传统的排查手段,会觉得效率差太多。推荐每个做服务端的同学都了解一下。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/25 13:34:01

3分钟搞定Kazam:Linux最强录屏工具完整安装教程

3分钟搞定Kazam&#xff1a;Linux最强录屏工具完整安装教程 【免费下载链接】kazam Kazam - Linux Desktop Screen Recorder and Broadcaster 项目地址: https://gitcode.com/gh_mirrors/kaz/kazam 还在为Linux系统寻找简单易用的屏幕录制工具而困扰吗&#xff1f;Kazam…

作者头像 李华
网站建设 2026/2/22 22:45:56

企业级文本智能实战指南:从数据到决策的价值挖掘

企业级文本智能实战指南&#xff1a;从数据到决策的价值挖掘 【免费下载链接】monkeylearn-python Official Python client for the MonkeyLearn API. Build and consume machine learning models for language processing from your Python apps. 项目地址: https://gitcode…

作者头像 李华
网站建设 2026/2/21 13:50:09

DsHidMini深度指南:让DualShock 3手柄在Windows上重获新生

DsHidMini深度指南&#xff1a;让DualShock 3手柄在Windows上重获新生 【免费下载链接】DsHidMini Virtual HID Mini-user-mode-driver for Sony DualShock 3 Controllers 项目地址: https://gitcode.com/gh_mirrors/ds/DsHidMini 作为一名游戏爱好者&#xff0c;你是否…

作者头像 李华
网站建设 2026/2/23 17:31:25

如何通过Gephi实现从数据混乱到洞察清晰的三步进阶

如何通过Gephi实现从数据混乱到洞察清晰的三步进阶 【免费下载链接】gephi Gephi - The Open Graph Viz Platform 项目地址: https://gitcode.com/gh_mirrors/ge/gephi 你是否曾经面对复杂的网络数据感到无从下手&#xff1f;看着密密麻麻的节点和连线&#xff0c;却无法…

作者头像 李华
网站建设 2026/2/23 4:36:02

云端游戏桥接方案:便携终端跨平台串流终极指南

云端游戏桥接方案&#xff1a;便携终端跨平台串流终极指南 【免费下载链接】Moonlight-Switch Moonlight port for Nintendo Switch 项目地址: https://gitcode.com/gh_mirrors/mo/Moonlight-Switch 想要在便携式游戏终端上畅玩PC大作&#xff1f;云端游戏桥接方案让这成…

作者头像 李华