news 2026/9/12 18:10:23

Cilium 连接跟踪(Connection Tracking)排查实战:cilium-dbg bpf ct 命令族完全指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Cilium 连接跟踪(Connection Tracking)排查实战:cilium-dbg bpf ct 命令族完全指南

Cilium 连接跟踪(Connection Tracking)排查实战:cilium-dbg bpf ct 命令族完全指南

【免费下载链接】ciliumeBPF-based Networking, Security, and Observability项目地址: https://gitcode.com/GitHub_Trending/ci/cilium

导读

本文围绕 Cilium 数据面最核心的状态机制——eBPF 连接跟踪(Connection Tracking, CT)展开,以官方命令参考文档 Documentation/cmdref/cilium-dbg_bpf_ct.md 为主体,结合仓库源码深入剖析cilium-dbg bpf ct命令族的实现原理。读完本文,你将掌握如何列出并解读节点上 TCP/UDP 等连接跟踪表中的条目、如何按集群维度查看 CT 状态、如何用时钟源换算条目存活时间,以及如何安全地清空全部连接跟踪条目,并理解这些操作在 BPF 层面对应哪张 map、走的是哪条调用链。

1. 连接跟踪(CT)在 Cilium 中的地位

Cilium 基于 eBPF 实现网络、安全与可观测性,而连接跟踪是这一切的基石:数据路径(datapath)中的 BPF 程序需要为每个流维护"谁发起、谁响应、属于哪个安全身份"的状态,才能完成 NAT(网络地址转换)、反向 NAT、状态化防火墙策略判定以及按连接维度统计流量。这些状态被持久化在位于/sys/fs/bpf/tc/globals/下的多个 BPF map 中。

从源码 pkg/maps/ctmap/types.go 可以看到,Cilium 将 CT map 按两个维度划分为四类:

  • 协议族维度:IPv4 与 IPv6;
  • 协议类型维度:TCP(有状态协议,需要精细的流转状态机)与非 TCP(Any,涵盖 UDP、ICMP 等)。

对应关系如下:

mapType说明
mapTypeIPv4TCPGlobal全局 IPv4 TCP CT map
mapTypeIPv6TCPGlobal全局 IPv6 TCP CT map
mapTypeIPv4AnyGlobal全局 IPv4 非 TCP CT map
mapTypeIPv6AnyGlobal全局 IPv6 非 TCP CT map

在 pkg/maps/ctmap/ctmap.go 中定义了四个全局 map 的实际名称:tcp4globaltcp6globalany4globalany6globalcilium-dbg bpf ct系列命令正是这些 map 的用户态操作入口。

2. 命令族总览:cilium-dbg bpf ct

2.1 命令定义

cilium-dbg bpf ct

描述:Connection tracking tables(连接跟踪表),即访问 Cilium 节点本地连接跟踪 BPF map 的总入口。

选项

-h, --help help for ct

该命令本身不执行具体操作,仅作为list(列表)与flush(清空)两个子命令的父命令容器。在源码中,它对应 cilium-dbg/cmd/bpf_ct.go 里定义的BPFCtCmd

// BPFCtCmd represents the bpf_ct command var BPFCtCmd = &cobra.Command{ Use: "ct", Short: "Connection tracking tables", } func init() { BPFCmd.AddCommand(BPFCtCmd) }

可以看到它挂载在BPFCmd(即cilium-dbg bpf,对应文档 Documentation/cmdref/cilium-dbg_bpf.md)之下,与bpf natbpf lb等命令平级,遵循 Cilium 统一的 "Direct access to local BPF maps" 设计。

2.2 全局父命令继承选项

ctct listct flush均继承自cilium-dbg根命令的通用选项:

--config string 配置文件(默认 $HOME/.cilium.yaml) -D, --debug 启用调试消息 -H, --host string 服务端 API 的 URI --log-driver strings 日志端点(示例:syslog) --log-opt map 日志驱动选项(示例:format=json)

其中-H/--host用于指定 Cilium agent 的 API 地址,调试与日志选项用于输出诊断信息,这些选项在所有cilium-dbg bpf *子命令中保持一致,方便脚本化调用与故障排查。

2.3 子命令一览

