3. eBPF 数据面基础:XDP 与 TC hook 点、BPF Map、BPF 程序生命周期、eBPF 在 Cilium 中的典型挂载点

在 Serverless 场景下,容器网络数据面的性能直接决定了 Pod 启动延迟与吞吐上限。Cilium 的核心竞争力在于利用 eBPF 技术将网络处理逻辑下沉到内核,绕过传统的 iptables 和 netfilter 框架。理解 eBPF 的数据面基础,是诊断 Cilium 网络性能瓶颈的前提。

3.1 XDP 与 TC:两个关键 Hook 点

eBPF 程序通过挂载到内核的特定 Hook 点来拦截和处理网络数据包。在 Cilium 的数据面中,最核心的两个 Hook 点是 XDP (eXpress Data Path) 和 TC (Traffic Control)。

特性 XDP (eXpress Data Path) TC (Traffic Control)
挂载位置 网卡驱动层,在 SKB (Socket Buffer) 分配之前 内核网络协议栈的 TC 层,在 SKB 分配之后
处理阶段 最早的数据包处理点,接近硬件 标准网络栈的入口/出口,支持更丰富的操作
性能 极高,可绕过整个协议栈,适合 DDoS 防护、负载均衡 较高,但比 XDP 多一次 SKB 分配开销
能力限制 无法直接修改 SKB 元数据,不支持 GRO/GSO 等 offload 可以修改 SKB 元数据,支持隧道封装、流量整形
Cilium 用途 NodePort 加速、DSR (Direct Server Return)、策略过滤 L3/L4 网络策略、隧道封装 (VXLAN/Geneve)、Service 转发
性能调优提示: 在 Serverless 平台中,如果 Pod 密度极高且对 PPS (Packet Per Second) 敏感,优先启用 XDP 模式处理 NodePort 流量。XDP 可以避免 SKB 分配,将延迟降低到微秒级。但需注意,XDP 不支持所有网卡驱动,且无法处理分片包。

下图展示了 XDP 与 TC 在数据包处理路径中的位置差异:

XDP 与 TC Hook 点在内核网络栈中的位置 网卡硬件 (NIC) 网卡驱动 (Driver) XDP Hook (eXpress Data Path) 内核网络协议栈 (SKB 分配 & 处理) TC Hook (Traffic Control Ingress/Egress)

3.2 BPF Map:eBPF 程序的数据交换中枢

BPF Map 是 eBPF 程序与用户空间、以及不同 eBPF 程序之间交换数据的核心数据结构。它本质上是一个键值存储,驻留在内核内存中。Cilium 大量使用 BPF Map 来存储连接跟踪表、策略规则、端点信息、负载均衡后端等。

3.2.1 常见 Map 类型与用途

Map 类型 数据结构 Cilium 典型用途
BPF_MAP_TYPE_HASH 哈希表 连接跟踪 (CT Map)、策略映射 (Policy Map)、端点映射 (Endpoint Map)
BPF_MAP_TYPE_ARRAY 数组 全局统计计数器、固定大小的查找表
BPF_MAP_TYPE_LRU_HASH LRU 哈希表 连接跟踪 (CT Map),自动淘汰旧条目,防止内存泄漏
BPF_MAP_TYPE_PERCPU_HASH Per-CPU 哈希表 高性能计数器,每个 CPU 独立副本,避免锁竞争
BPF_MAP_TYPE_SOCKMAP Socket 映射 Socket 重定向 (SK_MSG/SK_SKB),加速本地进程间通信
性能瓶颈诊断点: BPF Map 的查找和更新操作是 eBPF 程序的主要开销来源。在 Serverless 高并发场景下,如果 CT Map 过大导致哈希冲突增加,或者 Per-CPU Map 的 CPU 亲和性不佳,会直接导致 PPS 下降和延迟抖动。建议通过 bpftool map show 监控 Map 的 max_entries 和 bytes_used。

3.3 BPF 程序生命周期

理解 BPF 程序从加载到卸载的完整生命周期,有助于排查“程序未生效”或“资源泄漏”类问题。

  1. 加载 (Load):用户空间工具(如 bpftool、Cilium Agent)通过 bpf() 系统调用将 BPF 字节码加载到内核。内核的 verifier 会进行严格的安全检查(模拟执行、拒绝循环、检查指针)。
  2. 附加 (Attach):将加载后的 BPF 程序挂载到指定的 Hook 点(如 XDP、TC、tracepoint)。Cilium 通常通过 netlink 或 bpf() 系统调用的 BPF_PROG_ATTACH 命令完成。
  3. 运行 (Run):当内核事件(如数据包到达)触发 Hook 点时,BPF 程序在内核上下文中执行。程序可以访问 BPF Map、辅助函数,并返回一个动作码(如 XDP_PASS、XDP_DROP、TC_ACT_OK)。
  4. 分离 (Detach):当 Cilium Agent 重启或策略更新时,旧的 BPF 程序会被从 Hook 点分离。分离后,程序不再处理新事件。
  5. 卸载 (Unload):当 BPF 程序的引用计数降为 0(所有 Hook 点已分离,且无用户空间文件描述符引用),内核会释放其占用的内存和 BPF Map。
关键命令: 使用 bpftool prog list 查看当前加载的所有 BPF 程序及其 ID;使用 bpftool prog show id <id> --pretty 查看程序详情,包括附加到的 Hook 点、Map 关联、运行次数等。

3.4 eBPF 在 Cilium 中的典型挂载点

Cilium 将 eBPF 程序挂载到多个内核 Hook 点,以实现完整的容器网络功能。下图展示了 Cilium 数据面中 eBPF 程序的挂载架构:

Cilium 中 eBPF 程序的典型挂载点 网络数据包路径 eth0 (物理网卡) XDP: bpf_xdp (NodePort/DSR) TC Ingress: bpf_netdev TC Egress: bpf_netdev veth (容器对端) 容器内部 (Pod) eth0 (容器网卡) TC Ingress: bpf_lxc TC Egress: bpf_lxc Socket: bpf_sock (connect/sendmsg) cgroup: bpf_cgroup (策略)

3.4.1 关键挂载点说明

  • bpf_xdp (XDP):挂载在宿主机物理网卡上,用于处理入站 NodePort 流量。通过 DSR 模式,可以直接将数据包转发到目标 Pod,避免额外的 SNAT 开销。
  • bpf_netdev (TC Ingress/Egress):挂载在宿主机物理网卡或隧道设备上。Ingress 方向负责 VXLAN/Geneve 解封装、策略执行;Egress 方向负责封装、负载均衡。
  • bpf_lxc (TC Ingress/Egress):挂载在容器 veth 对的宿主机端。Ingress 方向负责入站策略检查;Egress 方向负责出站策略检查、连接跟踪。
  • bpf_sock (Socket):挂载在 cgroup 层级,拦截 connect、sendmsg、recvmsg 等系统调用。用于实现 Socket 级别的负载均衡和策略,绕过完整的网络栈,延迟极低。
  • bpf_cgroup (cgroup):挂载在 cgroup 层级,用于实现基于 cgroup 的网络策略,控制 Pod 的出站和入站流量。
诊断切入点: 当遇到 Pod 间通信延迟高或不通时,首先检查对应 veth 对的 bpf_lxc 程序是否正常加载。使用 tc filter show dev lxc+ ingress 和 tc filter show dev lxc+ egress 可以查看 TC 挂载点上的 BPF 程序。