阶段三 · eBPF:让内核可编程

eBPF:从网络插件到新平台层

一句话总结

eBPF 让 Linux 内核从"只能用, 不能改"的黑盒, 变成"可以安全地动态编程"的平台. 它的意义早已超出网络: 网络, 安全, 可观测三大领域正在被同一项内核技术重写--这就是为什么人们说 eBPF 是云原生的"新平台层".

前置说明: 本篇与网络存储篇的分工

eBPF 的底层原理(Hook 点, Verifier, Map, Cilium 如何重写数据平面)在「云原生网络与存储」第 04 篇已深入讲过. 本篇不重复那些, 而是换一个视角: 跳出"网络插件"这个单一应用, 看清 eBPF 作为一整个新平台层的全景--它在网络, 安全, 可观测三个域同时掀起的变革.

如果还没读过网络存储篇的 eBPF 原理, 建议先扫一眼; 读过的话, 本篇带我们"登高望远".

先用一分钟回顾: eBPF 凭什么特别

(已熟悉的可跳过) eBPF 的核心是一句话: 把一段经过安全校验的小程序, 动态加载进内核, 挂在内核的各种钩子上运行, 无需改内核源码, 无需重启. 它之所以革命性, 在于三个保证:

特性 意义
安全 加载前经 Verifier 校验, 保证不会崩内核, 不会死循环
高效 内核态直接运行(可 JIT), 没有内核↔用户态切换开销
动态 随时加载/卸载, 钩子遍布网络, 系统调用, 追踪等几乎所有内核事件

关键洞察: 内核能"看见"系统里发生的一切--每个网络包, 每次系统调用, 每次文件访问, 每次进程创建, 都从内核经过. 过去这些只能"被动观察"(且要么改内核, 要么靠笨重的内核模块); eBPF 让我们能在这些事件发生的那一刻, 安全地插入自己的逻辑. 谁掌握了内核这个"咽喉", 谁就能重写建立在它之上的一切.

传统上, 内核像一座只能参观, 不能改造的古建筑: 想加个功能, 要么推倒重建(改内核源码), 要么搭个危险的违章建筑(内核模块, 易塌).
eBPF 像给这座建筑装了标准化的"可编程插槽": 能往插槽里安全地插入功能模块, 即插即用, 即拔即走, 还有安检(Verifier)确保插的东西不会把楼搞塌.

eBPF 的三大应用域: 同一把钥匙, 开三把锁

这是本篇的核心. 因为 eBPF 能"在内核里观察和干预一切事件", 同一项技术被用到了三个看似不相关的领域, 且都做得比传统方案更好:

                   eBPF
(内核可编程)

┌──────────────┼──────────────┐
▼ ▼ ▼
网络 安全 可观测
看见&干预 看见&拦截 看见每个事件
每个数据包 每次系统调用/进程 无侵入采集
│ │ │
▼ ▼ ▼
Cilium Tetragon/Falco Hubble/Pixie/Parca

域一: 网络(已在网络存储篇深讲)

因为 eBPF 能在数据包进入内核的最早路径处理它, Cilium 用它重写了 K8s 数据平面: 用哈希表查找(O(1))替代 kube-proxy 的 iptables 线性遍历(O(n)), 做 L7 策略, 基于身份而非 IP 的安全. 细节见网络存储篇第 04 篇, 这里只标定它在版图上的位置: 网络是 eBPF 最先成熟, 最广为人知的应用域.

域二: 安全(第 05 篇详讲)

因为 eBPF 能在每次系统调用, 每次进程创建, 每次文件访问发生时看到并介入, 它成了运行时安全的理想工具: 实时检测"容器里突然执行了一个可疑命令""有进程在读敏感文件""发起了异常的网络连接", 甚至当场拦截. 代表是 Tetragon 和 Falco--这是第 05 篇的主题, 本篇先埋下"安全是 eBPF 的第二大主场"这个点.

域三: 可观测(呼应可观测性系列)

这是 eBPF 最优雅的应用之一. 可观测性系列里我们费力地"埋点"才能采集数据; 而 eBPF 因为站在内核这个"必经之路"上, 能不改一行应用代码就采集到海量信号:

  • 网络层: Hubble(Cilium 自带)实时看服务间流量, 依赖拓扑
  • 应用层: Pixie 等能无侵入地抓取 HTTP/gRPC/SQL 调用的细节(自动 instrumentation)
  • 性能: Parca 等做持续性能剖析(continuous profiling), 无侵入定位 CPU 热点

可观测性系列反复强调"埋点"的成本(改代码, 维护, 易遗漏). eBPF 的可观测应用是对这个痛点的釜底抽薪: 既然内核能看见一切, 就让内核来采集, 应用零改动.

当然它有边界--eBPF 看到的是内核层视角(系统调用, 网络包), 拿不到应用内部的业务语义(比如"这是哪个用户的订单"), 所以它补充而非取代应用层的主动埋点(OpenTelemetry). 两者结合: eBPF 抓"无侵入的基础设施层信号", OTel 抓"有业务语义的应用层信号".

为什么说 eBPF 是"新平台层"

把三个域合起来看, 会发现一件深刻的事: 过去网络, 安全, 可观测是三套独立的技术栈, 三拨人, 三套工具; 而现在它们正在收敛到同一个底座--eBPF.

