Cilium 分片跟踪与cilium-dbg bpf frag命令实战指南
【免费下载链接】ciliumeBPF-based Networking, Security, and Observability项目地址: https://gitcode.com/GitHub_Trending/ci/cilium
导读
当网络中传输的 IPv4/IPv6 数据报被分片(fragmentation)时,只有携带 L4 头的第一个分片才能用于基于四元组/五元组的数据路径处理。Cilium 借助 eBPF 的 LRU Hash Map 记录分片所属数据报的 L4 端口,从而在后续分片到达时恢复完整的 5 元组信息。本文以官方命令参考文档 cilium-dbg_bpf_frag.md 为主线,完整讲解cilium-dbg bpf frag与cilium-dbg bpf frag list命令的用法、选项与输出格式,并结合pkg/maps/fragmap、bpf/lib/ipv4.h、bpf/lib/ipv6.h等源码,深入剖析分片跟踪 BPF Map 的键值结构、创建时机与相关配置参数。读完本文,你将能够独立使用该命令查看节点上的分片跟踪表,并能读懂其输出背后的数据路径原理。
命令概览:cilium-dbg bpf frag
cilium-dbg bpf frag是cilium-dbg bpf(直接访问本地 BPF Map)家族下的一个子命令组,其职责是管理 IPv4 数据报分片(IPv4 datagram fragments)的跟踪信息。命令本身是一个分组命令,必须配合其子命令使用:
cilium-dbg bpf frag [command]命令定义位于 cilium-dbg/cmd/bpf_frag.go,源码中还为它注册了别名fragments,因此以下两种写法等价:
cilium-dbg bpf frag cilium-dbg bpf fragments分组命令支持一个通用选项:
Options: -h, --help help for frag当前该分组下只有一个子命令list(别名ls),即:
| 子命令 | 功能 | 文档 |
|---|---|---|
list/ls | 列出 IPv4 与 IPv6 分片 | cilium-dbg_bpf_frag_list.md |
查看分片跟踪表:cilium-dbg bpf frag list
cilium-dbg bpf frag list用于列出当前节点上被跟踪的 IPv4 与 IPv6 分片,其完整用法如下:
cilium-dbg bpf frag list [flags]执行该命令需要root 权限:从源码 cilium-dbg/cmd/bpf_frag_list.go 可以看到,命令入口首先调用common.RequireRootPrivilege("cilium bpf frag list")进行权限校验,普通用户直接执行会报权限错误。
子命令选项
Options: -h, --help help for list -o, --output string json| yaml| jsonpath='{}'-o, --output:指定输出格式,支持json、yaml以及jsonpath='{}'表达式。该选项由command.AddOutputOption(bpfFragListCmd)(见 bpf_frag_list.go)注册。
继承自父命令的全局选项
list子命令同时继承cilium-dbg的全局选项(见原命令文档),用于连接 agent、调试与控制日志:
| 选项 | 说明 |
|---|---|
--config string | 配置文件路径(默认$HOME/.cilium.yaml) |
-D, --debug | 开启调试信息 |
-H, --host string | server 端 API 的 URI |
--log-driver strings | 日志输出端点(例如syslog) |
--log-opt map | 日志驱动选项(例如format=json) |
默认表格输出
不带-o参数时,命令通过text/tabwriter输出对齐的文本表格,表头为ID / PROTO / SOURCE ADDRESS:PORT / DEST ADDRESS:PORT(见 printBPFFragmentEntries)。例如:
ID PROTO SOURCE ADDRESS:PORT DEST ADDRESS:PORT 12345 udp 10.0.0.1:4242 10.0.0.2:5353 67890 tcp [fd00::1]:4242 [fd00::2]:80字段含义:
- ID:分片所属数据报的 IP 分片标识(IPv4 的 Identification 字段 / IPv6 的 Fragment Identification),命令会通过
NativeID()将网络字节序转换为主机字节序后展示(IPv4 见 FragmentKey4.NativeID,IPv6 见 FragmentKey6.NativeID)。 - PROTO:L4 协议号,以符号名展示(如
tcp、udp),转换使用u8proto.U8proto(见 dumpFragmentsIPv4)。 - SOURCE ADDRESS:PORT / DEST ADDRESS:PORT:分片所属数据报的源/目的地址与 L4 端口。注意 IPv6 目的地址会以
[addr]:port形式展示,而源地址按addr:port形式展示(见 dumpFragmentsIPv6)。
当表中没有任何条目时,命令向 stderr 输出No entries found.;当某个地址族的分片跟踪未启用时,会输出IPv4 map doesn't exist, skipping或IPv6 map doesn't exist, skipping并继续处理另一个地址族(见 bpf_frag_list.go)。
机器可读输出(JSON / YAML)
结合-o参数可获得结构化输出,便于脚本与 Agent 解析:
# JSON 格式 cilium-dbg bpf frag list -o json # YAML 格式 cilium-dbg bpf frag list -o yaml # jsonpath 表达式 cilium-dbg bpf frag list -o 'jsonpath={.items[*].SourceAddress}'结构化的每条记录字段与表格列一一对应(见 bpfFragmentEntry):
[ { "ID": 12345, "Proto": "udp", "SourceAddress": "10.0.0.1:4242", "DestAddress": "10.0.0.2:5353" } ]数据路径中的分片跟踪原理
cilium-dbg bpf frag list展示的内容并非普通的状态数据,而是直接读取 Cilium agent 在数据路径(datapath)中维护的 eBPF Map,这正是命令被归入cilium-dbg bpf(Direct access to local BPF maps)家族的原因。
两个 LRU Hash Map
从 pkg/maps/fragmap/fragmap.go 可以看到,分片跟踪涉及两个独立的 BPF Map:
| 地址族 | BPF Map 名称 | 类型 |
|---|---|---|
| IPv4 | cilium_ipv4_frag_datagrams | BPF_MAP_TYPE_LRU_HASH |
| IPv6 | cilium_ipv6_frag_datagrams | BPF_MAP_TYPE_LRU_HASH |
Map 的类型与属性同样在 BPF 侧定义:IPv4 侧见 bpf/lib/ipv4.h(LRU_HASH+LIBBPF_PIN_BY_NAME+LRU_MEM_FLAVOR,上限为CILIUM_IPV4_FRAG_MAP_MAX_ENTRIES),IPv6 侧对应 bpf/lib/ipv6.h。
键值结构:与 BPF 头文件一一对应
Go 侧的键值类型被刻意设计为与 BPF C 结构体内存布局严格一致,并有注释明确对应关系:
- IPv4 键
FragmentKey4对应struct ipv4_frag_id(daddr / saddr / id / proto),值FragmentValue4对应struct ipv4_frag_l4ports(sport / dport)——见 fragmap.go 与 bpf/lib/ipv4.h。 - IPv6 键
FragmentKey6对应struct ipv6_frag_id(id / proto / pad / saddr / daddr),值FragmentValue6对应struct ipv6_frag_l4ports——见 fragmap.go 与 bpf/lib/ipv6.h。
这种内存对齐约束由 tools/alignchecker(bpf_alignchecker.c中add_type(struct ipv4_frag_id)等条目)在构建期进行校验,确保 Go 用户态与 BPF 内核态看到的键值布局一致。
分片跟踪解决什么问题
包文档 pkg/maps/fragmap/doc.go 给出了该功能的定位:将分片关联到其所属数据报的 L4 端口,从而恢复执行 L4 查找所需的完整 5 元组。
其工作流程(可从 bpf/lib/ipv4.h 与 bpf/lib/ipv6.h 的函数推断)大致如下:
- 当一个分片到达时,数据路径解析出分片标识、协议、源/目的地址,构造
ipv4_frag_id/ipv6_frag_id作为查找键; - 若该分片是携带 L4 头的首片,则把
sport/dport写入对应 Map; - 后续到达的非首片通过同一键在 Map 中查得 L4 端口,拼出完整 5 元组后继续执行基于 L4 的策略查找(例如 L4 负载均衡、策略匹配);
- 由于使用 LRU Hash,旧分片会被自动逐出,无需显式清理。
Map 的创建时机与 CLI 的只读访问
值得强调的是:这两个 BPF Map 由 Cilium agent 在启动阶段创建,cilium-dbg只负责打开读取。Map 的生命周期由 Hive 单元fragments-map管理(见 pkg/maps/fragmap/cell.go),在OnStart钩子中调用fragMap.init()完成创建。注释明确指出(fragmap.go):该 Map 仅由 agent 为数据路径创建,Map接口本身不向 agent 提供额外功能,仅作为依赖被 Loader 拾取以在启动时初始化。
CLI 侧则通过fragmap.OpenMap4/OpenMap6(fragmap.go)打开预初始化的 Map——其注释注明"仅供无法使用 Hive 的组件(主要是 cilium-dbg)使用,需由 Cilium agent 预先初始化"。这解释了为何在未启用相应跟踪或 agent 未启动时,命令会输出 "map doesn't exist, skipping" 而不是报错。
相关配置参数
分片跟踪是可选功能,由以下 agent 配置项控制(定义与默认值见 pkg/option/config.go 与 pkg/defaults/defaults.go):
| 配置项 | 说明 | 默认值 |
|---|---|---|
enable-ipv4-fragment-tracking | 启用 IPv4 分片跟踪 | 由 agent 默认配置决定 |
enable-ipv6-fragment-tracking | 启用 IPv6 分片跟踪 | 由 agent 默认配置决定 |
bpf-fragments-map-max | 分片 BPF Map 允许的最大条目数 | 8192 |
参数在 config.go 中从 viper 读取,并会进行范围校验:小于FragmentsMapMin或大于FragmentsMapMax的取值会被钳制到合法范围(见 config.go),相关边界在 pkg/option/config_test.go 中有对应测试用例。
从源码结构可以推断:newMap在构造时会根据option.Config.EnableIPv4FragmentsTracking与EnableIPv6FragmentsTracking决定是否创建对应地址族的 Map(见 fragmap.go),而maxMapEntries由daemonConfig.FragmentsMapEntries(即bpf-fragments-map-max)传入。因此,若某地址族跟踪未启用,frag list就会输出对应的 "doesn't exist" 提示。
实战:分片表排查流程
将上述命令组合起来,即可形成一套完整的分片跟踪排查流程:
# 1. 确认分片跟踪是否启用(查看 agent 配置) cilium-dbg config view | grep -i fragment # 2. 查看当前节点被跟踪的分片(表格形式) cilium-dbg bpf frag list # 3. 使用别名与机器可读输出,便于过滤分析 cilium-dbg bpf fragments ls -o json | jq '.[] | select(.Proto=="udp")' # 4. 若未启用,检查 agent 启动参数中的跟踪开关与 map 上限 # enable-ipv4-fragment-tracking / enable-ipv6-fragment-tracking / bpf-fragments-map-max典型解读场景:
- 表中出现大量条目且持续增长:说明节点存在较多分片流量,可关注
bpf-fragments-map-max(默认 8192)是否偏小导致 LRU 频繁逐出,或结合 BPF Map 压力指标观察; - 仅 IPv4 有数据而 IPv6 提示 map 不存在:说明只启用了
enable-ipv4-fragment-tracking; - 结合 bpf/tests/tc_nodeport_lb_fragments.h 中针对
ipv4_frag_id/ipv6_frag_id的构造与断言,可以进一步验证分片经过 nodeport/LB 路径时 L4 端口的恢复逻辑是否符合预期。
关联命令与进一步阅读
cilium-dbg bpf frag隶属cilium-dbg bpf家族,与其相关的命令与资料包括:
- 父命令:cilium-dbg bpf(Direct access to local BPF maps),其中还包含
frag、ipcache、ct、nat、lb、metrics等子命令; - 子命令:cilium-dbg bpf frag list;
- Go 侧 Map 实现:pkg/maps/fragmap/fragmap.go、pkg/maps/fragmap/cell.go、pkg/maps/fragmap/doc.go;
- BPF 侧键值结构与查找逻辑:bpf/lib/ipv4.h、bpf/lib/ipv6.h;
- 分片相关测试:bpf/tests/tc_nodeport_lb_fragments.h。
值得注意的是,命令参考文档由cilium-dbg的 cobra 定义自动生成(文档头部标注 "autogenerated via cilium-dbg cmdref"),实际命令行为以仓库内 cilium-dbg/cmd/bpf_frag.go 与 cilium-dbg/cmd/bpf_frag_list.go 的源码为准。
【免费下载链接】ciliumeBPF-based Networking, Security, and Observability项目地址: https://gitcode.com/GitHub_Trending/ci/cilium
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考