Cilium 的 `cilium-dbg bpf nat retries list` 命令详解:解读 SNAT 端口分配重试直方图 📅 发布时间:2026/9/12 12:05:32 👁 浏览次数: Cilium 的cilium-dbg bpf nat retries list命令详解解读 SNAT 端口分配重试直方图【免费下载链接】ciliumeBPF-based Networking, Security, and Observability项目地址: https://gitcode.com/GitHub_Trending/ci/cilium导读cilium-dbg bpf nat retries list是 Cilium 提供的调试命令用于展示数据面 SNAT源地址转换端口分配重试次数的直方图帮助开发者诊断端口冲突、NAT 表耗尽等数据面健康问题。本文以该命令为核心结合 cilium-dbg/cmd/bpf_nat_retries_list.go、pkg/maps/nat/nat.go 与 bpf/lib/nat.h 等仓库源码完整说明命令的语法、输出格式、底层 BPF map 结构及直方图的生成原理使读者能够独立完成诊断、解读与后续处置。命令定位NAT retries histogram 是什么Cilium 的数据面在执行 SNAT 时需要为出站连接分配可用的源端口。当选择的端口与已有 NAT 映射冲突时内核 BPF 程序会重试并挑选下一个端口这一过程可能反复多次。NAT retries histogramNAT 重试直方图正是对这一过程的量化记录它以重试次数为桶bucket统计每种重试次数下成功或失败分配的连接数量。重试次数越多说明 NAT 端口空间越拥挤端口冲突越频繁若大量连接都落在高重试次数区间甚至触达最大重试上限仍失败则意味着端口空间可能耗尽需要扩容 NAT 端口范围或排查端口占用问题。该命令是cilium-dbg bpf nat命令族的一员其兄弟命令包括cilium-dbg bpf nat retries——retries 父命令仅作为命令分组使用cilium-dbg bpf nat retries list——展示直方图本文主题cilium-dbg bpf nat retries flush——将直方图清零便于观测一段新时间窗口内的统计数据。命令语法与完整参数cilium-dbg bpf nat retries list [flags]list 子命令选项选项说明-h, --help显示 list 子命令的帮助信息-o, --output string指定输出格式可选json、yaml或jsonpath{}该子命令不接受位置参数若传入多余参数会打印Invalid argument并中止执行见 bpf_nat_retries_list.go。从父命令继承的全局选项--config string Config file (default is $HOME/.cilium.yaml) -D, --debug Enable debug messages -H, --host string URI to server-side API --log-driver strings Logging endpoints to use (example: syslog) --log-opt map Log driver options (example: formatjson)--config指定配置文件路径默认读取$HOME/.cilium.yaml-D, --debug开启调试信息输出-H, --host指定连接 cilium-agent 服务端 API 的 URI--log-driver与--log-opt配置日志输出端点及其选项。注意该命令需要 root 权限执行源码中通过common.RequireRootPrivilege(cilium bpf nat retries list)强制校验见 bpf_nat_retries_list.go。输出解读直方图每个数字的含义默认文本输出不带-o参数时命令逐行打印直方图格式为重试次数TAB连接数0: 18200 1: 1024 2: 312 3: 87 ... 31: 3 32: 1左侧为桶的键即重试次数取值范围为0 ~ SnatCollisionRetries即0 ~ 32共 33 个桶右侧为该重试次数对应的连接分配数量桶键为32即SnatCollisionRetries时表示达到最大重试次数仍未能分配端口的连接数对应 BPF 侧的DROP_NAT_NO_MAPPING丢弃结果。输出逻辑见 bpf_nat_retries_list.go遍历 BPF map 中所有条目按键重试次数填充一个长度为SnatCollisionRetries1的直方图数组最后以%d:\t%d\n逐行打印。结构化输出json / yaml / jsonpath使用-o json时输出为条目列表每个条目包含键与值两个字段[ { Key: 0, Value: 18200 }, { Key: 32, Value: 1 } ]对应的 Go 结构体定义为RetriesMapRecordKey *RetriesKey、Value *RetriesValue其中RetriesKey与RetriesValue均为单个uint32字段见 pkg/maps/nat/nat.go。-o yaml输出 YAML 格式-o jsonpath{}则按给定的 JSONPath 表达式筛选字段。源码级原理直方图背后的 BPF mapMap 定义两个 per-CPU 数组直方图数据存放在两个 BPF map 中分别对应 IPv4 与 IPv6见 pkg/maps/nat/nat.go地址族BPF map 名称说明IPv4cilium_snat_v4_alloc_retriesIPv4 NAT 端口分配重试直方图IPv6cilium_snat_v6_alloc_retriesIPv6 NAT 端口分配重试直方图这两个 map 的类型均为PerCPUArray即每个 CPU 一个独立数组从而避免多核并发更新时的锁竞争max_entries为SnatCollisionRetries 1 33恰好覆盖 0~32 共 33 个桶见 newRetriesMap。BPF 侧对应的 map 声明位于 bpf/lib/nat.h 与 bpf/lib/nat.h。命令如何读取并汇总list命令的处理流程如下见 bpf_nat_retries_list.go 与 pkg/maps/nat/nat.go通过getIpEnableStatuses()探测当前节点 IPv4/IPv6 的启用状态——优先查询 cilium-agent 的 healthz/config API失败时回退读取运行时配置文件agent-runtime-config.json最后回退到默认值见 cilium-dbg/cmd/helpers.go调用nat.RetriesMaps(ipv4, ipv6)构造对应地址族的 retries map 对象未启用的地址族返回 nil会跳过打开 map通过DumpPerCPUWithCallback遍历全部条目并把每个条目在各 CPU 上的计数值求和——因为 map 是 per-CPU 的直接读值只能看到当前 CPU 的计数见 bpf_nat_retries_list.go。BPF 侧如何写入直方图端口分配逻辑位于 bpf/lib/nat.h。BPF 程序使用#pragma unroll展开循环最多重试SNAT_COLLISION_RETRIES定义于 bpf/node_config.h值为 32次每次尝试通过__snat_create创建反向 SNATRevSNAT条目若成功则跳出循环若端口冲突则按__snat_clamp_port_range规则取下一个端口首次失败时从随机端口开始后续port 1顺序探测无论最终成功还是失败都会以实际消耗的重试次数为键对直方图桶执行自增*retries_hist——因此直方图既记录了成功分配的连接也记录了最终失败达到 32 次上限的尝试当重试次数超过SNAT_SIGNAL_THRES即SNAT_COLLISION_RETRIES / 2 16见 bpf/lib/nat.h时通过send_signal_nat_fill_up向 agent 发送 NAT 表将满的信号触发 GC 清理过期连接占用的端口。实战诊断流程与命令组合查看当前直方图# 以默认文本格式查看 IPv4/IPv6 的 NAT 重试直方图 cilium-dbg bpf nat retries list # 以 JSON 格式输出便于脚本解析 cilium-dbg bpf nat retries list -o json # 以 YAML 格式输出 cilium-dbg bpf nat retries list -o yaml # 使用 jsonpath 只提取重试次数为 32 的条目 cilium-dbg bpf nat retries list -o jsonpath{range .items[?(.Key32)]}{.Key}:{.Value}{end}实际用法请以cilium-dbg bpf nat retries list --help输出为准。结合 flush 观测一段时间窗口由于直方图是累计计数器若要评估最近一段时间的端口分配压力可以先清零再观察# 1. 将直方图清零 cilium-dbg bpf nat retries flush # 2. 等待业务流量运行一段时间后再次查看 cilium-dbg bpf nat retries listflush的实现位于 cilium-dbg/cmd/bpf_nat_retries_flush.go它对 IPv4/IPv6 两个 map 逐一执行ClearAll()清空全部计数。结果判读与处置建议若大量计数集中在0附近说明端口分配几乎不冲突NAT 端口空间健康若高重试桶如 10~31计数显著增长说明端口空间趋于紧张可考虑调整 SNAT 端口范围或排查是否存在大量短连接导致的端口占用若桶32最大重试次数的计数持续增长则说明存在DROP_NAT_NO_MAPPING丢弃端口空间可能已耗尽同时 agent 会在重试超过 16 次后收到nat_fill_up信号并触发 GC此时应结合cilium-dbg bpf nat list查看实际映射占用情况。单元测试对直方图语义的验证仓库的 BPF 测试 bpf/tests/bpf_nat_tests.c 直接验证了直方图与端口分配算法的行为测试维护retries_before、retries_10percent等 5 个长度为SNAT_COLLISION_RETRIES 1的快照数组在测试的不同进度点10%、50%、75%、100%通过map_lookup_elem(cilium_snat_v4_alloc_retries, ...)读取直方图并求差值见 bpf_nat_tests.c测试断言达到最大重试次数SNAT_COLLISION_RETRIES的失败连接占比在 50% 进度时小于 25、在 75% 时小于 7%、在 100% 时小于 16%见 bpf_nat_tests.c测试还断言重试次数少的桶计数不低于重试次数多的桶这一单调性特征见 bpf_nat_tests.c佐证了直方图桶键即重试次数、值即连接数的语义。相关资源命令参考cilium-dbg bpf nat retries list、cilium-dbg bpf nat retries、cilium-dbg bpf nat retries flush命令实现cilium-dbg/cmd/bpf_nat_retries_list.go、cilium-dbg/cmd/bpf_nat_retries_flush.goBPF map 定义与常量pkg/maps/nat/nat.go、bpf/node_config.h数据面端口分配逻辑bpf/lib/nat.h端口分配算法测试bpf/tests/bpf_nat_tests.c【免费下载链接】ciliumeBPF-based Networking, Security, and Observability项目地址: https://gitcode.com/GitHub_Trending/ci/cilium创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考