WEBKT

使用eBPF追踪TCP连接?这几个关键指标你必须掌握!

27 0 0 0

eBPF:内核观测的瑞士军刀

实战:构建TCP连接追踪器

1. 确定追踪点(Probe Points)

2. 编写eBPF程序

3. 编译eBPF程序

4. 加载和运行eBPF程序

5. 用户空间程序

进阶:更丰富的指标和可视化

eBPF的优势和挑战

总结

作为一名系统管理员,网络工程师,你是否经常遇到以下困扰?

  • 线上服务偶发性延迟增高,但苦于无法快速定位问题?
  • 想要了解特定TCP连接的性能瓶颈,却抓不到关键数据?
  • 面对复杂的网络环境,缺乏有效的监控手段?

如果你也有以上疑问,那么eBPF(Extended Berkeley Packet Filter)绝对值得你深入了解。 它就像一个超级探针,能够在你内核中安全、高效地运行自定义代码,实时监控和分析各种事件。今天,我就带你一起,利用eBPF打造一个简易但强大的TCP连接追踪工具,让你对网络性能了如指掌。

eBPF:内核观测的瑞士军刀

在深入实践之前,我们先来简单认识一下eBPF。传统上,内核调试需要修改内核代码,这既复杂又危险。而eBPF提供了一种更优雅的方式:

  1. 无需修改内核源码:eBPF程序运行在内核虚拟机中,通过verifier的严格检查,保证安全性和稳定性。
  2. 事件驱动:eBPF程序可以挂载到各种事件上,如系统调用、函数入口/退出、网络事件等,只有当事件发生时才会被触发。
  3. 高性能:eBPF程序经过JIT(Just-In-Time)编译,直接在内核中运行,性能损耗极低。
  4. 灵活可编程:你可以使用C、Rust等高级语言编写eBPF程序,然后编译成字节码加载到内核中。

实战:构建TCP连接追踪器

我们的目标是创建一个eBPF程序,能够追踪TCP连接的建立、关闭、数据传输等事件,并统计连接的时延、吞吐量等指标。以下是实现步骤:

1. 确定追踪点(Probe Points)

首先,我们需要确定要追踪的关键内核函数。对于TCP连接,以下几个函数非常重要:

  • tcp_v4_connect / tcp_v6_connect: TCP连接建立(connect系统调用)
  • tcp_close: TCP连接关闭
  • tcp_sendmsg: TCP发送数据
  • tcp_recvmsg: TCP接收数据

我们可以使用kprobekretprobe分别在这些函数的入口和退出处挂载eBPF程序。kprobe用于在函数入口处执行代码,kretprobe用于在函数退出时执行代码。

2. 编写eBPF程序

接下来,我们需要编写eBPF程序,来收集我们关心的信息。这里以tcp_v4_connect为例,展示如何获取连接信息并记录时间戳:

#include <uapi/linux/ptrace.h>
#include <net/sock.h>
#include <net/tcp_states.h>
struct connect_event {
u32 pid;
u32 saddr;
u32 daddr;
u16 dport;
u64 ts;
};
BPF_PERF_OUTPUT(connect_events);
int kprobe__tcp_v4_connect(struct pt_regs *ctx, struct sock *sk)
{
struct connect_event event = {};
// 获取进程ID
event.pid = bpf_get_current_pid_tgid();
// 获取源IP地址
event.saddr = sk->sk_rcv_saddr;
// 获取目标IP地址和端口
event.daddr = sk->sk_daddr;
event.dport = sk->sk_dport;
// 获取当前时间戳
event.ts = bpf_ktime_get_ns();
// 将事件发送到用户空间
connect_events.perf_submit(ctx, &event, sizeof(event));
return 0;
}

这段代码做了以下几件事:

  1. 定义了一个connect_event结构体,用于存储连接事件的信息,包括进程ID、源IP地址、目标IP地址、目标端口和时间戳。
  2. 使用BPF_PERF_OUTPUT定义了一个perf事件,用于将数据从内核空间传递到用户空间。
  3. 编写kprobe__tcp_v4_connect函数,这个函数会在tcp_v4_connect函数入口处被执行。
  4. 在函数中,我们通过sk结构体获取连接的各种信息,并使用bpf_ktime_get_ns获取当前时间戳。
  5. 最后,我们使用connect_events.perf_submit将事件发送到用户空间。

