BPF技术整理笔记

目录

  • eBPF是什么?
  • eBPF是做什么的?可以解决什么问题?
  • eBPF可以带来的解决方案是什么?
  • eBPF的技术点
    • eBPF hook
    • eBPF Map
    • eBPF Helper Function
  • eBPF有什么限制吗?


前言

21年因为项目需求而要开发一个工具,可以满足:故障排查,问题分析,统计数据等需要。开始实现的比较简单,就是针对抓取的log数据进行各个维测数据的解析和处理。具有如下几种缺陷:

1、log内容主要还是借助于简单的printf和printk的内容,这类打印信息量不足。主要是release的版本不可能有太多此类的信息,否则会严重影响系统的性能。

2、信息量少也意味着无法有效支撑问题问题的相关信息追溯,无法进行有效的数据统计。因此很多监控和买点方案就无法有效实现。

3、无法将工具有效整合到整个软件开发工程中去。所以无法得到各个方面的资源支撑。所以工具必然不能得到很好地推广而进行迭代优化。

后来发现eBPF技术能够很好地满足需求。因此开始接触了eBPF技术。趁着这段时间,准备针对这个技术做一个比较完整的学习和梳理记录。

1、eBPF是什么?

BPF:Berkeley Packet Filter,伯克利包过滤器

发明之初是一款网络过滤神器,tcpdump就是基于这个神器的神器

eBPF:extended Berkeley Packet Filter 扩展的伯克利包过滤器

演进成一套通用执行引擎,不再仅仅是网络分析,可以基于eBPF开发

性能分析,系统跟踪,网络优化等多种类型的工具平台。

原来的BPF被称为cBPF(classic BPF),当前Linux内核只运行eBPF,内核将会透明地转换成eBPF再执行

BPF再数据包过滤山引入了两大革新:
  1. 1)一个新的虚拟机设计,有效地工作再基于寄存器的CPU之上,基于栈的虚拟机和基于寄存器的虚拟机区别-CSDN博客

2)应用程序使用缓存只复制顾虑数据包相关的数据,不会复制数据包的所有信息,最大程度地减少处理的的数据,提高处理效率

eBPF目前发展成为一套通用的执行引擎,提供可基于系统或程序事件高效安全执行特定代码的通用能力,通用能力的使用者不再局限内核开发者。使用场景也不仅仅是网络分析。可以基于eBPF开发性能分析,系统追踪,网络优化等多种类型的工具和平台。

eBPF由执行字节码指令,存储对象和辅助函数组成。工作原理如下:

eBPF字节码指令在内核执行前必须通过BPF验证器的验证,同时在启用BPF JIT模式的内核中,会直接将指令转成内核可执行的本地指令运行,具有很搞笑的执行效率。

2、BPF是做什么的?可以解决什么问题?

1)linux内核开发目标:强安全,高性能,持续交付

强安全:就是不能允许不可信的代码运行在内核中。

高性能:作为承载千百服务的操作系统内核,需要有高性能的保障应用的快速发展需求。

持续交付:就是不断升级迭代更新。同时,升级动作本身对于用户而言尽量不会感知到。

2)linux内核开发的一般解决方案和缺陷

直接修改内核代码,通过API暴露能力,用户可能要等上n年才能更新到这个版本来使用。而且每次的功能更新都可能需要重新编译打包内核代码

开发新的可即时加载的内核模块,这个内核模块可能会随着每一个内核版本的发布而不可用了,因此你必须小心地为每一次的内核版本更新调整模块代码。不然就会让内核模块直接崩溃

3、BPF可以带来的解决方案是什么?

强安全:BPF验证器(verifier)通过沙盒机制检查每一个程序是否能够安全运行在内核中,拒绝不安全的代码。

高性能:JIT编译保障了程序本地运行的高性能

持续交付:程序可以被无缝替换,并不影响在运行的任务。

强安全:就是在检查不通过的,将拒绝这个程序被加载到内核中去,从而保证内核本身不会崩溃,有一个验证器进行验证这是不同于内核模块的。比如以下几种情况就是无法通过BPF验证器的:

没有实际加载BPF程序所需的权限的

访问任意内核空间内存数据的

将任意内核空间内存数据暴露给用户空间的

高性能:通过安全验证后,JIT编译生成的是通用字节码,它是完全可移植的,可以在任意CPU架构山加载这个字节码的。这样我们能获得本地编译后的程序运行速度了。

持续交付:通过了JIT编译后,就会把编译后的程序附加到各种系统调用的钩子(hook)上,而且可以在不影响系统运行的情况下,实时地在线地替换掉这些运行在Linux内核中的BPF程序。

4、eBPF的技术点

BPF钩子(hooks)

能够加快BPF程序的地方:

1)kenrel functions(kprobes)

2)userspace functions(uprobes)

3)system calls

4)fentry

5)fexit

6)Tracepoints

7)network devices(tc/xdp)

8)network routes

9)TCP congestion algorithms

10)sockets(data level)

这10种钩子就是内核中可以加载BPF程序的地方。

包括:文件打开,创建TCP链接,Socket链接到发送系统消息等几乎所有的系统调用。用户空间的各种动态信息都能加载BPF程序。

BPF Map:

BPF Map,存储数据,交换信息的桥梁

Map的类型:Hash tables,Arrays,LRU(Least Recently Used),Ring Buffer,Stack Trace,LPM(Longest Prefix match)

Map的功能:Program state,Program configuration,Share data between programs,share state,metrics,and statistics with user space

对于一个程序通常复杂的逻辑就必须要记录数据的状态的部分。BPF Map就是用来存储数据的状态信息,统计信息和指标信息的。

BPF Map是可以被用户空间访问并操作的

BPF Map是可以与BPF程序分离的,即当创建一个BPF Map的BPF程序运行结束后,该BPF Map还能存在,而不是随着程序一起消亡的。

基于上面的特点,我们可以利用BPF Map持久化数据,在不丢失重要数据的同时,更新BPF程序逻辑,实现在不同程序之间共享信息,在收集统计信息或指标等场景下,非常有用

BPF Helper Function:BPF的辅助函数

辅助函数的清单:

Random numbers

Get current time

Map access

Get process/cgroup context

Manipulate network packets and forwarding

Access socket data

Perform tail call

Access process stack

Access syscall arguments

它们是面向开发者的,提供操作BPF程序和BPF Map的工具类函数。就是一个中间件。适配内核的迭代更新,主要是内核函数的变化,而对开发者是透明的,形成稳定的API接口。

例如:BPF程序需要生成一个随机数,那么有一个辅助函数可以帮助检索并询问内核,让内核完成“给我一个随机数”的任务,或者“从BPF Map中读取某个值”等等。

只要与操作系统内核的交互都是通过BPF辅助函数来完成的,由于这些都是稳定的API,所以BPF程序可以跨内核版本进行移植。

eBPF技术有些什么限制?

eBPF程序不能调用任意的内核参数,只限于内核模块中列出的BPF Helper函数,函数支持列表也随着内核演进而不断增加

eBPF程序不允许包含无法达到的指令,防止加载无效代码,延迟程序的终止。

eBPF程序中循环次数限制且必须在有限时间内结束

eBPF堆栈大小被限制在MAXBPFSTACK。Linux5.8,被设置为512。可以改用BPF Map,大小是无限的。

eBPF字节码大小最初被限制在4096条指令,Linux5.8版本,已放宽至100万条指令(BPF_COMPLEXITY_LIMIT_INSNS),对于无权限的BPF程序,仍然保留4096条的限制(BPF_MAXINSNS)


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值