如何观测 eBPF 程序的 map 命中次数以定位网络延迟

解读

在国内云原生面试中,“观测 eBPF map 命中次数”常被用来验证候选人是否具备内核级网络排障能力。Docker 场景下,网络延迟可能来自 veth、bridge、iptables、CNI 插件乃至宿主机内核路径,eBPF 程序(tc/xdp/cgroup)是排查这类亚毫秒级毛刺的利器。面试官期望你给出一条可落地的全链路观测方案,而不是简单罗列 bpftool 命令;同时必须兼顾生产安全(不能随意改镜像、不能重启容器)与权限合规(国内大厂宿主机通常启用 SELinux/AppArmor、SecComp)。

知识点

  1. eBPF map 类型与命中语义:HASH、PERCPU_HASH、LRU_HASH 的命中指 map_lookup_elem() 返回非 NULL;ARRAY 命中指索引在范围内。
  2. 内核暴露的统计接口:/proc/sys/net/core/bpf_jit_enable 开启后,map 元素查找次数由内核 kfunc bpf_map_lookup_elem() 内的原子计数器记录,可通过 bpf_map_info 的 id + fd 读取。
  3. 观测工具链
    • bpftool(>=5.8)支持 bpftool map show id <ID> -d 打印 lookup_cntrefcnt
    • bcc/libbpf 程序可自定义 __sync_fetch_and_add(&map->lookup_cnt, 1) 实现业务级命中统计。
    • perf stat -e bpf:bpf_map_lookup_elem 可采样 miss/hit 事件,但需内核 CONFIG_BPF_EVENTS=y。
  4. Docker 网络路径
    容器 → veth → docker0 → iptables/raw/mangle/nat → 宿主机物理网卡;tc egress/ingress 钩子挂载在 veth 容器侧或宿主机侧,命中次数低说明包未走到 eBPF 程序,需检查 qdisc 绑定位置
  5. 最小权限实践:国内合规要求容器内不能携带 CAP_SYS_ADMIN,观测侧容器需独立 privileged DaemonSet,通过 hostPID+hostNetwork 挂载 /sys/fs/bpf,与业务容器解耦。

答案

给出一套在不改业务镜像、不重启容器的前提下,5 分钟内定位网络延迟是否由 eBPF map miss 引起的实战步骤:

  1. 定位延迟点
    在宿主机执行 netqtop -t 1(阿里自研开源)或 tc -s qdisc show dev vethxxx,若看到 tc 层延迟 >0.3 ms 且抖动明显,初步怀疑 tc-eBPF。

  2. **找到对应 map:
    bpftool net show 列出附着在 vethxxx 的 prog id,假设为 123;
    bpftool prog show id 123 得到 map_ids 456。

  3. **观测命中次数:
    bpftool map show id 456 -d | grep lookup_cnt
    连续采样 3 次,间隔 1 秒:

    while :; do bpftool map show id 456 -d | awk '/lookup_cnt/{print $2}'; sleep 1; done
    

    若 lookup_cnt 每秒增长量 远小于 PPS,说明大量包未命中 map,出现 map miss

  4. **验证 miss 导致延迟:
    在 eBPF 代码中把 miss 路径打上 bpf_trace_printk:“miss tcp_sock key=%u”,
    宿主机 cat /sys/kernel/debug/tracing/trace_pipe | grep miss 若随延迟同步出现,即可确认。

  5. **根因与修复:
    国内常见原因是 Docker 热重启后 veth 索引变化,而 eBPF map key 仍用旧 ifindex。
    修复:在 eBPF 中使用 bpf_get_socket_cookie()bpf_sk_lookup_tcp() 做 key,避免依赖 ifindex;上线前通过 GitLab-CI 的 eBPF 单元测试 用 trafficgen 打 1 Mpps,断言 lookup_cnt/PPS > 99%。

拓展思考

  1. 云原生可观测性融合:将 map lookup_cnt 封装为 Prometheus metric,via bpf_exporter,Grafana 面板同时展示 PPS、lookup_cnt、RTT,实现 miss 与延迟的 1:1 关联告警
  2. 多租户安全:在金融级容器平台中,宿主机 eBPF 只读观测需启用 BPF LSM 策略,禁止非授信容器调用 bpf() syscall,防止恶意篡改 map。
  3. 无特权替代方案:若宿主机内核 >=5.10,可用 BPF CO-RE 将统计逻辑编译进 tracee-ebpf,容器侧仅挂载 tracee 的 unix socket 读取命中数据,全程无需 CAP_BPF,满足国内银行监管“容器零特权”红线。