Cilium egress 网关 BPF 策略管理:cilium-dbg bpf egress 命令族深度指南

发布时间:2026/9/12 17:32:40
Cilium egress 网关 BPF 策略管理:cilium-dbg bpf egress 命令族深度指南 Cilium egress 网关 BPF 策略管理cilium-dbg bpf egress 命令族深度指南【免费下载链接】ciliumeBPF-based Networking, Security, and Observability项目地址: https://gitcode.com/GitHub_Trending/ci/ciliumcilium-dbg bpf egress是 Cilium 提供的直接管理本地 BPF 映射BPF maps的命令族用于查看与排障 Egress Gateway出口网关路由规则在数据面中的落地状态。本指南以命令参考文档为骨架结合 bpf_egress.go、bpf_egress_list.go、egressmap/policy.go 等源码与 egress-gateway.rst 功能文档讲解该命令族的结构、输出字段语义、底层 BPF 映射实现以及如何在真实集群中用它验证和排查 Egress Gateway 策略。读完本文你将能够熟练使用cilium-dbg bpf egress list定位策略未生效、网关选择异常等常见问题。命令族概览从 cilium-dbg 到 egress 策略映射cilium-dbg是 Cilium 的调试客户端其bpf子命令族提供对本地 BPF 映射的直接访问Direct access to local BPF maps参见 cilium-dbg_bpf.md。bpf egress是其中的一个分支职责是管理出口路由规则Manage the egress routing rules。从 bpf_egress.go 的源码可以看到它的定义方式// BPFEgressCmd represents the bpf command var BPFEgressCmd cobra.Command{ Use: egress, Short: Manage the egress routing rules, } func init() { BPFCmd.AddCommand(BPFEgressCmd) }这是一个典型的 cobra 命令组节点它本身没有Run执行逻辑只负责挂载子命令。当前仓库中该命令族包含一个子命令子命令用途cilium-dbg bpf egress list列出 egress 策略条目List egress policy entries命令的完整层级为cilium-dbg→cilium-dbg bpf→cilium-dbg bpf egress→cilium-dbg bpf egress list。egress 命令自身的选项-h, --help help for egressegress命令组本身只暴露-h/--help。继承自父命令的全局选项无论执行哪个子命令都会继承以下来自cilium-dbg根命令的选项参考 cilium-dbg_bpf.md 中的 Options inherited from parent commands--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指定服务端 API 的 URI用于连接非默认的 Cilium Agent 端点--log-driver/--log-opt配置日志输出端点与选项例如将日志送往 syslog 或按formatjson输出。这些选项在排查分布式集群时很有用你可以用-H指向特定节点上的 Agent或在调试复杂环境时用-D打开调试日志。核心子命令cilium-dbg bpf egress list该子命令的完整签名Synopsis为cilium-dbg bpf egress list [flags]它列出 egress 策略条目即读取当前节点上已下发的 Egress Gateway 策略 BPF 映射内容。其选项为-h, --help help for list -o, --output string json| yaml| jsonpath{}-o/--output支持json、yaml以及jsonpath{}三种结构化输出格式便于脚本化和与jq等工具配合进行自动化校验。在 bpf_egress_list.go 中该选项通过command.AddOutputOption(bpfEgressListCmd)注册当检测到command.OutputOption()非空时会走结构化输出路径if command.OutputOption() { if err : command.PrintOutput(bpfEgressList); err ! nil { Fatalf(error getting output of map in %s: %s\n, command.OutputOptionString(), err) } return }没有指定-o时命令以表格形式输出见下文输出字段与示例解读。命令执行流程源码级在 bpf_egress_list.go 的Run函数中命令依次执行以下步骤权限检查调用common.RequireRootPrivilege(cilium bpf egress list)要求以 root 权限运行因为读取 BPF 映射需要足够权限。打开 IPv4 V2 策略映射调用egressmap.OpenPinnedPolicyMap4V2(log)打开 pin 在 BPF 文件系统中的cilium_egress_gw_policy_v4_v2映射。若打开失败且错误不是fs.ErrNotExist即映射确实存在但打不开则直接Fatalf报错。打开 IPv6 策略映射调用egressmap.OpenPinnedPolicyMap6(log)打开cilium_egress_gw_policy_v6处理方式同上。遍历映射对每个 key/value 对调用IterateWithCallback回调将内核态结构转换为用户态可读的egressPolicy结构体。异常兜底若 IPv4 与 IPv6 映射都不存在打印Cannot find egress gateway bpf maps并返回若映射存在但没有任何条目打印No entries found.。最终通过printEgressList用 tabwriter 对齐输出。输出字段结构命令将内核映射中的条目映射为用户态结构体type egressPolicy struct { SourceIP string DestCIDR string EgressIP string GatewayIP string Ifindex uint32 }表格输出的表头为Source IP Destination CIDR Egress IP Gateway IP Egress Ifindex各字段的含义如下Source IP匹配策略的源端PodIP。策略管理器会把每个匹配podSelector的 Pod IP 单独写入一条策略条目因此这里通常是对应 Pod 的地址而不是 CIDR。Destination CIDR策略destinationCIDRs中命中的目的网段含掩码长度。Egress IP用于对流量做 SNAT源地址转换的出口 IP即策略egressGateway.egressIP指定或由接口/默认路由推导出的地址。Gateway IP被选为网关节点的节点内部 IP即策略egressGateway.nodeSelector匹配到的节点地址。Egress Ifindex网关节点上用于出口流量的网络接口索引ifindex由数据面在执行 FIB 查找与重定向时使用。Gateway IP 的特殊值与告警语义值得注意的是Gateway IP 列并不是始终显示普通 IP。在 bpf_egress_list.go 中有一个mapGatewayIP翻译函数它把内核映射中的两个哨兵值翻译成人类可读的字符串// This function attempt to translate gatewayIP to special values if they exist // or return the IP as a string otherwise. func mapGatewayIP(ip netip.Addr) string { if ip egressgateway.GatewayNotFoundIPv4 { return Not Found } if ip egressgateway.ExcludedCIDRIPv4 { return Excluded CIDR } return ip.String() }这两个特殊值的定义位于 manager.go// GatewayNotFoundIPv4 is a special IP value used as gatewayIP in the BPF policy // map to indicate no gateway was found for the given policy GatewayNotFoundIPv4 netip.IPv4Unspecified() // 0.0.0.0 // ExcludedCIDRIPv4 is a special IP value used as gatewayIP in the BPF policy map // to indicate the entry is for an excluded CIDR and should skip egress gateway ExcludedCIDRIPv4 netip.MustParseAddr(0.0.0.1) // EgressIPNotFoundIPv4 is a special IP value used as egressIP in the BPF policy map // to indicate no egressIP was found for the given policy EgressIPNotFoundIPv4 netip.IPv4Unspecified()因此当你执行cilium-dbg bpf egress list时可能看到如下三种 Gateway IP 形态显示的 Gateway IP含义Not Found策略未匹配到任何网关节点nodeSelector 无命中。根据 egress-gateway.rst 的说明此时 Cilium 会丢弃匹配目的 CIDR 的流量Excluded CIDR该条目是策略excludedCIDRs排除网段对应的占位条目命中该条目的流量跳过Egress Gateway 逻辑按普通路径转发普通 IP正常选中网关节点时的节点内部 IP同样地Egress IP 为0.0.0.0EgressIPNotFoundIPv4表示当前节点尚未推导出可用的出口 IP例如指定的egressIP未配置在节点任何网卡上此时网关节点会以No Egress IP configured为原因丢弃匹配流量。底层支撑Egress 策略 BPF 映射结构cilium-dbg bpf egress list读取的是 pin 在 BPF 文件系统中的两张映射定义于 egressmap/policy.goconst ( PolicyMapName4V2 cilium_egress_gw_policy_v4_v2 PolicyMapName6 cilium_egress_gw_policy_v6 )两张映射的创建逻辑与数据结构类型ebpf.LPMTrie最长前缀匹配树这是它能够以源 IP 目的 CIDR作为复合键进行最长前缀匹配的关键容量由--egress-gateway-policy-map-max配置项控制默认值为1 1416384条见 egressmap/policy.go 中的DefaultPolicyConfig创建条件仅当EnableEgressGateway为 true 时才创建IPv4 映射依赖EnableIPv4IPv6 映射依赖EnableIPv6访问权限映射以unix.BPF_F_RDONLY_PROG创建BPF 程序只读并注册压力指标WithPressureMetric。映射 key/value 的内存布局与数据面 C 结构一一对应见 bpf_alignchecker.c 中的add_type对齐检查。IPv4 键与值// EgressPolicyKey4 is the key of an egress policy map. type EgressPolicyKey4 struct { PrefixLen uint32 align:lpm_key // SourceIP 全 32 位 DestCIDR 掩码位数 SourceIP types.IPv4 align:saddr DestCIDR types.IPv4 align:daddr } type EgressPolicyVal4V2 struct { EgressIP types.IPv4 align:egress_ip GatewayIP types.IPv4 align:gateway_ip Reserved [3]uint32 align:reserved EgressIfindex uint32 align:egress_ifindex Reserved2 uint32 align:reserved2 }注意 LPM 键的PrefixLen编码方式PolicyStaticPrefixBits4即 32表示源 IP 部分的位数加上目的 CIDR 的掩码位数destPrefix.Bits()后得到完整的PrefixLen。也就是说LPM 匹配针对的是源 IP 目的 CIDR这个复合前缀读取时通过PrefixLen - PolicyStaticPrefixBits4还原目的 CIDR 的掩码长度func NewEgressPolicyKey4(sourceIP netip.Addr, destPrefix netip.Prefix) EgressPolicyKey4 { key : EgressPolicyKey4{} ones : destPrefix.Bits() key.SourceIP.FromAddr(sourceIP) key.DestCIDR.FromAddr(destPrefix.Addr()) key.PrefixLen PolicyStaticPrefixBits4 uint32(ones) return key }IPv6 键与值type EgressPolicyKey6 struct { PrefixLen uint32 align:lpm_key SourceIP types.IPv6 align:saddr DestCIDR types.IPv6 align:daddr } type EgressPolicyVal6 struct { EgressIP types.IPv6 align:egress_ip GatewayIP types.IPv4 align:gateway_ip // 注意IPv6 值中网关 IP 仍为 IPv4 Reserved [3]uint32 align:reserved EgressIfindex uint32 align:egress_ifindex Reserved2 uint32 align:reserved2 }一个值得注意的实现细节IPv6 策略值中的GatewayIP仍然是types.IPv4。这从 egressmap/policy.go 的结构体定义可以直接观察到也解释了为何cilium-dbg bpf egress list的 IPv6 解析回调中同样使用mapGatewayIP(val.GetGatewayAddr())做特殊值翻译。数据面如何消费这些条目内核数据面在 bpf/lib/egress_gateway.h 中实现策略查找与执行lookup_ip4_egress_gw_policy(saddr, daddr)以源 IP目的 IP为键查找 LPM 映射egress_gw_request_needs_redirect返回包是否需要重定向到网关节点。当gateway_ip为EGRESS_GATEWAY_NO_GATEWAY时返回DROP_NO_EGRESS_GATEWAY丢弃为EGRESS_GATEWAY_EXCLUDED_CIDR时返回CTX_ACT_OK跳过否则返回CTX_ACT_REDIRECT并携带网关 IPegress_gw_snat_needed判断是否需要对离开集群的流量执行 SNAT。命中策略时取egress_ifindex与egress_ip作为 SNAT 参数egress_gw_snat_needed_hook还会先通过lookup_ip4_remote_endpoint检查目的地址是否属于集群内部实体Pod 或节点若是则跳过 SNAT——这正对应文档中内部集群 IP 会被排除在 egress gateway SNAT 逻辑之外的描述。由此可见你在cilium-dbg bpf egress list中看到的每一行就是数据面对应一次map_lookup_elem的完整命中决策表。这些条目从何而来策略管理与映射填充Egress 策略映射的内容由 pkg/egressgateway 包中的管理器Manager负责维护。其工作原理可以概括为API 对象用户通过CiliumEgressGatewayPolicyCEGPCRD 声明策略这是集群作用域资源.metadata.namespace不应被指定。内部表示policy.go 中的PolicyConfig保存了从 CRD 解析出的endpointSelectors、nodeSelectors、dstCIDRs、excludedCIDRs以及网关配置policyGwConfigs。其中policyGatewayConfig描述哪个节点充当网关——支持按标签nodeSelector或显式egressIP/interface指定。端到端订阅Manager 通过 hive/resource 机制订阅CiliumNode、CiliumEndpoint与策略资源维护nodes、nodesAddresses2Labels、policyConfigs与epDataStore等缓存见 manager.go 的Manager结构体。网关选择当多个节点匹配同一组标签时按节点名称的字典序选择第一个若nodeSelector无匹配则 Gateway IP 被置为GatewayNotFoundIPv4数据面将丢弃匹配流量。写入映射最终通过 egressmap/policy.go 的Update方法把源 IP目的 CIDR→Egress IPGateway IPEgress Ifindex写入cilium_egress_gw_policy_v4_v2/cilium_egress_gw_policy_v6策略删除时调用Delete。excludedCIDRs对应的占位条目则写入GatewayIP ExcludedCIDRIPv4见 manager.go 中ExcludedCIDRIPv4的赋值点。同步节奏--egress-gateway-reconciliation-trigger-interval默认 1 秒见 manager.go控制状态调和触发间隔。因此cilium-dbg bpf egress list实际上是以只读方式快照管理器写入数据面的策略状态它是用户侧观察这个同步结果最直接的窗口。实战在集群中验证与排障 Egress Gateway前置条件与启用在使用cilium-dbg bpf egress list之前需要确保 Egress Gateway 功能已启用。依据 egress-gateway.rst该功能要求同时开启BPF masquerading与kube-proxy replacementHelm 方式--set egressGateway.enabledtrue --set bpf.masqueradetrue --set kubeProxyReplacementtrueConfigMap 方式enable-bpf-masquerade: true enable-egress-gateway: true kube-proxy-replacement: true修改后需要滚动重启 Agent 与 Operator$ kubectl rollout restart ds cilium -n kube-system $ kubectl rollout restart deploy cilium-operator -n kube-system同时注意功能兼容性约束文档明确列出必须使用crd身份分配模式identityAllocationMode: crd与kvstore模式不兼容与 Cluster Mesh 不兼容策略选中的网关必须与源 Pod 位于同一集群与 CiliumEndpointSlice 功能不兼容。编写并下发示例策略仓库自带的示例位于 examples/kubernetes-egress-gateway/egress-gateway-policy.yamlapiVersion: cilium.io/v2 kind: CiliumEgressGatewayPolicy metadata: name: egress-sample spec: selectors: - podSelector: matchLabels: org: empire class: mediabot io.kubernetes.pod.namespace: default destinationCIDRs: - 192.168.60.13/32 egressGateway: nodeSelector: matchLabels: egress-node: true egressIP: 192.168.60.100该策略将default命名空间中带org: empire、class: mediabot标签的 Pod 发往192.168.60.13/32的流量经带egress-node: true标签的网关节点以192.168.60.100作为出口 IP 进行 SNAT。关于网关节点的配置文档给出了三种方式三者不可同时混用指定接口egressGateway.interface: ethX取该接口上第一个 IPv4 与 IPv6 地址作为出口 IP显式指定出口 IPegressGateway.egressIP: a.b.c.d该 IP 必须已配置在节点的某个网络设备上出口接口由数据面对每个包做路由查找动态确定两者都省略选取带默认路由的网络接口取其上第一个 IPv4/IPv6 地址作为出口 IP。注意egressIP与interface同时出现在egressGateway中时该策略会被 Cilium 忽略。若需让同一策略选择多个网关节点可以使用egressGateways列表字段条目配置与egressGateway完全相同。多网关模式下源端点在生命周期内会通过其 CiliumEndpoint 的 UID 哈希被固定分配到一个网关见 policy.go 中基于hash/fnv的分配逻辑但变更网关会中断既有连接。用 cilium-dbg bpf egress list 验证功能文档 egress-gateway.rst 给出的标准验证方式就是本命令族$ kubectl -n kube-system exec ds/cilium -- cilium-dbg bpf egress list Defaulted container cilium-agent out of: cilium-agent, config (init), mount-cgroup (init), apply-sysctl-overwrites (init), mount-bpf-fs (init), wait-for-node-init (init), clean-cilium-state (init) Source IP Destination CIDR Egress IP Gateway IP 192.168.2.23 192.168.60.13/32 0.0.0.0 192.168.60.12对上例的解读来自文档的明确说明Source IP192.168.2.23匹配策略podSelector的某个 Pod 的 IP每个匹配 Pod 一条记录Destination CIDR192.168.60.13/32策略destinationCIDRs命中的目的地址Gateway IP192.168.60.12匹配策略nodeSelector的网关节点内部 IPEgress IP0.0.0.0在除网关节点外的所有 Agent 上Egress IP 列显示为0.0.0.0即EgressIPNotFoundIPv4哨兵值只有运行在网关节点上的 Agent 才会显示实际用于 SNAT 的出口 IP如策略中指定的egressIP。输出格式选项的实战用法当条目较多或需要自动化断言时使用结构化输出。例如以 JSON 形式获取全部条目$ kubectl -n kube-system exec ds/cilium -- cilium-dbg bpf egress list -o json返回的 JSON 数组元素包含SourceIP、DestCIDR、EgressIP、GatewayIP、Ifindex五个字段与egressPolicy结构体对应。也可用-o yaml或-o jsonpath{...}做精确字段提取便于接入告警或巡检脚本。表格模式下若映射为空会输出No entries found.若两张映射都不存在功能未启用或 Agent 未创建映射则输出Cannot find egress gateway bpf maps。常见问题排查清单结合上文分析遇到策略未按预期生效时可按以下顺序排查确认功能已启用检查 Agent 是否设置了enable-egress-gateway、enable-bpf-masquerade与kube-proxy-replacement并确认身份分配模式为crd确认映射存在执行cilium-dbg bpf egress list若提示Cannot find egress gateway bpf maps说明当前 Agent 未创建策略映射IPv4/IPv6 映射仅在对应地址族启用时创建对照期望检查条目若列表中没有与 Pod/目的 CIDR 对应的行说明策略选择器未命中——检查 Pod 标签与nodeSelector是否与策略匹配文档建议核对 Pod 与出口节点的标签识别特殊值Gateway IP 为Not FoundnodeSelector无匹配节点流量将被数据面以DROP_NO_EGRESS_GATEWAY丢弃Gateway IP 为Excluded CIDR该条目对应excludedCIDRs命中时跳过 Egress Gateway 逻辑Egress IP 为0.0.0.0当前节点未推导出出口 IP如egressIP未绑定到任何网卡网关节点将按No Egress IP configured丢弃流量注意单节点视角配置会传播到所有 Agent因此任意 Agent 上都能看到策略条目但 Egress IP 列只有网关节点上才显示真实出口 IP网络配置变更后重放策略Cilium 不会自动响应网关节点网卡/IP 的变化如增删 IP需要重新 apply 一次CiliumEgressGatewayPolicy强制重新选择接口与出口 IP确认设备覆盖无论以哪种方式配置出口 IP都需确保--devicesAgent 选项包含了所选网络接口。总结cilium-dbg bpf egress命令族虽小却是连接用户意图CEGP 策略与数据面事实BPF 策略映射的关键调试桥梁。通过cilium-dbg bpf egress list及其-o结构化输出你可以快速验证策略下发、定位网关选择失败、识别排除网段占位条目并借助Not Found/Excluded CIDR两个特殊值的语义准确判断数据面行为。结合 egressmap/policy.go 的映射定义、egressgateway/manager.go 的填充逻辑与 egress_gateway.h 的数据面消费路径本命令族即可成为你日常运维 Cilium Egress Gateway 时最高效的第一现场。【免费下载链接】ciliumeBPF-based Networking, Security, and Observability项目地址: https://gitcode.com/GitHub_Trending/ci/cilium创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考