Wasm-bpfWebAssembly eBPF 库和运行时
Wasm-bpf 是一个 WebAssembly eBPF 库和运行时, 基于 CO-RE(一次编写 – 到处运行) libbpf 和 wasm-micro-runtime 实现。
Wasm 最初是以浏览器安全沙盒为目的开发的,发展到目前为止,WebAssembly 已经成为一个用于云原生软件组件的高性能、跨平台和多语言软件沙箱环境,Wasm 轻量级容器也非常适合作为下一代无服务器平台运行时。另一个令人兴奋的趋势是 eBPF 的兴起,它使云原生开发人员能够构建安全的网络、服务网格和多种可观测性组件,并且它也在逐步渗透和深入到内核的各个组件,提供更强大的内核态可编程交互能力。
现在,借助 Wasm-bpf 编译工具链和运行时,我们可以使用 Wasm 将 eBPF 程序编写为跨平台的模块,同时使用 C/C++ 或 Rust 来编写 Wasm-eBPF 程序并发布。通过在 WebAssembly 中使用 eBPF 程序,我们不仅能让 Wasm 应用享受到 eBPF 的高性能和对系统接口的访问能力,还可以让 eBPF 程序使用到 Wasm 的沙箱、灵活性、跨平台性、和动态加载,并且使用 Wasm 的 OCI 镜像来方便、快捷地分发和管理 eBPF 程序。结合这两种技术,我们将会给 eBPF 和 Wasm 生态来一个全新的开发体验!
- 亮点:
-
通用
: 给 WASM 提供大部分的 eBPF 功能。 比如从ring buffer
或者perf buffer
中获取数据、 通过maps
提供内核
eBPF 和用户态
Wasm 程序之间的双向通信、 动态加载
,附加
或者解除附加
eBPF程序等。 支持大量的 eBPF 程序类型和 map 类型, 覆盖了用于tracing(跟踪)
,networking(网络)
,security(安全)
的使用场景。 -
高性能
: 对于复杂数据类型,没有额外的序列化
开销。 通过共享内存
来避免在 Host 和 WASM 端之间的额外数据拷贝。 -
简单便捷的开发体验
: 提供和 libbpf-bootstrap 相似的开发体验,自动生成
Wasm-eBPF 的skeleton
头文件以及用于绑定的类型
定义。 -
非常轻量
: 编译完成的二进制文件只有1.5 MB
的大小,编译好的 WASM 模块只有~90K
,远远比传统的以容器方式分发和运行 eBPF 程序来的轻量,同时保持良好的隔离性和沙箱特性。你可以非常容易地使用任何语言,在任何平台上建立你自己的 Wasm-eBPF 运行时,使用相同的工具链来构建应用!
- 演示视频:https://www.bilibili.com/video/BV1vD4y1P78S/
- 示例代码:
使用 C/C++ 在 Wasm 中构建 eBPF 应用,将 eBPF 字节码加载到内核并处理内核返回的对应的数据
/* Load and verify BPF application */ skel = bootstrap_bpf__open(); if (!skel) { fprintf(stderr, "Failed to open and load BPF skeleton\\n"); return 1; }
<span style="color:var(--color-prettylights-syntax-comment)"><span style="color:var(--color-prettylights-syntax-comment)">/*</span> Parameterize BPF code with minimum duration parameter <span style="color:var(--color-prettylights-syntax-comment)">*/</span></span> skel->rodata->min_duration_ns = env.min_duration_ms * <span style="color:var(--color-prettylights-syntax-constant)">1000000ULL</span>; <span style="color:var(--color-prettylights-syntax-comment)"><span style="color:var(--color-prettylights-syntax-comment)">/*</span> Load & verify BPF programs <span style="color:var(--color-prettylights-syntax-comment)">*/</span></span> err = bootstrap_bpf__load(skel); <span style="color:var(--color-prettylights-syntax-keyword)">if</span> (err) { <span style="color:var(--color-prettylights-syntax-constant)">fprintf</span>(stderr, <span style="color:var(--color-prettylights-syntax-string)"><span style="color:var(--color-prettylights-syntax-string)">"</span>Failed to load and verify BPF skeleton<span>\\n</span><span style="color:var(--color-prettylights-syntax-string)">"</span></span>); <span style="color:var(--color-prettylights-syntax-keyword)">goto</span> cleanup; } <span style="color:var(--color-prettylights-syntax-comment)"><span style="color:var(--color-prettylights-syntax-comment)">/*</span> Attach tracepoints <span style="color:var(--color-prettylights-syntax-comment)">*/</span></span> err = bootstrap_bpf__attach(skel); <span style="color:var(--color-prettylights-syntax-keyword)">if</span> (err) { <span style="color:var(--color-prettylights-syntax-constant)">fprintf</span>(stderr, <span style="color:var(--color-prettylights-syntax-string)"><span style="color:var(--color-prettylights-syntax-string)">"</span>Failed to attach BPF skeleton<span>\\n</span><span style="color:var(--color-prettylights-syntax-string)">"</span></span>); <span style="color:var(--color-prettylights-syntax-keyword)">goto</span> cleanup; }</pre>
使用 Rust 在 Wasm 中编写 eBPF 应用:
extern "C" fn handle_event(_ctx: u32, data: u32, _data_sz: u32) { let event_slice = unsafe { slice::from_raw_parts(data as *const Event, 1) }; let event = &event_slice[0]; let pid = event.pid; let ppid = event.ppid; let exit_code = event.exit_code; if event.exit_event == 1 { print!( "{:<8} {:<5} {:<16} {:<7} {:<7} [{}]", "TIME", "EXIT", unsafe { CStr::from_ptr(event.comm.as_ptr() as *const i8) } .to_str() .unwrap(), pid, ppid, exit_code ); ... }
一行命令从云端的 Github Packages 中下载并运行 eBPF 程序,或通过 Github Packages 发布:
# push to Github Packages ecli push https://ghcr.io/eunomia-bpf/sigsnoop:latest # pull from Github Packages ecli pull https://ghcr.io/eunomia-bpf/sigsnoop:latest # run eBPF program ecli run https://ghcr.io/eunomia-bpf/sigsnoop:latest
- 后续更新计划:
- 继续完善多种语言支持;
- 支持更完善的 eBPF 特性;
- 探索更多的应用场景;
评论