eBPF 程序开发入门:从原理到生产级工具构建

概述 eBPF(Extended Berkeley Packet Filter)是 Linux 内核领域近十年来最具革命性的技术之一。它允许开发者在不修改内核源代码、不加载内核模块的前提下,安全高效地在内核空间运行自定义程序。从网络包过滤到系统调用追踪、从性能分析到安全审计,eBPF 已经成为现代可观测性和网络数据面的基石。 我将从 eBPF 的基本原理出发,逐步深入到开发环境搭建、程序类型选择、BCC 与 libbpf+CO-RE 的工程对比,最后给出一个完整的生产级 eBPF 工具开发流程。适合有一定 Linux 内核基础的 SRE 工程师和系统开发者阅读。 一、eBPF 的演进:从 BPF 到 eBPF 1.1 经典 BPF(cBPF) 1992 年,Steven McCanne 和 Van Jacobson 在论文《The BSD Packet Filter: A New Architecture for User-level Capture》中提出了 BPF。其核心思想是将一个基于寄存器的虚拟机嵌入内核,允许用户将过滤程序注入内核空间,只有匹配的网络包才会被复制到用户态,从而大幅减少不必要的上下文切换开销。 经典 BPF 的局限性很明显: 特性 cBPF eBPF 寄存器数量 2 个 32 位 11 个 64 位 指令集 简单,仅支持包过滤 丰富,支持函数调用、64 位运算 程序大小 严格限制(4096 指令) 百万级指令(经验证器检查) 挂载点 仅网络包 系统调用、内核函数、跟踪点、网络等 安全机制 基本检查 验证器 + JIT 编译 1....

April 1, 2025 · 13 分钟 · 2562 字 · 徐保金

Linux 性能分析利器:BPF 与 bcc 工具集

eBPF:内核可编程的革命 传统性能分析工具分两类:一类是 top、vmstat、iostat 这样的"概览型"工具,告诉你系统层面发生了什么,但看不到细节;另一类是 strace、gdb 这样的"跟踪型"工具,能看细节但开销巨大,生产环境基本不敢用。 eBPF(Extended Berkeley Packet Filter)改变了一切。它允许你在不修改内核源码、不加载内核模块的前提下,安全地在内核中运行沙箱程序。这些程序挂载到内核的 hook 点(kprobes、tracepoints、perf events 等),在事件发生时被触发执行,采集数据后通过 ring buffer 传递到用户态。 为什么说这是革命性的?三个原因: 安全:eBPF 程序在加载时经过验证器(verifier)检查,确保不会死循环、不会非法访问内存,不需要 root 权限加载内核模块的风险。 低开销:eBPF 程序在内核态直接执行,只有采集到的数据才通过 ring buffer 拷贝到用户态,热路径上的开销极小。 可编程:你可以针对自己的具体问题编写精确的探针程序,而不是依赖通用工具"凑合"用。 eBPF 的完整技术文档可参考 BPF Compiler Collection (BCC) 官方仓库,本文所有工具均来自该项目。 bcc 工具集安装 bcc(BPF Compiler Collection)是基于 eBPF 的性能分析工具集,由 iovisor 项目维护,提供了数十个开箱即用的追踪工具。 Ubuntu / Debian # Ubuntu 20.04+ 推荐方式 sudo apt update sudo apt install -y bpfcc-tools linux-headers-$(uname -r) # 验证安装 /usr/share/bcc/tools/biolatency --help CentOS / RHEL # CentOS 8 / RHEL 8+ sudo dnf install -y bcc-tools kernel-devel-$(uname -r) # CentOS 7 需通过 ELRepo sudo yum install -y epel-release sudo yum install -y bcc-tools kernel-devel-$(uname -r) # 工具默认安装在 /usr/share/bcc/tools/ 目录下 ls /usr/share/bcc/tools/ 安装后建议将工具路径加入 PATH:...

November 13, 2024 · 5 分钟 · 953 字 · 徐保金

cgroup v2 完全指南:从架构原理到生产实践

概述 在云原生和容器化技术全面普及的今天,Linux cgroup(控制组)作为资源隔离和限制的内核基石,其重要性不言而喻。从 Docker 容器的内存限制到 Kubernetes Pod 的 CPU Requests/Limits,底层都依赖 cgroup 机制。然而,cgroup v1 的多层级架构、控制器行为不一致、线程模型混乱等历史包袱,让运维人员在生产环境中频频踩坑。 cgroup v2 作为对 v1 的彻底重构,采用单一层级树(unified hierarchy)架构,从根本上解决了 v1 的设计缺陷。自 Linux 4.5 引入以来,经过多个内核版本的迭代完善,cgroup v2 在 5.x 内核上已趋于成熟稳定。Ubuntu 22.04+、RHEL 9+、Debian 12+ 等主流发行版已默认使用 cgroup v2,Docker 和 Kubernetes 也已全面支持。 我将从 cgroup v2 的架构原理出发,深入讲解核心控制器的工作机制,结合 systemd 集成、Docker 容器限制、Kubernetes 场景等实战配置,最后覆盖 v1 到 v2 的迁移策略,帮助你在生产环境中驾驭这一关键技术。 cgroup v1 vs v2:为什么要重构 v1 的核心痛点 cgroup v1 在设计之初,每个控制器可以独立挂载在不同的层级树上。这带来了灵活性,但也埋下了大量隐患: 问题维度 v1 表现 影响 多层级架构 每个控制器可挂载在独立的层级树 进程在不同控制器中可属于不同 cgroup,管理视图割裂 线程模型 进程的线程可分散到不同 cgroup 资源计量混乱,难以准确归因 控制器间协调 各控制器独立运作 无法做跨资源的统一策略(如 CPU 和内存的联动) 委派安全 子 cgroup 委派权限粗粒度 容器逃逸风险,安全边界模糊 接口一致性 不同控制器文件命名和语义不统一 运维认知负担高,脚本维护困难 v2 的设计哲学 cgroup v2 的核心设计原则是单一层级树(unified hierarchy):整个系统只有一棵 cgroup 树,所有控制器挂载在同一棵树上。一个进程只属于一个 cgroup,该 cgroup 上可以同时启用 CPU、内存、IO 等多个控制器。...

July 23, 2024 · 17 分钟 · 3430 字 · 徐保金