* cilium-dbg bpf ct flush - 清空所有连接跟踪条目 * cilium-dbg bpf ct list - 列出连接跟踪条目

3. 列出连接跟踪条目:cilium-dbg bpf ct list

3.1 语法与输出格式选项

cilium-dbg bpf ct list [cluster <identifier>] [flags]

该命令列出节点上的连接跟踪条目,是排查连接建立失败、NAT 异常、流表堆积等问题的第一入口。参数与选项如下:

参数/选项说明
[cluster <identifier>]可选,指定要查看的集群 ID(ClusterMesh 多集群场景),省略时默认查看global本节点全局 map
-o, --output string输出格式,支持jsonyamljsonpath='{}'
-d, --time-diff打印条目的剩余存活时间差(time difference),便于判断条目何时过期
--time-diff-clocksource-hz int手动指定时钟源频率 Hz(默认 250),仅在 jiffies 模式且不向服务端查询时使用
--time-diff-clocksource-mode string手动指定时钟源模式(ktime/jiffies),而不是向服务端查询

从源码 cilium-dbg/cmd/bpf_ct_list.go 可以看到命令别名ls与三个 flag 的注册:

var bpfCtListCmd = &cobra.Command{ Use: "list [cluster <identifier>]", Aliases: []string{"ls"}, Short: "List connection tracking entries", Run: func(cmd *cobra.Command, args []string) { t, id, err := parseArgs(args) ... }, }

3.2 参数解析:global 与 cluster 两种视图

parseArgs(cilium-dbg/cmd/bpf_ct_list.go)实现了参数校验:

  • 不带参数:等价于传入global,读取本节点全局 CT map(向后兼容旧行为);
  • cluster <identifier>:解析集群 ID,并通过cmtypes.ValidateClusterID校验其取值范围,随后调用ctmap.GetClusterCTMaps(id, ipv4, ipv6)读取该集群维度的 CT map(对应 pkg/maps/ctmap/per_cluster_ctmap.go 中的 per-cluster CT map 实现);
  • 其他参数:报错unknown type

getMaps(cilium-dbg/cmd/bpf_ct_list.go)会根据getIpEnableStatuses()探测当前节点是否启用了 IPv4/IPv6,再决定实际读取哪几张 map。对于global视图,调用 pkg/maps/ctmap/ctmap.go 中的ctmap.Maps(ipv4, ipv6)

// Maps returns a slice of all CT maps that are used. func Maps(ipv4, ipv6 bool) []*Map { result := make([]*Map, 0, mapCount) if ipv4 { result = append(result, newMap(MapNameTCP4Global, mapTypeIPv4TCPGlobal)) result = append(result, newMap(MapNameAny4Global, mapTypeIPv4AnyGlobal)) } if ipv6 { result = append(result, newMap(MapNameTCP6Global, mapTypeIPv6TCPGlobal)) result = append(result, newMap(MapNameAny6Global, mapTypeIPv6AnyGlobal)) } return result }

即最多遍历tcp4globalany4globaltcp6globalany6global四张 map。每张 map 通过ctmap.OpenCTMap(pkg/maps/ctmap/ctmap.go)打开;若某张 map 不存在(例如未启用 IPv6),会打印Unable to open <path>: <err>. Skipping.并跳过,而不会中断整个命令。

3.3 条目内容:五元组 Key 与 CT Entry Value

list输出的每条记录由一个 Key 和一个 Value 组成。测试用例 cilium-dbg/cmd/bpf_ct_list_test.go 给出了直观的样例:

  • Key(五元组):目的地址DestAddr、源地址SourceAddr、目的端口DestPort、源端口SourcePort、下一层协议号NextHeader(6 为 TCP、17 为 UDP)以及标志位Flags
  • Value(CtEntry):包含Packets/Bytes(该方向累计的包数与字节数)、Lifetime(剩余存活时间)、FlagsRevNAT(反向 NAT 端口)、TxFlagsSeen/RxFlagsSeen(观测到的 TCP 收发标志位)、SourceSecurityID(源安全身份,对应 Cilium 的 identity 机制)以及LastTxReport/LastRxReport(最近一次收发的时间戳,用于计算 time-diff)。

这些字段定义在 pkg/maps/ctmap 与 pkg/tuple 中,是解读流状态的关键依据。