传统: 三个孤立的塔                  eBPF 时代: 三者共用一个新平台层
┌────┐ ┌────┐ ┌────┐ ┌────┐ ┌────┐ ┌────┐
│网络│ │安全│ │观测│ │网络│ │安全│ │观测│
│自成│ │自成│ │自成│ └─┬──┘ └─┬──┘ └─┬──┘
│一套│ │一套│ │一套│ ──▶ └──────┼──────┘
└────┘ └────┘ └────┘ ┌────▼─────┐
各装各的, 各管各的 │ eBPF │ ← 统一的内核可编程底座
│(新平台层)│
└──────────┘

"平台层"的含义就在这里: eBPF 不是某一个工具, 而是一个所有这些工具都构建于其上的, 可编程的基础设施层--就像 K8s 是"编排平台层", 容器是"打包平台层"一样, eBPF 正在成为"内核数据平面的平台层". 回到第 01 篇的抽象阶梯, 这是一次特殊的"下沉式抽象": 它没有往上加一层, 而是把最底下的内核那一层变得可编程, 从而让上面的网络/安全/观测都能被重新发明.

延续第 01 篇的克制: 绝大多数工程师不需要也不应该亲自写 eBPF 程序--那需要内核知识, 对版本敏感, 调试困难. 和 eBPF 的关系, 通常是使用那些基于 eBPF 构建的工具(Cilium, Tetragon, Pixie), 享受它的红利而不碰它的复杂度.

所以学习 eBPF 的正确姿势是: 理解它的能力边界和它赋能了哪些工具(这样选型时知道该往哪找), 而非一头扎进内核去写 BPF 字节码. 把它当"新平台层"来认知, 而非当"又一门要精通的编程技术".

快速回顾

  • eBPF 的本质(回顾): 安全, 高效, 动态地往内核钩子里插小程序; 底层原理见网络存储篇第 04 篇
  • 关键洞察: 内核能看见系统里的一切事件(包/系统调用/进程/文件), eBPF 让我们能在事件发生时安全介入--掌握内核咽喉, 就能重写其上的一切
  • 三大应用域: 网络(Cilium, 已深讲), 安全(Tetragon/Falco, 第 05 篇), 可观测(Hubble/Pixie/Parca, 无侵入采集)
  • eBPF 把可观测的"埋点税"降到近零, 但只能拿到内核层视角, 需与 OTel 应用层埋点互补
  • "新平台层": 网络/安全/观测从三套独立技术栈收敛到 eBPF 这个统一可编程底座; 是一次"让最底层内核可编程"的下沉式抽象
  • 理性视角: 我们多半是 eBPF 工具的间接用户, 理解其能力边界即可, 不必亲手写 eBPF

eBPF 既然能在内核看到/干预一切, 它本身安全吗? 会不会成为攻击面?

这是个好问题, 答案是"设计上有强约束, 但仍需谨慎". 正面: Verifier 保证加载的 eBPF 程序不会崩内核, 不会越界访存, 会终止--这比传统内核模块(能为所欲为)安全得多; 加载 eBPF 通常也需要高权限(如 CAP_BPF), 不是谁都能加载.

需警惕的一面: 正因为 eBPF 能力强大, 能观测和干预内核, 一旦攻击者获得了加载 eBPF 的权限, 它也可能被用于恶意监控或隐藏行踪(已有相关研究). 所以生产中要严格管控谁能加载 eBPF 程序. 能力越大, 权限越要收紧--这本身也是第 05 篇运行时安全要关注的.

eBPF 对内核版本有要求, 老系统用不了怎么办?

确实, eBPF 的高级能力依赖较新的内核(很多特性要 5.x 甚至更高), 老内核(如一些企业 Linux 的 3.x/4.x)支持有限. 应对方式:

  1. 升级内核(最彻底, 但有运维成本)
  2. 用支持 CO-RE(Compile Once - Run Everywhere) 的现代 eBPF 工具(如新版 Cilium/Tetragon), 它们对内核版本的兼容性做了大量工作, 能在较广的内核范围运行
  3. 评估时先确认内核版本够不够--这正是第 01 篇说的"它把复杂度/前提转移到哪": eBPF 把一部分前提转移成了"对内核版本的要求". 选型前务必核对.

动手练习

  1. 概括三域能力: 用一句话分别说出 eBPF 在网络, 安全, 可观测三个域各自的"杀手级能力", 并各举一个代表工具.
  2. 零埋点采集体验: 装一个基于 eBPF 的可观测工具(如 Cilium 的 Hubble, 或单机的 bpftrace), 不改任何应用代码, 观察它能采集到什么--亲身体会"零埋点采集".
  3. 检查内核版本: 用 uname -r 看机器的内核版本, 查一下它对 eBPF 的支持程度--理解"内核版本"这个前提.
  4. 信号边界对比: 对照可观测性系列, 列出 eBPF 工具无侵入拿到的信号, 和它拿不到,仍需 OpenTelemetry 应用层埋点的信号(提示: 业务语义).
  5. 平台层思考: 思考并写下: 为什么说 eBPF 是"新平台层"而不是"又一个网络插件"? 用本篇"三个域收敛到一个底座"的视角回答.