共计 2773 个字符,预计需要花费 7 分钟才能阅读完成。
如果非要说以后计算机领域最有前途的两个根底软件技术,那非 eBPF 和 wasm 莫属了。
什么是 eBPF?
Linux 内核始终是实现监督 / 可察看性,网络和安全性的现实场合。可怜的是,这通常是不切实际的,因为它须要更改内核源代码或加载内核模块,并导致彼此重叠的形象层。eBPF 是一项革命性的技术,能够在 Linux 内核中运行沙盒程序,而无需更改内核源代码或加载内核模块。通过使 Linux 内核可编程,基础架构软件能够利用现有的层,从而使它们更加智能和功能丰富,而无需持续为零碎减少额定的复杂性层。
eBPF 导致了网络,安全性,应用程序配置 / 跟踪和性能故障排除等畛域的新一代工具的开发,这些工具不再依赖现有的内核性能,而是在不影响执行效率或安全性的状况下被动从新编程运行时行为。
如果间接解释 eBPF,有点不明所以。那咱们就看看有哪些基于 eBPF 的工程,这些工程或者你曾经晓得,或是曾经常常应用,兴许你会明确 eBPF 间隔咱们并不边远。
基于 eBPF 的我的项目
1:bcc
BCC 是用于创立基于 eBPF 的高效内核跟踪和操作程序的工具包,其中包含一些有用的命令行工具和示例。BCC 简化了用 C 进行内核检测的 eBPF 程序的编写,包含 LLVM 的包装器以及 Python 和 Lua 的前端。它还提供了用于间接集成到应用程序中的高级库。
2:bpftrace
bpftrace 是 Linux eBPF 的高级跟踪语言。它的语言受 awk 和 C 以及 DTrace 和 SystemTap 等以前的跟踪程序的启发。bpftrace 应用 LLVM 作为后端将脚本编译为 eBPF 字节码,并利用 BCC 作为与 Linux eBPF 子系统以及现有 Linux 跟踪性能和连接点进行交互的库。
3:Cilium
Cilium 是一个开源我的项目,提供基于 eBPF 的联网,安全性和可察看性。它是从头开始专门设计的,旨在将 eBPF 的劣势带入 Kubernetes 的世界,并满足容器工作负载的新可伸缩性,安全性和可见性要求。
4:Falco
Falco 是一种行为流动监视器,旨在检测应用程序中的异样流动。Falco 在 eBPF 的帮忙下审核 Linux 内核层的零碎。它应用其余输出流(例如容器运行时度量规范和 Kubernetes 度量规范)丰盛了收集的数据,并容许间断监督和检测容器,应用程序,主机和网络流动。
5:Katran
Katran 是一个 C ++ 库和 eBPF 程序,用于构建高性能的第 4 层负载平衡转发立体。Katran 利用 Linux 内核中的 XDP 根底构造来提供用于疾速数据包解决的内核性能。它的性能与 NIC 接管队列的数量成线性比例,并且应用 RSS 敌对的封装转发到 L7 负载平衡器。
6:Sysdig
Sysdig 是提供深层零碎可见性的简略工具,并具备对容器的原生反对。
其余基于 eBPF 技术的我的项目还有很多,比方 kubectl-trace,ply 等,这里不再赘述。
如何编写一个 eBPF 程序?
在很多状况下,不是间接应用 eBPF,而是通过 Cilium,bcc 或 bpftrace 等我的项目间接应用 eBPF,这些我的项目在 eBPF 之上提供了形象,并且不须要间接编写程序,而是提供了指定基于用意的定义的性能,而后应用 eBPF 施行。
如果不存在更高级别的形象,则须要间接编写程序。Linux 内核心愿 eBPF 程序以字节码的模式加载。尽管当然能够间接编写字节码,但更常见的开发实际是利用 LLVM 之类的编译器套件将伪 C 代码编译为 eBPF 字节码。
在编写 eBPF 程序之前,须要简略理解几个概念。
1)map(映射):BPF 最令人着迷的方面之一是,内核上运行的代码和加载了该代码的程序能够在运行时应用消息传递互相通信。
BPF 映射是驻留在内核中的键 / 值存储。任何 BPF 程序都能够拜访它们。在用户态中运行的程序也能够应用文件描述符拜访这些映射。只有当时正确指定数据大小,就能够在映射中存储任何类型的数据。内核将键和值视为二进制 blobs,它并不关怀您在映射中保留的内容。
BPF 验证程序包含多种保护措施,以确保您创立和拜访映射的形式是平安的。当咱们解释如何拜访这些映射中的数据时,咱们也将解释这些保护措施。
当然 BPF 映射类型有很多,比方哈希表映射,数组映射,Cgroup 数组映射等,别离满足不同的场景。
2)验证器
BPF 验证程序也是在您的零碎上运行的程序,因而,对其进行严格审查是确保其正确执行工作的指标。
验证程序执行的第一项查看是对 VM 行将加载的代码的动态剖析。第一次查看的目标是确保程序有预期的后果。为此,验证程序将应用代码创立有向循环图(DAG)。验证程序剖析的每个指令将成为图中的一个节点,并且每个节点都链接到下一条指令。验证程序生成此图后,它将执行深度优先搜寻(DFS),以确保程序实现并且代码不蕴含危险门路。这意味着它将遍历图的每个分支,始终到分支的底部,以确保没有递归循环。
这些是验证器在第一次查看期间可能回绝您的代码的情景,要求有以下几个方面:
- 该程序不蕴含管制循环。为确保程序不会陷入有限循环,验证程序会回绝任何类型的管制循环。曾经提出了在 BPF 程序中容许循环的倡议,然而截至撰写本文时,没有一个被采纳。
- 该程序不会尝试执行超过内核容许的最大指令数的指令。此时,可执行的最大指令数为 4,096。此限度是为了避免 BPF 永远运行。在第 3 章,咱们探讨如何嵌套不同的 BPF 程序,以平安的形式解决此限度。
- 该程序不蕴含任何无法访问的指令,例如从未执行过的条件或性能。这样能够避免在 VM 中加载有效代码,这也会提早 BPF 程序的终止。
- 该程序不会尝试越界。
验证者执行的第二项查看是 BPF 程序的空运行。这意味着验证者将尝试分析程序将要执行的每条指令,以确保它不会执行任何有效的指令。此执行还将查看所有内存指针是否均已正确拜访和勾销援用。最初,空运行向验证程序告诉程序中的控制流,以确保无论程序采纳哪个管制门路,它都会达到 BPF_EXIT 指令。为此,验证程序会跟踪堆栈中所有拜访过的分支门路,并在采纳新门路之前对其进行评估,以确保它不会屡次拜访特定门路。通过这两项查看后,验证者认为程序能够平安执行。
3) hook:因为 eBPF 是事件驱动的,所以 ebpf 是作用于具体的 hook 的。依据不同的作用,罕用的有 XDP,trace,套接字等。
4)帮忙函数:eBPF 程序无奈调用任意内核性能。容许这样做会将 eBPF 程序绑定到特定的内核版本,并使程序的兼容性复杂化。取而代之的是,eBPF 程序能够调用帮忙函数,该函数是内核提供的家喻户晓且稳固的 API。
总结
平安,网络,负载平衡,故障剖析,追踪等畛域都是 eBPF 的主战场。
对于云原生畛域,Cilium 曾经应用 eBPF 实现了无 kube-proxy 的容器网络。利用 eBPF 解决 iptables 带来的性能问题。
整个 eBPF 生态倒退比拟好,社区曾经提供了诸多工具不便大家编写本人的 eBPF 程序。