3.4 文本输出与结构化输出(JSON/YAML/jsonpath)

dumpCt(cilium-dbg/cmd/bpf_ct_list.go)实现了两种输出路径:

  • 文本模式(默认):对每张 map 调用doDumpEntries,最终走m.DumpEntriesWithTimeDiff(clockSource)(pkg/maps/ctmap/ctmap.go),逐条打印五元组与状态信息,立即输出,适合人工阅读;
  • 结构化模式(指定-o json|yaml|jsonpath):通过command.AddOutputOption注册的 output 选项触发。此时命令会先通过DumpWithCallback把四张 map 的条目统一收集到内存,待全部读取完毕后再输出一份一致的完整对象,避免 JSON/YAML 被多张 map 的输出切碎,方便jqyq进一步加工。

常用示例:

# 文本方式查看本节点全部 CT 条目 cilium-dbg bpf ct list # 以 JSON 输出,交给 jq 过滤(例如只看 TCP 条目) cilium-dbg bpf ct list -o json | jq '.[] | select(.key.NextHeader == 6)' # 查看指定集群 ID 的 CT 条目(ClusterMesh 场景) cilium-dbg bpf ct list cluster 1 # 打印每条目剩余存活时间(依赖时钟源换算) cilium-dbg bpf ct list -d

lslist的别名,两者等价。

3.5 深入解析-d/--time-diff:时钟源(ClockSource)换算

CT 条目中记录的Lifetime与时间戳不是墙上时钟,而是 BPF 侧单调时钟的"tick"计数,直接打印对用户不友好。因此-d选项需要先确定时钟源模式,再换算为秒:

getClockSource(cilium-dbg/cmd/bpf_ct_list.go)的优先级如下:

  1. 未指定--time-diff-clocksource-mode时,调用timestamp.GetClockSourceFromAgent(client.Daemon)(pkg/maps/timestamp/timestamp.go)向 Cilium agent 查询真实时钟源;查询失败则回退到GetClockSourceFromRuntimeConfig()读取本地运行配置;
  2. 指定ktime模式时,直接构造ClockSource{Mode: ktime},tick 与纳秒一一对应;
  3. 指定jiffies模式时,必须提供非零的--time-diff-clocksource-hz(即内核 HZ,默认 250),否则报错invalid HZ value;换算时用 tick 除以 Hz 得到秒数(见 pkg/maps/timestamp/timestamp.go 中 ktime/jiffies 两种换算分支);
  4. 其他模式字符串直接报错invalid clocksource

因此,若 agent 不可达但你又需要-d输出,可以手动指定模式与频率,例如在 HZ=100 的内核上:

cilium-dbg bpf ct list -d --time-diff-clocksource-mode jiffies --time-diff-clocksource-hz 100

4. 清空连接跟踪条目:cilium-dbg bpf ct flush

4.1 语法与选项

cilium-dbg bpf ct flush [flags]

描述:Flush all connection tracking entries(清空所有连接跟踪条目)。该命令只有-h/--help一个选项。

4.2 实现原理:一次基于 GC 机制的批量清理

与直觉不同,flush并非简单地逐条Delete,而是复用了 CT map 的垃圾回收(GC)机制。源码 cilium-dbg/cmd/bpf_ct_flush.go 的流程如下:

  1. 通过getIpEnableStatuses()判断 IPv4/IPv6 启用状态;
  2. 打开 NAT 全局 map(nat.GlobalMaps),调用ctmap.InitMapInfo初始化 map 信息——因为 flush 需要同步清理与 CT 条目关联的 NAT 映射;
  3. 通过stream.Multicast建立 GC 事件广播通道,用于在清理过程中联动 NAT map 的条目回收;
  4. ctmap.Maps(ipv4, ipv6)返回的每张 CT map 调用m.Flush(next4, next6)
  5. 每张 map 清理完毕后打印Flushed <N> entries from <path>

Map.Flush的实现位于 pkg/maps/ctmap/ctmap.go:

// Flush runs garbage collection for map m with the name mapType, deleting all // entries. The specified map must be already opened using bpf.OpenMap(). func (m *Map) Flush(next4, next6 func(GCEvent)) int { d, _ := m.doGC(GCFilter{ RemoveExpired: true, Time: MaxTime, }, next4, next6) return d }

