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

【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.0;docs.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/ 下可见与文档同构的包名:policymap、ctmap、nat、ipcache、lxcmap、authmap、fragmap 等。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 .