排查实战: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有状态协议需要精细的流转状态机与非 TCPAny涵盖 UDP、ICMP 等。对应关系如下mapType说明mapTypeIPv4TCPGlobal全局 IPv4 TCP CT mapmapTypeIPv6TCPGlobal全局 IPv6 TCP CT mapmapTypeIPv4AnyGlobal全局 IPv4 非 TCP CT mapmapTypeIPv6AnyGlobal全局 IPv6 非 TCP CT map在 pkg/maps/ctmap/ctmap.go 中定义了四个全局 map 的实际名称tcp4global、tcp6global、any4global、any6global。cilium-dbg bpf ct系列命令正是这些 map 的用户态操作入口。2. 命令族总览cilium-dbg bpf ct2.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 nat、bpf lb等命令平级遵循 Cilium 统一的 Direct access to local BPF maps 设计。2.2 全局父命令继承选项ct、ct list、ct flush均继承自cilium-dbg根命令的通用选项--config string 配置文件默认 $HOME/.cilium.yaml -D, --debug 启用调试消息 -H, --host string 服务端 API 的 URI --log-driver strings 日志端点示例syslog --log-opt map 日志驱动选项示例formatjson其中-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 list3.1 语法与输出格式选项cilium-dbg bpf ct list [cluster identifier] [flags]该命令列出节点上的连接跟踪条目是排查连接建立失败、NAT 异常、流表堆积等问题的第一入口。参数与选项如下参数/选项说明[cluster identifier]可选指定要查看的集群 IDClusterMesh 多集群场景省略时默认查看global本节点全局 map-o, --output string输出格式支持json、yaml、jsonpath{}-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 两种视图parseArgscilium-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。getMapscilium-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 }即最多遍历tcp4global、any4global、tcp6global、any6global四张 map。每张 map 通过ctmap.OpenCTMappkg/maps/ctmap/ctmap.go打开若某张 map 不存在例如未启用 IPv6会打印Unable to open path: err. Skipping.并跳过而不会中断整个命令。3.3 条目内容五元组 Key 与 CT Entry Valuelist输出的每条记录由一个 Key 和一个 Value 组成。测试用例 cilium-dbg/cmd/bpf_ct_list_test.go 给出了直观的样例Key五元组目的地址DestAddr、源地址SourceAddr、目的端口DestPort、源端口SourcePort、下一层协议号NextHeader6 为 TCP、17 为 UDP以及标志位FlagsValueCtEntry包含Packets/Bytes该方向累计的包数与字节数、Lifetime剩余存活时间、Flags、RevNAT反向 NAT 端口、TxFlagsSeen/RxFlagsSeen观测到的 TCP 收发标志位、SourceSecurityID源安全身份对应 Cilium 的 identity 机制以及LastTxReport/LastRxReport最近一次收发的时间戳用于计算 time-diff。这些字段定义在 pkg/maps/ctmap 与 pkg/tuple 中是解读流状态的关键依据。3.4 文本输出与结构化输出JSON/YAML/jsonpathdumpCtcilium-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 的输出切碎方便jq或yq进一步加工。常用示例# 文本方式查看本节点全部 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 -dls是list的别名两者等价。3.5 深入解析-d/--time-diff时钟源ClockSource换算CT 条目中记录的Lifetime与时间戳不是墙上时钟而是 BPF 侧单调时钟的tick计数直接打印对用户不友好。因此-d选项需要先确定时钟源模式再换算为秒getClockSourcecilium-dbg/cmd/bpf_ct_list.go的优先级如下未指定--time-diff-clocksource-mode时调用timestamp.GetClockSourceFromAgent(client.Daemon)pkg/maps/timestamp/timestamp.go向 Cilium agent 查询真实时钟源查询失败则回退到GetClockSourceFromRuntimeConfig()读取本地运行配置指定ktime模式时直接构造ClockSource{Mode: ktime}tick 与纳秒一一对应指定jiffies模式时必须提供非零的--time-diff-clocksource-hz即内核 HZ默认 250否则报错invalid HZ value换算时用 tick 除以 Hz 得到秒数见 pkg/maps/timestamp/timestamp.go 中 ktime/jiffies 两种换算分支其他模式字符串直接报错invalid clocksource。因此若 agent 不可达但你又需要-d输出可以手动指定模式与频率例如在 HZ100 的内核上cilium-dbg bpf ct list -d --time-diff-clocksource-mode jiffies --time-diff-clocksource-hz 1004. 清空连接跟踪条目cilium-dbg bpf ct flush4.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 的流程如下通过getIpEnableStatuses()判断 IPv4/IPv6 启用状态打开 NAT 全局 mapnat.GlobalMaps调用ctmap.InitMapInfo初始化 map 信息——因为 flush 需要同步清理与 CT 条目关联的 NAT 映射通过stream.Multicast建立 GC 事件广播通道用于在清理过程中联动 NAT map 的条目回收对ctmap.Maps(ipv4, ipv6)返回的每张 CT map 调用m.Flush(next4, next6)每张 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。TestDumpCt4与TestDumpCt6分别使用mockmaps.NewCtMockMap构造包含 IPv4TCPNextHeader6与 IPv6UDPNextHeader17条目的 mock CT map测试将标准输出重定向到管道强制 JSON 输出模式后调用dumpCt再反序列化校验输出内容与预期条目一致这验证了两点实现事实结构化输出会把多张 map 的条目聚合成一个对象且 JSON 输出中条目的 Key/Value 字段与 mock 数据完全对应。此外pkg/maps/ctmap 包还包含 GC 相关的gc/子包、per_cluster_ctmap.goClusterMesh 场景的按集群 CT map与ctmap_privileged_test.go需要特权环境的 map 级测试感兴趣的读者可以沿这些路径继续深入。6. 实战场景小结场景推荐命令查看节点当前所有连接跟踪条目cilium-dbg bpf ct list用机器可读格式分析流表配合 jq/yqcilium-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 nat、bpf lb交叉定位网络问题。【免费下载链接】ciliumeBPF-based Networking, Security, and Observability项目地址: https://gitcode.com/GitHub_Trending/ci/cilium创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考