它构造一个GCFilter{RemoveExpired: true, Time: MaxTime},即把"所有条目都视为已过期",从而让 GC 路径删除全部条目,同时联动删除关联的 NAT 条目。这样做既保证了 CT 与 NAT 的一致性,也复用了经过测试的成熟清理逻辑。

4.3 使用注意

  • flush需要 root 权限(命令内部调用common.RequireRootPrivilege,与list一致);
  • 该操作会清空该节点上的全部连接跟踪状态,所有在途连接都需要重新建立跟踪,可能影响现存长连接并产生短暂的数据面开销;在排查 NAT/CT 表异常或需要从零观测流表增长时使用,生产环境应谨慎评估影响窗口。

5. 源码级验证:list 的测试用例

仓库为ct list的输出逻辑提供了完整的单元测试:cilium-dbg/cmd/bpf_ct_list_test.go。

  • TestDumpCt4TestDumpCt6分别使用mockmaps.NewCtMockMap构造包含 IPv4(TCP,NextHeader=6)与 IPv6(UDP,NextHeader=17)条目的 mock CT map;
  • 测试将标准输出重定向到管道,强制 JSON 输出模式后调用dumpCt,再反序列化校验输出内容与预期条目一致;
  • 这验证了两点实现事实:结构化输出会把多张 map 的条目聚合成一个对象,且 JSON 输出中条目的 Key/Value 字段与 mock 数据完全对应。

此外,pkg/maps/ctmap 包还包含 GC 相关的gc/子包、per_cluster_ctmap.go(ClusterMesh 场景的按集群 CT map)与ctmap_privileged_test.go(需要特权环境的 map 级测试),感兴趣的读者可以沿这些路径继续深入。

6. 实战场景小结

场景推荐命令
查看节点当前所有连接跟踪条目cilium-dbg bpf ct list
用机器可读格式分析流表(配合 jq/yq)cilium-dbg bpf ct list -o json/-o yaml
判断条目何时过期、排查流表堆积cilium-dbg bpf ct list -d
多集群场景下查看指定集群的 CT 状态cilium-dbg bpf ct list cluster <identifier>
清理全部连接跟踪状态(谨慎)cilium-dbg bpf ct flush
快速查看命令用法cilium-dbg bpf ct list --help/cilium-dbg bpf ct flush --help

通过cilium-dbg bpf ct命令族,运维与开发者可以在不进入 Pod、不依赖监控面板的情况下,直接审视 eBPF 数据面的连接跟踪状态,并结合 Documentation/cmdref/cilium-dbg_bpf.md 中的其他 BPF map 查看命令(如bpf natbpf lb)交叉定位网络问题。

【免费下载链接】ciliumeBPF-based Networking, Security, and Observability项目地址: https://gitcode.com/GitHub_Trending/ci/cilium

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/12 18:03:38

Redis字符串类型深度解析与性能优化实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/12 18:03:21

Godot 4 首次启动全链路指南:安装、汉化与首个2D场景实操

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/12 18:01:28

CYW240128驱动移植实战:从ESP32到FPGA的联合调试全解析

先说结论&#xff1a;CYW240128 厂商提供的驱动例程&#xff0c;通常不会直接给你一份 ESP32 FPGA 的双端完整调试工程。别急着失望&#xff0c;这几乎是所有液晶模组厂的“通病”&#xff0c;因为对屏厂来说&#xff0c;他们交付的是一块模组、一颗控制器、一个初始化方案&am…

作者头像 李华
网站建设 2026/9/12 18:01:22

FPGA实现CNN图像分类的硬件加速与工程实践

简介&#xff1a;面向毕业设计、课程设计与硬件深度学习实践者&#xff0c;这份基于FPGA实现的CNN图像分类系统资料&#xff0c;完整展示了将卷积神经网络部署到可编程逻辑器件上的软硬件协同设计流程&#xff0c;可用于学习图像识别加速、Verilog/SystemVerilog开发与答辩汇报…

作者头像 李华
网站建设 2026/9/12 18:00:05

车载蓝牙开发实战:从HCI协议栈到AudioFlinger的全链路解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/12 17:58:42

虚拟DOM原理与前端性能优化实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华