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 在数据包处理路径中的位置差异:
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 程序从加载到卸载的完整生命周期,有助于排查“程序未生效”或“资源泄漏”类问题。
- 加载 (Load):用户空间工具(如
bpftool、Cilium Agent)通过bpf()系统调用将 BPF 字节码加载到内核。内核的 verifier 会进行严格的安全检查(模拟执行、拒绝循环、检查指针)。 - 附加 (Attach):将加载后的 BPF 程序挂载到指定的 Hook 点(如 XDP、TC、tracepoint)。Cilium 通常通过
netlink或bpf()系统调用的BPF_PROG_ATTACH命令完成。 - 运行 (Run):当内核事件(如数据包到达)触发 Hook 点时,BPF 程序在内核上下文中执行。程序可以访问 BPF Map、辅助函数,并返回一个动作码(如
XDP_PASS、XDP_DROP、TC_ACT_OK)。 - 分离 (Detach):当 Cilium Agent 重启或策略更新时,旧的 BPF 程序会被从 Hook 点分离。分离后,程序不再处理新事件。
- 卸载 (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 程序的挂载架构:
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 程序。