eBPF学习摘要1(概述、理论)
早期内核包过滤是将网络数据包拷贝到用户态进行过滤,这样整体的包过滤性能低,后续在1992年的BSD操作系统上引入BPF包过滤技术,Linux在内核2.1.75正式引入BPF技术。网络数据包过滤可以直接在内核中执行,避免将网络数据包在用户态执行,极大提高了包过滤性能。如tcpdump工具就是利用BPF技术实现。2014年对BPF技术进行全面扩展,诞生了eBPF(extended Berkeley Packet Filter)使得BPF不仅仅是网络栈层面功能。后续iovisor 引入 BCC、bpftrace 等工具,成为 eBPF 在跟踪和排错领域的最佳实践。另外 eBPF 最重大的特性是在内核中运行沙盒程序而无需修改内核源码和重新编译内核就可以扩展内核的功能,Cilium、Katran、Falco 等一系列基于 eBPF 优化网络和安全的开源项目也逐步诞生。并且,越来越多的开源和商业解决方案开始借助 eBPF,优化其网络、安全以及观测的性能。
图片来源: http://blog.csdn.net/eBPF_Kindling/article/details/123575619
发展历程
1992年:BPF全称Berkeley Packet Filter,诞生初衷提供一种内核中自定义报文过滤的手段(类汇编),提升抓包效率。(tcpdump)
2011年:linux kernel 3.2版本对BPF进行重大改进,引入BPF JIT,使其性能得到大幅提升。
2014年: linux kernel 3.15版本,BPF扩展成eBPF,其功能范畴扩展至:内核跟踪、性能调优、协议栈QoS等方面。与之配套改进包括:扩展BPF ISA指令集、提供高级语言(C)编程手段、提供MAP机制、提供Help机制、引入Verifier机制等。
2016年:linux kernel 4.8版本,eBPF支持XDP,进一步拓展该技术在网络领域的应用。随后Netronome公司提出eBPF硬件卸载方案。Cilium项目正式发布。
2018年:linux kernel 4.18版本,引入BTF,将内核中BPF对象(Prog/Map)由字节码转换成统一结构对象,这有利于eBPF对象与Kernel版本的配套管理,为eBPF的发展奠定基础。
2018年:从kernel 4.20版本开始,eBPF成为内核最活跃的项目之一,新增特性包括:sysctrl hook、flow dissector、struct_ops、lsm hook、ring buffer等。场景范围覆盖容器、安全、网络、跟踪等
2021年:微软、Facebook、Google、Isovalent、NetFlix成立eBPF基金会,同年Cilium发布基于eBPF的Service Mesh解决方案
eBPF 基本架构及使用
参考链接: http://blog.51cto.com/dengchj/2944202
实现原理
用户态
1、用户编写 eBPF 程序,可以使用 eBPF 汇编或者 eBPF 特有的 C 语言来编写。
2、使用 LLVM/CLang 编译器,将 eBPF 程序编译成 eBPF 字节码。
3、调用 bpf() 系统调用把 eBPF 字节码加载到内核。
内核态
1、当用户调用 bpf() 系统调用把 eBPF 字节码加载到内核时,内核先会对 eBPF 字节码进行安全验证。
2、使用 JIT(Just In Time)技术将 eBPF 字节编译成本地机器码(Native Code)。
3、然后根据 eBPF 程序的功能,将 eBPF 机器码挂载到内核的不同运行路径上(如用于跟踪内核运行状态的 eBPF 程序将会挂载在 kprobes 的运行路径上)。当内核运行到这些路径时,就会触发执行相应路径上的 eBPF 机器码。
4、通过map与用户空间程序交互
如何保证内核安全性和优缺点
-
需要特权执行:eBPF程序加载到Linux内核的进程都必须在特权模式(root)下运行,或者需要CAP_BPF功能,不受信任的程序不能加载eBPF程序
-
验证器:加载eBPF程序到内核后需要经过验证如有界循环、越界访问内存、使用未初始化的变量。
-
程序执行保护:已经加载在内核中的eBPF程序会进入read-only模式试图修改会直接crash内核。
-
限制内核访问范围: eBPF程序不能直接访问任意内核其他函数。必须通过eBPF helpers访问固定helpers函数。
-
eBPF 堆栈大小被限制在 MAX_BPF_STACK,截止到内核 Linux 5.8 版本,被设置为 512字节。
-
eBPF 字节码大小最初被限制为 4096 条指令,截止到内核 Linux 5.8 版本, 当前已将放宽至 100 万指令。
优点:
1.速度和性能。 内核态进行,速度和效率高。
2.灵活:无需修改内核代码,即可扩展内核功能拥有无限想象空间。
3.低侵入性:基于eBPF实现链路追踪、服务治理等场景不需要侵入用户层。
缺点:
1.eBPF本身一些特性和能力依赖新版本内核。
2.学习成本高,需要对Linux Kernel和操作系统原理有深入了解。
目前行业落地情况
应用
- 动态追踪:bcc、bpftrace
- 观测监控:Pixie、Hubble
- 网络:Cilium、Katran
- 安全:Falco、Tracee
能解决什么问题
为什么需要eBPF能实现可观测性
eBPF可观测性-指标采集
eBPF除了常规的指标监控如CPU、内存等,还可以监控细粒度的系统调用等信息,通过内核Kprobe或者Tracepoint实现;
eBPF可观测性-链路追踪
与传统APM相比,eBPF进行链路追踪不需要与业务本身进行绑定。通过拦截sock相关的send/recv操作,解析协议头,获得进程之间的调用关系,可进一步关联Kubernetes元数据,获得容器、服务之间的调用关系;
展望未来
1、基于eBPF的服务网格
去除每个pod的sidecar,内核态实现服务治理(cilium1.12已实现)
2、基于eBPF的负载均衡器
利用 socket eBPF,可以在不用直接处理报文和NAT 转换的前提下,实现了负载均衡逻辑。Service网络 POD<–> Service <–> POD优化成 POD <–> POD,从而使Service网络性能基本等同于POD 网络。软件结构如下:
3、基于eBPF的网络安全策略
不再依赖 iptables,不需要创建巨量的 iptables rule,从而显著降低 iptables 带来的性能影响。
参考链接:
http://mp.weixin.qq.com/s/Xr8ECrS_fR3aCT1vKJ9yIg
http://blog.csdn.net/eBPF_Kindling/article/details/123575619
http://www.51cto.com/article/715674.html
http://colobu.com/2022/05/22/use-ebpf-to-trace-rpcx-microservices/
http://arthurchiao.art/blog/ebpf-and-k8s-zh/
http://zhuanlan.zhihu.com/p/480811707
http://github.com/mikeroyal/eBPF-Guide
http://zhuanlan.zhihu.com/p/373090595