eBPF 简述

60 阅读5分钟

eBPF(Extended Berkeley Packet Filter)是一项 Linux 内核技术,支持用户动态加载程序到内核中运行,用于扩展和增强内核功能。eBPF 程序在一个安全的虚拟机中执行,可在网络、性能监控、调试、跟踪、安全等领域提供强大的功能支持。


  1. eBPF 的核心技术模块

    1.   eBPF 子系统

          eBPF 子系统是 Linux 内核的一个核心功能模块。

      • 内核组成部分:它以代码的形式嵌入在内核源码中,作为 Linux 内核编译和运行时的一部分。
      • 功能模块:提供一种机制,使得用户可以动态扩展内核功能,而无需重新编译或加载模块。
      • 运行环境:eBPF 子系统随着内核启动加载,并始终作为内核的一部分运行。

          关键特点

      • 嵌入式:eBPF 是内核的原生能力,而非独立运行的服务或进程。
      • 动态扩展:通过用户加载 eBPF 程序,eBPF 子系统支持对内核行为进行定制。
      • 安全可靠:运行 eBPF 程序时会经过严格的验证,确保不会影响内核稳定性。
    1.   eBPF 虚拟机 (eBPF VM)

    • 功能:提供运行 eBPF 程序的执行环境。

    • 特性

      • RISC 风格的寄存器虚拟机,支持 11 个寄存器(10 个通用 + 1 个栈指针)。
      • 执行 eBPF 字节码,可以解释执行或通过 JIT 编译为本地机器码。
      • 高效的运行方式,避免了用户态和内核态的频繁切换。
    • 用途

      • 运行用户加载的 eBPF 程序。

      • 提供灵活的运行环境支持多种场景(网络、跟踪、性能优化)。

    1.   验证器 (Verifier)

    • 功能:在加载 eBPF 程序到内核之前,验证程序的安全性和合法性。

    • 特性

      • 确保 eBPF 程序不会造成内核崩溃或资源滥用。

      • 检查程序的以下内容:

        • 无死循环(验证程序终止性)。
        • 内存访问是否安全(指针检查、越界访问)。
        • 寄存器状态是否符合要求。
      • 构建控制流图 (CFG) 对程序逻辑进行分析。

    • 用途

      • 防止不受信任的代码对内核造成破坏。

      • 提供强制性安全保证。

    1.    JIT 编译器 (Just-In-Time Compiler)

    • 功能:将 eBPF 字节码即时编译为本地机器码,提高执行效率。

    • 特性

      • 支持多种硬件架构(x86、ARM、RISC-V 等)。
      • 提高运行性能,使 eBPF 程序接近内核原生代码的速度。
      • 可动态启用或禁用(通过内核配置 CONFIG_BPF_JIT 控制)。
    • 用途

      • 加速高频调用的 eBPF 程序(如网络包过滤程序)。

      • 降低解释执行的性能开销。

    1.    BPF Maps

    • 功能:高效的数据存储和共享结构,用于在内核态和用户态之间交换数据。

    • 特性

      • 支持多种数据结构类型,如哈希表、数组、LRU 缓存、队列、栈等。
      • 用户态和内核态都可以通过 API 操作 Maps。
      • 支持 BPF Maps 的持久化,用于跨程序或进程的共享。
    • 用途

      • 存储 eBPF 程序的运行结果。

      • 提供用于统计、监控或临时存储的数据。

    1.    Helper Functions

    • 功能:提供 eBPF 程序访问内核功能的接口。

    • 特性

      • eBPF 程序不能直接调用内核函数,而是通过 Helper Functions 与内核交互。
      • Helper Functions 被内核预定义,每个函数有固定编号。
    • 常用 Helper Functions

      • bpf_ktime_get_ns():获取系统时间(纳秒)。
      • bpf_map_update_elem():更新 Map 中的元素。
      • bpf_get_current_pid_tgid():获取当前进程的 PID 和 TID。
      • bpf_trace_printk():输出调试信息到内核日志。
    • 用途

      • 扩展 eBPF 程序的能力,实现复杂逻辑。

      • 提供与内核交互的安全接口。

    1.    挂载点 (Hooks)

    • 功能:定义 eBPF 程序的触发位置。

    • 特性

      • 支持将 eBPF 程序挂载到内核的多个触发点。
      • 每个挂载点提供特定的上下文信息供程序使用。
    • 常见挂载点

      • 网络路径

        1. XDP (eXpress Data Path) :处理网络包,位于网络栈的最底层。
        2. TC Traffic Control :在传输层或网络层控制流量。
      • 内核跟踪

        1. KprobeKretprobe:挂载到内核函数的入口或返回点。
        2. Tracepoints:挂载到内核中预定义的跟踪点。
      • cgroup

        1. 绑定到特定的 cgroup,用于控制其资源使用或行为。
      • 性能事件

        1. 与性能监控工具结合,分析系统运行情况。
    • 用途

      • 捕获和处理特定的内核事件。
      • 实现网络优化、安全检查等功能。

  1. eBPF 的技术功能概览

      2.1 网络优化

    • 功能:动态调整网络行为,提高网络性能。

    • 常见用途

      • XDP:超低延迟的数据包过滤和转发。
      • TC:灵活的流量整形和包处理。
    • 示例:基于 eBPF 实现负载均衡、防火墙规则。

      2.2 系统跟踪与监控

    • 功能:实时监控系统性能,捕获关键内核事件。

    • 常见用途

      • 使用 Tracepoints 或 Kprobes 跟踪内核行为。
      • 收集性能指标(如 I/O 延迟、CPU 占用)。
    • 示例:利用 bpftrace 生成系统性能报告。

      2.3 安全增强

    • 功能:动态应用安全策略,检测和阻止恶意行为。

    • 常见用途

      • 使用 cgroup BPF 限制容器访问资源的行为。
      • 检测和阻止非法网络流量。
    • 示例:监控并限制某些系统调用的使用。

      2.4 数据采集与分析

    • 功能:捕获系统运行时数据,提供高效的分析能力。

    • 常见用途

      • 通过 Perf Events 收集性能数据。
      • 使用 Maps 存储实时统计信息。
    • 示例:eBPF 数据用于调试或系统调优。

      2.5 内核扩展能力

    • 功能:通过用户态代码动态扩展内核功能。

    • 常见用途

      • 在不修改内核源码的情况下实现新功能。
      • 按需加载和卸载程序,降低系统维护成本。
    • 示例:动态插入日志记录或性能分析功能。


  1. 总结

eBPF 技术通过其核心模块(虚拟机、验证器、JIT 编译器、Maps、Helper Functions 和挂载点)为 Linux 内核提供了强大的扩展能力。这种动态、安全、高效的设计,使得 eBPF 成为现代系统优化、监控、安全和调试的核心工具。