土法炼钢 · 系统与基础设施

【Cilium / eBPF】关键 BPF Map:policy、service、CT 的职责与失败表象

文章导航

分类入口
kubernetesnetwork
标签入口
#cilium#ebpf#bpf-maps#policymap#conntrack#service-lb#ipcache#v1.20.0

目录

第 3 篇 说明程序挂在哪;本篇钉 Map 状态轴。Cilium 数据面的权威运行态很大一块住在 BPF map 里:策略允许谁、Service 指到哪、连接是否已跟踪。内核里 map 类型、哈希冲突与内存布局见 ebpf/;这里只写 Cilium 用哪些表、默认上限、满了或陈旧时人看到什么

本篇在系列中的位置

篇目 核心内容
第 3 篇 · BPF 挂载 hook 与加载
第 4 篇 · 关键 BPF Map policy / service / CT 等职责与失败表象
第 5 篇 · 东西向包路径 包在路径上何时查这些表
系列目录 全部篇目

版本锚定:Cilium v1.20.0docs.cilium.io/en/v1.20/network/ebpf/maps/;源码 pkg/maps/*bpf/ @ v1.20.0。容量数字引用官方默认表;生产应用 --bpf-*-max / dynamic sizing 后以实际配置为准。


一、先建立「表 → 职责」卡片

官方 eBPF Maps 文档给出默认上限与规模含义(节选,口径为文档默认值):

Map(文档名) Scope 默认上限(文档) 规模含义(文档)
Connection Tracking node 512k TCP / 256k UDP 并发连接与预期 UDP 应答规模
NAT node 512k NAT 条目上限
Endpoints node 64k 本地 endpoint + host IP
IP cache node 512k 跨集群 endpoint 解析规模叙述
Service Load Balancer node 64k LB 服务条目;与后端数/端口数耦合
Service Backends node 64k 累计唯一后端
Policy endpoint 16k 每 endpoint 允许的 identity+port+protocol 对
Auth / Neighbor / Frag / … node 见文档 认证关系、邻居、分片等

agent 可用 --bpf-policy-map-max--bpf-ct-global-tcp-max--bpf-ct-global-any-max--bpf-nat-global-max--bpf-lb-map-max 等覆盖;亦可用 --bpf-map-dynamic-size-ratio 按内存比例动态设定若干大表(文档列出受影响的 CT/NAT/neigh/snat/reverse_sk 等)。文档硬约束:若显式设定 CT 上限,NAT 表不得超过 CT(TCP+UDP)合计的 2/3——否则 NAT 与 CT 生命周期会错配。

pkg/maps/ 下可见与文档同构的包名:policymapctmapnatipcachelxcmapauthmapfragmap 等。LB 相关实现分布在 datapath/bpf 的 lb 逻辑与对应 map 封装中;文档称服务 LB map 为 cilium_lb{4,6}_services_v2


二、Policy map:身份策略的执行表

职责

每 endpoint 一张(前缀)policy map,键语义是 identity + 端口 + 协议(及方向相关字段),值编码允许/拒绝等。源码 pkg/maps/policymap

// MapName is the prefix for endpoint-specific policy maps...
// "_v3_": semantic change due to policy identity aggregation.
MapName = "cilium_policy_v3_"

摘录来自 v1.20.0;注释要求:BPF 格式或既有布局的语义变化时必须改名,以便与旧 map/程序干净分离。v1.20 的 v3 对应 policy identity aggregation 语义,而非单纯字段重排。

另有 cilium_call_policy / cilium_egresscall_policy 一类 prog array,用于 tail call 进入 endpoint 策略程序——它们是「跳转表」,与「允许关系表」分工不同。

失败表象

现象方向 优先怀疑
特定 Pod 在策略变复杂后开始拒绝合法对端 该 endpoint 的 policy map 16k 默认上限被打满(文档:Max 16k allowed identity+port+protocol pairs)
升级 1.19↔︎1.20 后已有连接异常 map 世代/语义切换窗口;上游用改名前缀降低缺身份丢包
标签变更后短暂 deny/allow 条目尚未收敛(见 第 2 篇),不一定是满表

压力指标方向:agent 提供 policy map pressure 相关阈值(cmdref 中有 pressure threshold 类选项)。无集群时只记「满表会让策略无法继续写入」,不编造具体 metrics 名输出。


三、Service / Backend map:kube-proxy 替代的状态面

职责

文档:Service LB map(cilium_lb{4,6}_services_v2)保存 ClusterIP / NodePort 等负载均衡条目;默认经 --bpf-lb-map-max 设为 64k。满表时 Cilium 可能无法 reconcile Service 更新,影响连通到 Service IP 或创建新 Service 的能力——这是官方写明的失败模式,不是推测。

Sizing 启发式(文档公式):

[ (#) (#) ]

[ (#) () () ]

文档提醒:若存在「选中海量后端」的离群 Service,均值启发式会低估。Backend map、source range、session affinity 另有独立上限(各默认 64k 叙事)。

失败表象

现象方向 优先怀疑
部分 VIP 不通、新建 Service 不生效,节点 CPU 未必高 LB map 满或 reconcile 失败
扩容后端后流量仍打到旧 Pod backend/服务条目未更新或缓存路径异常
调整 --bpf-lb-map-max 后重启 文档警告:map 已创建后再改大小并重启会导致重填期间连接中断

第 6 篇 的衔接:本篇只钉「状态在哪、满了怎样」;具体 ClusterIP/NodePort 走哪条 BPF 路径在第 6 篇展开。相对 iptables kube-proxy:规则风暴换成 map 容量与 reconcile 风暴——失败模式从「iptables-restore 卡顿」变为「插入失败 / 条目陈旧」。


四、CT 与 NAT:连接状态与地址转换

职责

Cilium 使用自有 BPF CT 表,而不是把关键路径建立在 netfilter conntrack 上(与「旁路 netfilter」叙事一致;回退路径除外)。文档对比:kube-proxy 按 CPU 核数估算内核 CT 上限;Cilium CT 按内存与 dynamic ratio 估算,并给出示例对照表(同 ratio 0.0025 下不同 vCPU/内存的条目数)。这些数字是文档示例,不是本站实测。

NAT map 服务 SNAT/DNAT 类条目;与 CT 的 2/3 约束防止 NAT 条目无法被 CT 生命周期覆盖。

失败表象

现象方向 优先怀疑
突发短连接后新建失败,旧长连接仍在 CT 表压力 / 驱逐
出站访问外部或 NodePort 回程异常 NAT 与 CT 不匹配、NAT 满
仅 UDP / 仅 TCP 出问题 ct_any vs ct_tcp 不同上限与超时配置

超时类选项(cmdref)如 service TCP/ANY 超时会影响「Service 条目在 CT 中的寿命」——表象可能是偶发后端切换或连接复用异常;需与应用超时区分。本篇不下「应设多少秒」的处方。


五、ipcache、Endpoints 与其它相关表

Map 职责直觉 失败表象方向
IP cache IP → Identity(及节点信息)解析 身份窗口、跨节点策略误判、陈旧身份
Endpoints 本地 endpoint / host IP 本地投递找不到 endpoint
Neighbor NodePort 等路径邻居缓存 邻居相关转发异常
Auth 认证关系(若启用) 认证策略失败
Frag 分片重组跟踪 分片流量异常

ipcache 是 Identity 轴与包路径轴的桥梁:策略键是身份,包上先看到的是 IP。缓存滞后会把第 2 篇的变更窗口放大到「IP 已变身份未变」或反向。ClusterMesh 下 ipcache 压力与集群规模耦合——第 11 篇再收。

Endpoints map 的节点局部性常被忽略:它回答「这个节点上谁可以收这个包」,不回答「集群里谁拥有这个身份」。跨节点不通时两边都要查——源侧策略与 ipcache、目的侧 endpoints 与目的侧 policy——不能只在出问题的客户端节点上翻一张表。

分片表默认上限相对较小(文档 IPv4/IPv6 fragmentation 各 8k 量级叙事)。若业务大量依赖分片(少见但在某些 UDP/隧道场景出现),满表表象会像「随机丢大包」,却与 policy deny 无关。把 MTU/分片问题误判成策略,是 Map 轴常见归因错误。

动态 sizing 文档还给出与 kube-proxy CT 条目的对照表(按 vCPU/内存示例)。引用时必须保持口径:那是官方在给定 ratio 下的计算示例,用于理解数量级,不是本站在某一云厂商规格上的实测,也不是「Cilium CT 一定更大/更小」的排名结论。


六、排障顺序:先问哪张表

Symptom → which map axis?
  policy deny / label change     → policy map + ipcache (+ identity)
  Service VIP / NodePort broken  → LB services + backends (+ CT)
  burst new flows fail           → CT (+ NAT)
  local delivery miss            → endpoints map
  upgrade weirdness              → map generation (e.g. policy_v3_) + prog reload

口诀与第 1 篇一致:先点名表,再改 YAML。改 NetworkPolicy 解决不了 LB map 满;加大 CT 也解决不了 identity 未解析。

内核实现(hash/LRU/per-CPU 阵列等)如何影响延迟与内存,见 ebpf/ 的 Map 篇章;本系列只要求能把症状映射到上表。

同一症状也可能跨表:例如「偶发连不上 Service」既可能是 CT 驱逐后的重新选后端,也可能是 backend map 与 EndpointSlice 短暂不一致,还可能是目的侧 policy 在身份窗口内拒绝。正确顺序是:先用第 5 篇停顿点缩小到一两类表,再用本篇失败表象做假说,而不是同时改三个 --bpf-*-max

容量规划上再钉一句工程约束:LB map 文档写明首次创建后改大小并重启会中断连接重填。因此「先用默认 64k 上线、不够再改」会把容量事故变成变更事故。更稳的做法是按启发式估算后端×端口积,对离群 Service 单独核算,把上限写进安装参数——这是 Map 轴上的发布纪律,不是性能玄学。

相对 k8s-network/13 产品文里的 map 概览,本篇多出来的是满表与世代切换的失败合同:产品文告诉你有哪些表,本篇告诉你表拒绝服务时人会看见什么。与 ebpf/ 的分工同样清楚:那边解释 map 在内核里如何分配与查找;这边解释 Cilium 把哪些控制面对象编译进哪些表、以及表满时的业务症状。


七、学术谱系、争论与开放问题

谱系:可编程数据面把「规则列表」换成「可更新的内核映射」——与经典 BPF map 作为共享状态的范式一致。Cilium 的贡献在于把 CNI 策略 / Service / CT 做成一套命名稳定、可配置上限、可动态 sizing 的映射集合,并把失败写成运维可理解的「满表 / reconcile 失败」。

相对经典 netfilter 规则表:iptables 的失败常常是线性匹配变慢全量刷新卡顿;BPF map 的失败常常是插入返回满世代切换窗口。两者都是「状态更新跟不上控制面意图」,但信号完全不同。若团队故障手册仍写「检查 iptables 规则条数」,在 KPR 集群上会系统性漏掉 Map 轴。

争论:固定上限 vs 动态 sizing

主张 风险
固定 --bpf-*-max 容量可预测;便于容量规划 估小则故障;估大则内存常驻
dynamic ratio 随节点内存伸缩 不同节点条目上限不一致;行为更难横向对比

文档同时提供两种旋钮,本身说明社区未把单一策略当作教条。可检验问题是:你的故障手册是否包含 map 压力信号,还是只有「重启 agent」。

另一争论与第 2 篇呼应:identity aggregation 减少 policy 条目是否值得排障可读性下降。聚合让 map 更不容易满,但从「一条 map 记录」反推「哪条 CiliumNetworkPolicy」更难。第 7 篇策略编译会给出控制面侧的选择器展开;本篇只强调数据面看到的是已经聚合后的键

开放问题

  1. map 压力与节点规模可观测性是否足够在「将满」前提前告警(系列研究台账 01–04)。
  2. identity aggregation 降低 policy 条目的收益,与排障时「聚合后更难从 map 反推选择器」的张力——第 7、13 篇。
  3. LB map 扩容必须中断的约束,在何种编排下可被蓝绿节点池吸收——第 6、12 篇。
  4. 多集群 ipcache 上限与 ClusterMesh 身份传播如何共同决定「远程身份陈旧」的概率——第 11 篇。

八、小结

  1. Policy / Service / CT(及 ipcache 等)是 Cilium 数据面的状态主板。
  2. 官方默认上限与满表后果是 A 级排障依据;动态 sizing 与 2/3 NAT 约束必须写进容量规划。
  3. v1.20 cilium_policy_v3_ 标记身份聚合语义世代。
  4. 内核 map 细节外链 ebpf/;本篇只钉 Cilium 职责与表象。
  5. 下一篇沿包路径走一遍:何时查哪张表。

九、参考资料

规范 / 官方文档(A)

源码(A)

站内对照

实验台账


上一篇:BPF 挂载 · 系列目录 · 下一篇:东西向包路径

读完这篇,下一步读什么

优先读同系列或同问题的下一篇,把单篇消费变成主题集群。


By .