eBPF 介绍

发布时间: 更新时间: 总字数:678 阅读时间:2m 作者: IP上海 分享 网址

eBPF(extended Berkeley Packet Filter, 可扩展伯克利包过滤器) 对内核进行动态编程,以实现高效联网、可观察性、可追踪性和安全性

介绍

  • eBPF 是从 BPF(也称 cBPF:classic Berkeley Packet Filter) 发展而来的,BPF 专门用来过滤网络数据包
  • eBPF 允许程序在不修改内核源代码,或添加额外的内核模块情况下运行
  • 特征
    • 无侵入特性:观测成本极低,应用无需修改任何代码和重启进程
    • 动态可编程性:无需重启探针,动态下发 eBPF 脚本即可修改探针侧的逻辑
    • 高性能:自带 JIT 编译,使探针能够获得内核本地运行的效率
    • 安全:verifier 机制限制了 eBPF 脚本能够访问的内核函数,保证内核运行的稳定

eBPF 架构

eBPF 架构图

转自

  • 用户态
    • 用户编写 eBPF 程序,可以使用 eBPF 汇编或者 eBPF 特有的 C 语言来编写
    • 使用 LLVM/CLang 编译器,将 eBPF 程序编译成 eBPF 字节码
    • 调用 bpf() 系统调用把 eBPF 字节码加载到内核
  • 内核态
    • 当用户调用 bpf() 系统调用把 eBPF 字节码加载到内核时,内核先会对 eBPF 字节码进行安全验证
    • 使用 JIT(Just In Time) 技术将 eBPF 字节编译成本地机器码(Native Code)
    • 根据 eBPF 程序的功能,将 eBPF 机器码挂载到内核的不同运行路径上
      • 如用于跟踪内核运行状态的 eBPF 程序将会挂载在 kprobes 的运行路径上
    • 当内核运行到这些路径时,会触发执行相应路径上的 eBPF 机器码

eBPF 使用

BCC 工具

BCC 工具支持使用 PythonC 语言组合来编写 eBPF 程序,参考

# ubuntu
sudo apt-get install bcc bpfcc-tools linux-headers-$(uname -r)

$ bcc -v
bcc: version 0.16.17
Usage: bcc [-ansi] [-options] [-o output] file [files].

hello world

  • C 语言编写 eBPF 内核态程序:hello.c
int hello_world(void *ctx)
{
    bpf_trace_printk("Hello, World!");
    return 0;
}
  • Python 开发 用户态 程序:hello.py
#!/usr/bin/env python3

from bcc import BPF

# 加载 eBPF 内核态程序
b = BPF(src_file="hello.c")

# 将 eBPF 程序挂载到内核探针 kprobe
# do_sys_openat2() 是系统调用 openat() 在内核中的实现
b.attach_kprobe(event="do_sys_openat2", fn_name="hello_world")

# 读取并且打印 eBPF 内核态程序输出的数据
b.trace_print()
  • 运行 eBPF 程序
$ sudo python3 hello.py
b'           <...>-2111    [000] ...21   239.916342: bpf_trace_printk: Hello, World!'
b'      irqbalance-962     [001] ...21   242.346380: bpf_trace_printk: Hello, World!'
b'      irqbalance-962     [001] ...21   242.346886: bpf_trace_printk: Hello, World!'
...
  • bpf_trace_printk() 会将信息写入 /sys/kernel/debug/tracing/trace_pipe

参考

  1. https://ebpf.io/
  2. https://ebpf.io/what-is-ebpf/
  3. https://developer.aliyun.com/article/992125
Home Archives Categories Tags Statistics
本文总阅读量 次 本站总访问量 次 本站总访客数