【可观测性工程】eBPF 可观测性全景:bcc、bpftrace、libbpf 的工程路径
eBPF 如何实现零侵入、内核级、低开销的可观测性:从 kprobe/uprobe/tracepoint/fentry 钩子机制,到 bcc 工具集、bpftrace 脚本语言、libbpf+CO-RE 可移植编程,再到 Pixie、DeepFlow、Grafana Beyla 等商业化工具,结合内核版本兼容性与生产部署实战。
发布来自土法炼钢兴趣小组的知识、笔记、进展和应用。主题包括数据结构和算法、编程语言、网络安全、密码学等。
共 30 篇文章 · 返回首页
eBPF 如何实现零侵入、内核级、低开销的可观测性:从 kprobe/uprobe/tracepoint/fentry 钩子机制,到 bcc 工具集、bpftrace 脚本语言、libbpf+CO-RE 可移植编程,再到 Pixie、DeepFlow、Grafana Beyla 等商业化工具,结合内核版本兼容性与生产部署实战。
从内核源码拆解 Linux 网络丢包追踪的完整体系:kfree_skb tracepoint 与 80+ 种 drop_reason 枚举、drop_monitor netlink 子系统、dropwatch 工具、perf 丢包记录、bpftrace 丢包聚合脚本,以及生产环境常见丢包点速查表。
从内核 tracepoint 定义出发,系统讲解 bpftrace、perf、ftrace 三大工具在网络诊断中的实战用法:TCP 重传根因分析、softirq 延迟定位、收发包路径延迟剖析、conntrack 表满监控、per-function 火焰图,以及各工具的适用场景与性能开销对比。
从内核源码全面拆解 eBPF 在网络子系统中的所有挂载点:TC BPF direct-action 模式与 bpf_mprog 多程序链、XDP 驱动级钩子回顾、socket ops 回调与 TCP 生命周期事件、cgroup BPF 策略控制、sk_msg/sk_skb 的 sockmap 重定向引擎、struct_ops 实现自定义拥塞控制,以及 bpftrace 可观测实战。
从内核源码拆解 XDP 的完整实现:xdp_buff 数据结构、驱动级钩子、五种动作路径、AF_XDP 零拷贝通道、devmap/cpumap/xskmap 重定向机制、多缓冲区支持,以及 bpftrace 可观测实战。
从内核源码拆解网络子系统的内存管理全貌:sk_buff 分配路径与 slab 缓存、page_pool 页面回收机制、NUMA 感知分配策略、socket 内存记账与反压,以及 bpftrace 可观测实战。
单队列网卡的时代早已过去,但多队列本身只是起点——如何把包分到正确的 CPU 上,才是性能的关键。本文从 Linux 6.6 内核源码拆解多队列网络的完整流量分发体系:RSS 硬件哈希与 Toeplitz 算法、RPS 软件多队列模拟与 get_rps_cpu() 路径、RFS 应用感知的 rps_sock_flow_table 机制、XPS 发送端 CPU/队列亲和、aRFS 硬件流表加速,以及 netdev_pick_tx() 发送队列选择逻辑。
隧道是 overlay 网络的基础设施。本文从 Linux 6.6 内核源码拆解四类隧道协议的实现:ip_tunnel 通用框架与 struct ip_tunnel_key 元数据、IPIP 最小开销封装、GRE 可选头部与 ERSPAN 集成、VXLAN 的 UDP 封装路径与 FDB 转发表、metadata mode 流式隧道与 OVS/Cilium 集成、WireGuard 的 Noise 协议与加密路由模型,以及各协议的封装开销与硬件卸载能力对比。
容器网络不能没有虚拟设备。本文从 Linux 6.6 内核源码拆解四类核心虚拟网络设备的实现:veth pair 的 veth_xmit 零拷贝转发与 XDP native 模式、Linux bridge 的 br_handle_frame 转发路径与 FDB 学习/老化机制、macvlan 五种模式的内核实现差异、tun/tap 的内核态与用户态数据交换路径,以及各类设备的性能特征对比。
容器网络的一切隔离能力,都建立在网络命名空间之上。本文从 Linux 6.6 内核源码拆解 struct net 的完整布局、possible_net_t 与 RCU 访问模式、pernet_operations 子系统注册与生命周期回调、copy_net_ns() 命名空间创建路径、per-netns 路由表/netfilter/socket 隔离机制,以及 veth pair 跨命名空间数据转发的 skb->dev 切换原理。
dev_queue_xmit() 不是直接把包交给网卡——中间还有一层 Traffic Control。本文从 Linux 6.6 内核源码拆解 TC 框架的完整实现:struct Qdisc 与 Qdisc_ops 操作表、pfifo_fast/fq_codel/HTB/TBF 的内核实现差异、TCQ_F_CAN_BYPASS 快路径、TCQ_F_NOLOCK 无锁排队、EDT(Earliest Departure Time)调度模型、TC BPF direct-action 模式,以及 MQ 多队列根 qdisc 与 netdev_queue 的关系。
iptables/nftables 只是用户态前端——真正拦截每一个网络包的是内核中的 Netfilter 框架。本文从 Linux 6.6 内核源码拆解 Netfilter 的三大核心:nf_hook_entries 钩子链的注册与遍历、nf_conn 连接跟踪的双向元组哈希表与 GC 机制、NAT 的 SNAT/DNAT 转换路径;以及 nf_tables 相比 iptables 的关键架构升级——generation-based 无锁更新和 blob 化规则存储。
IP 包到了 ip_rcv_finish(),下一跳怎么选?本文深入拆解 Linux 路由子系统的完整实现:fib_table 的 LC-trie 数据结构、fib_info/fib_nh 的内存布局、fib_rules 策略路由链、ECMP 多路径哈希选路、nexthop 对象 API、FNHE 异常缓存(路由缓存的替代品)、dst_entry 与 rtable 的关系、IPv6 fib6 差异,以及 bpftrace 追踪路由决策的实战方法。
IP 层知道下一跳是 10.0.0.1,但网卡发帧需要 MAC 地址。ARP 解析只是表面——底层是邻居子系统(neighbour subsystem)的完整状态机:NUD_INCOMPLETE → NUD_REACHABLE → NUD_STALE → NUD_DELAY → NUD_PROBE → NUD_FAILED。本文从 Linux 6.6 内核源码拆解 struct neighbour、neigh_table 双哈希表、ARP 请求/响应处理、NDP(IPv6)、Proxy ARP、GC 回收机制,以及 neigh_connected_output 快路径的 L2 头缓存优化。
你调用 socket(AF_INET, SOCK_STREAM, 0) 创建一个 TCP 连接,底层发生了什么?内核分配了两个核心对象——VFS 层的 struct socket 和协议层的 struct sock,通过 proto_ops 和 proto 两张分发表,把文件系统语义的 read/write 翻译成协议语义的 tcp_sendmsg/tcp_recvmsg。本文从 Linux 6.6 内核源码拆解 socket 创建、双层分发、SO_REUSEPORT 多核分发、epoll 集成的完整实现。
UDP 简单?在内核中它一点都不简单。双哈希表 socket 查找、SO_REUSEPORT 多核分发、Early Demux 路由缓存、UDP GRO 聚合、reader_queue 无锁读、forward allocation 内存管理、UDP 封装(ESP/L2TP/VXLAN)——本文从 Linux 6.6 内核源码拆解 UDP 的每一个优化细节。
tcp_sendmsg 把用户数据拷到 sk_buff 就完事了?远没有。后面还有 Nagle 合并、TSQ 限流、cwnd/rwnd 双窗口门控、RACK-TLP 丢包检测、拥塞状态机五态跳转、sk_pacing_rate 软件限速。本文从 Linux 6.6 内核源码拆解 TCP 数据传输的完整路径——从 send() 到 ACK 处理——以及拥塞控制框架 tcp_congestion_ops 的可插拔架构。
TCP 连接在内核中不只是一个状态机——它是一组精心设计的数据结构和队列。本文从 Linux 6.6 内核源码出发,拆解 TCP 连接建立的 SYN Queue / Accept Queue 二级队列模型、request_sock 半连接对象、tcp_sock 全连接对象、SYN Cookie 无状态防御、TCP Fast Open 零 RTT 机制、inet_timewait_sock 轻量级 TIME_WAIT 实现,以及完整的 TCP 状态机在内核中的真实转换路径。
IP 层是 Linux 网络栈的中枢——收包时决定本地投递还是转发,发包时查路由、过 Netfilter、做分片。本文从 Linux 6.6 内核源码出发,拆解 ip_rcv → 路由决策 → ip_local_deliver / ip_forward 的完整路径,深入 FIB 表的 LC-trie 实现、策略路由 ip rule 选表机制、IP 分片/重组状态机、PMTU 发现与 FNHE 缓存,以及 Netfilter 五个钩子点的实际调用时机。
网络包到达网卡后,真正消耗 CPU 的处理全部发生在软中断上下文。本文从 Linux 6.6 内核源码出发,拆解 softirq 10 向量优先级体系、__do_softirq() 主循环与 MAX_SOFTIRQ_RESTART 放弃策略、ksoftirqd 调度时机、Threaded NAPI 替代方案,以及 CONFIG_PREEMPT_RT 下的行为变化。最后用 bpftrace/perf 实测软中断延迟和 time_squeeze 饥饿。
一个用户态 send() 调用要走过 TCP 分段、IP 路由、Netfilter 钩子、Qdisc 排队、GSO 分段、驱动 DMA 映射六个阶段才能把数据送上网线。本文从 Linux 6.6 内核源码出发,逐函数拆解完整的 TX 发包路径,深入 TSQ 限流、Qdisc 调度、BQL 防膨胀、GSO/TSO 分段决策等核心机制。
一个网络包从网卡 DMA 到用户态 recvmsg(),要走过硬中断、NAPI 轮询、GRO 聚合、协议分发、IP 路由、Netfilter 钩子、TCP/UDP 处理、socket 队列八个阶段。本文从 Linux 6.6 内核源码出发,逐函数拆解完整的 RX 收包路径,量化每一跳的 CPU 开销,并用 bpftrace 实测各阶段延迟分布。
sk_buff 是 Linux 内核网络栈的通用货币——每一个收到或发出的网络包,都必须装在这个容器里走完全程。本文从 Linux 6.6 内核源码出发,拆解 sk_buff 的内存布局、四大指针操作、clone 与 copy 的代价差异、skb_shared_info 的 fragment 机制,并用 bpftrace 实测 sk_buff 分配热点和生命周期。
用户抱怨「慢」时第一问题:是 CPU 本身跑得慢,还是调度器让你等?本文讲 runq latency、wakeup latency、block time 三线拆分;perf sched、bpftrace runqlat、schedviz 工具链;生产案例:CFS quota throttle、NUMA 迁移、PSI 告警。
系统梳理 Linux I/O 性能分析工具——iostat、blktrace、BCC/bpftrace、ftrace、perf 的使用方法,以及 I/O 瓶颈排查流程与常见问题模式
系统讲解 eBPF 在网络诊断中的工程应用:bcc 工具集(tcplife/tcpretrans/tcpdrop)的使用场景、bpftrace 自定义网络探针编写、XDP 丢包分析、内核协议栈延迟追踪,建立基于 eBPF 的系统化网络诊断方法。
一份面向线上事故的事件驱动代码排障手册:从症状收敛、strace/eBPF/perf 逐层下钻,到 OpenTelemetry 集成与 Sanitizer 离线复盘。
从 NIC 驱动到用户态 read(),一个网络包在 Linux 内核中到底经历了什么?本文拆解 sk_buff、NAPI、softirq、netfilter 的完整收包路径,并用 bpftrace 实测追踪每一跳的延迟。
你的 P99 延迟突然飙到 500ms,但平均值只有 3ms。日志里什么都没有,Prometheus 图表一片祥和。bpftrace 一行命令,30 秒定位问题。这篇文章告诉你怎么做到的。
你有火焰图,但它只能告诉你 CPU 在忙什么——CPU 不忙的时候呢?从 perf 到 Parca,Linux 性能分析工具链走过了 15 年,是时候搞清楚每个工具的真正定位了。