对于其他追踪点,我们可以类似地编写eBPF程序,获取相应的信息。

3. 编译eBPF程序

编写完成后,我们需要将eBPF程序编译成字节码。可以使用clangllvm工具链进行编译:

clang -O2 -target bpf -c tcp_connect_tracer.c -o tcp_connect_tracer.o

4. 加载和运行eBPF程序

编译完成后,我们需要将eBPF程序加载到内核中并运行。可以使用bpftoollibbpf等工具进行加载和管理。

这里以bpftool为例:

bpftool prog load tcp_connect_tracer.o /sys/fs/bpf/tcp_connect_tracer
bpftool prog attach kprobe tcp_v4_connect /sys/fs/bpf/tcp_connect_tracer

第一条命令将tcp_connect_tracer.o加载到/sys/fs/bpf/tcp_connect_tracer路径下。

第二条命令将eBPF程序挂载到tcp_v4_connect函数的入口处。

5. 用户空间程序

现在,我们需要编写一个用户空间程序,用于从perf事件中读取数据,并进行分析和展示。以下是一个简单的Python示例:

from bcc import BPF
import socket
import struct
# 加载eBPF程序
b = BPF(src_file="tcp_connect_tracer.c")
# 定义事件处理函数
def print_event(cpu, data, size):
event = b["connect_events"].event(data)
print("%-6d %-16s %-16s %-4d" % (event.pid, socket.inet_ntoa(struct.pack(">I", event.saddr)), socket.inet_ntoa(struct.pack(">I", event.daddr)), event.dport))
# 打印表头
print("PID %-16s %-16s PORT" % ("SRC", "DEST"))
# 绑定事件处理函数
b["connect_events"].open_perf_buffer(print_event)
# 循环读取事件
while True:
try:
b.perf_buffer_poll()
except KeyboardInterrupt:
exit()

这段代码做了以下几件事:

  1. 使用bcc库加载eBPF程序。
  2. 定义print_event函数,用于处理从perf事件中读取到的数据,并将结果打印到控制台。
  3. 使用b["connect_events"].open_perf_buffer绑定事件处理函数。
  4. 循环读取perf事件,直到用户手动停止程序。

运行这个Python程序,你就可以实时看到TCP连接的建立信息了。

进阶:更丰富的指标和可视化

以上只是一个简单的示例,你可以根据自己的需求,扩展这个工具,收集更多有用的指标,例如:

  • 连接时延:记录连接建立和数据传输的时间戳,计算时延。
  • 吞吐量:统计单位时间内发送和接收的数据量。
  • TCP状态:追踪TCP连接的状态变化(如SYN_SENT、ESTABLISHED、FIN_WAIT1等)。
  • 重传率:统计TCP重传的次数。

此外,你还可以将收集到的数据可视化,例如使用Grafana等工具,创建漂亮的仪表盘,实时监控网络性能。

eBPF的优势和挑战

使用eBPF进行TCP连接追踪,相比传统的工具,有以下优势:

  • 低开销:eBPF程序运行在内核中,避免了用户空间和内核空间的数据拷贝,性能损耗极低。
  • 高精度:eBPF可以精确地追踪内核事件,获取微秒级别的时间戳。
  • 可编程:你可以根据自己的需求,自定义追踪逻辑和指标。

当然,eBPF也面临一些挑战:

  • 学习曲线:eBPF编程需要一定的内核知识和编程经验。
  • 安全性:eBPF程序需要在内核中运行,安全性至关重要,需要经过严格的验证。
  • 可移植性:不同的内核版本可能存在差异,需要针对不同的内核版本进行适配。

总结

eBPF为我们提供了一种强大的内核观测手段,可以用于TCP连接追踪、性能分析、安全审计等各种场景。虽然学习曲线较陡峭,但一旦掌握,你将拥有一个无与伦比的工具,能够深入了解系统的运行状态,解决各种疑难杂症。希望这篇文章能够帮助你入门eBPF,开启你的内核探索之旅!

作为一名经验丰富的开发者,我强烈建议你深入学习eBPF,它将成为你解决问题的利器。不要害怕挑战,勇敢地探索内核的奥秘吧!

内核探险家 eBPFTCP追踪内核观测

评论点评

打赏赞助
sponsor

感谢您的支持让我们更好的前行

分享

QRcode

https://www.webkt.com/article/9670