第 2 篇 钉了 Identity;本篇钉 BPF 挂载轴。没有挂载点,数字身份只是控制面对象;有了挂载点,策略与 Service 才成为每个包上的查找。本文只回答:Cilium 在路径上用哪些 hook、各自干什么、程序如何被加载与替换。Verifier 可达性、复杂度上限与 JIT 后端不在此重写——请读 ebpf/。
本篇在系列中的位置
篇目 核心内容 第 2 篇 · Endpoint 与 Identity 数字身份 第 3 篇 · BPF 挂载 TC/XDP/cgroup 角色;加载与替换 第 4 篇 · 关键 BPF Map map 职责与失败表象 系列目录 全部篇目
版本锚定:Cilium v1.20.0;文档
docs.cilium.io/en/v1.20/network/ebpf/intro/;源码bpf/bpf_{xdp,host,lxc,sock,overlay,wireguard}.c与pkg/datapath/loader@ tag v1.20.0。内核能力矩阵见官方系统要求;不以「最新内核万能」糊弄。
一、Hook 不是百科,是路径上的岗位
Cilium Datapath Intro(v1.20)列出数据面实际使用的 hook,并强调它们组合成更高层对象(Prefilter、Endpoint Policy、Service、L3 Encryption、Socket Layer Enforcement、L7 Policy)。排障时要问的是「这个包经过了哪个岗位」,而不是背全内核 hook 列表。
| Hook(文档口径) | 在路径上的岗位 | Cilium 典型用途 |
|---|---|---|
| XDP | 驱动最早收包点 | 预过滤、NodePort 等早路径加速;丢弃明显非法流量 |
| TC ingress/egress | 设备 qdisc 分类点;容器侧常挂在 veth 主机端 | L3/L4 策略、重定向到 endpoint、与 host/overlay 衔接 |
| Socket operations | cgroup 上 TCP 状态变迁 | 发现可加速的 ESTABLISHED 连接 |
| Socket send/recv(sk_msg 等) | 已建立套接字的消息路径 | 同节点 socket 直通,减少重复策略遍历 |
Intro 对 TC 的关键句值得原意保留:容器用 veth pair 连到主机;在主机侧 veth 的 TC ingress 上挂程序,可监控并强制离开容器的流量;再结合主机侧其他 TC 程序,覆盖进出节点的路径。XDP 与面向网络的 TC ingress 可耦合——此时合理假设多数流量已通过更早过滤。
这与 k8s-network/13 中的 hook 表同构,但本系列后续要用它解释停顿点:策略拒绝多落在 Endpoint Policy(TC/lxc 路径),Service VIP 转换可能落在 TC 或 cgroup connect,同节点加速落在 socket 层。
二、源码入口与数据面对象的对应
v1.20.0 的 bpf/
目录用多个编译单元对应不同挂载角色(文件名即第一线索):
| 源码入口 | 角色直觉 |
|---|---|
bpf_xdp.c |
物理/驱动早路径 |
bpf_host.c |
主机设备 / 主机网络命名空间侧逻辑 |
bpf_lxc.c |
每 endpoint(lxc)策略与转发核心 |
bpf_sock.c |
cgroup/socket 相关 |
bpf_overlay.c |
overlay(如 VXLAN)路径 |
bpf_wireguard.c |
WireGuard 相关数据面 |
bpf_lxc.c 头部直接 #include
lib/policy.h、lib/lb.h、lib/identity.h、lib/nat.h、lib/nodeport.h
等,说明 endpoint 程序是策略、LB、身份、NAT
的交汇点,而不是「只做隔离」的瘦过滤器。加载与编排在
Go 侧 pkg/datapath/(含
loader、linux、xdp
等包)完成:把编译产物挂到正确的
device/cgroup,并管理替换。
Intro 中的高层对象如何映射到岗位:
Prefilter ≈ XDP + CIDR/endpoint 合法性类查找
Endpoint Policy ≈ TC/lxc(及关联 tail call)上的 identity→policy
Service ≈ LB map 查找(可嵌在 endpoint/host 路径)
L3 Encryption ≈ 加密标记 + 内核 xfrm / 相关 BPF 辅助
Socket Enforcement ≈ sockops 选中 + sk_msg 直通
L7 Policy ≈ 重定向到用户态 Envoy(边界见第 10 篇)
硬边界:本篇不推导 verifier 如何证明
bpf_lxc
复杂程序安全;若加载失败,先把错误当作「程序未上岗」,再决定是内核版本、复杂度、还是
map 兼容问题。算法与指令限制见 ebpf/。
三、按流量方向看挂载(与 Life of a Packet 对齐)
官方 Life of a Packet 给出三幅图:Endpoint→Endpoint、Egress from Endpoint、Ingress to Endpoint。本篇只提取挂载含义;逐跳停顿与 map 查找留到 第 5 篇。
同节点 Endpoint → Endpoint
包在两个 veth/endpoint 程序之间传递;可选 L7 时旁路到代理。启用 socket layer enforcement 时,文档写明:TCP 握手阶段仍需穿越 endpoint policy,直到 ESTABLISHED;之后同节点路径可主要留在 L7(若有)与 socket 加速,避免反复跑完整策略块。
失败表象对照:
- 握手失败、ESTABLISHED 后却异常:可能策略/身份问题,或 socket 加速未挂上。
- 仅同节点慢而跨节点「正常」:少见,但若加速路径异常回退到完整 TC 路径,值得查 sockops/sk_msg 是否按预期附着。
Egress from Endpoint
出站经 endpoint 策略后,可走 overlay
设备(文档默认名叙事为
cilium_vxlan)或直连路由;可选 L3
encryption。挂载岗位是 lxc/host/overlay
程序链,而不是应用进程里的 iptables。
Ingress to Endpoint
入站可先解密,再经 host/overlay 进入目标 endpoint 策略。XDP 预过滤若启用,非法目的地可在更早丢弃——压力下这是「省 CPU」也是「改丢包地点」:故障从 TC 挪到 XDP 时,Hubble/传统 tcpdump 抓取点要跟着变。
cgroup 与 kube-proxy 替代的衔接
kube-proxy 替代篇(第 6 篇)会展开 ClusterIP 在 cgroup connect 等路径上的透明转换。本篇先立界:cgroup hook 让进程发起连接时看到 Service 语义,而不必先把包送进经典 netfilter DNAT。能力依赖内核;文档 Iptables Usage 写明:若 eBPF 数据面缺少所需能力,功能可能回退到 legacy iptables 实现。
四、程序生命周期:加载、替换、与 map 同生共死
加载
agent 启动与 endpoint 变更时,loader
路径大致是:根据节点/endpoint 配置生成或选择 BPF 对象 →
创建/打开依赖的 map →
BPF_PROG_LOAD(经库封装)→ attach 到 device 或
cgroup。Intro 把「程序 + map +
虚拟设备(cilium_host /
cilium_net)+ 可选 overlay + 可选
Envoy」看成一套组合物。
可核对失败模式(机制级,不编造日志):
| 阶段 | 表象方向 |
|---|---|
| 加载被 verifier 拒绝 | 新程序未替换旧程序;功能停在旧行为或缺失 |
| attach 失败(设备/权限/内核) | 接口上无期望程序;流量可能走意外主机路径 |
| map 不兼容 | 升级/降级需要重建 map;v1.20 policy map 改名前缀即一例 |
加载失败时,控制面往往仍显示「agent
Running」。挂载轴的检查必须落到接口/cgroup
上是否真有期望程序,而不是只看 Pod 状态。具体用
bpftool / cilium bpf 还是节点
debug,属于第 12
篇运维口径;本篇只要求把「程序未上岗」从「策略写错」里拆出来。
替换与窗口
BPF
程序替换通常追求新程序就位后再切流量视角,但控制面与多程序协作仍可能留下窗口:例如
bpf_lxc 注释提到可能在 bpf_host
策略程序尚未就绪时加载,并对 host 路径给出
DROP_HOST_NOT_READY
一类细粒度错误——这是组件就绪顺序问题,不是应用层「偶发」。
Policy map 在 v1.20 使用 cilium_policy_v3_
前缀(pkg/maps/policymap):格式未必变,但
identity aggregation
语义变,改名迫使升级/降级时重建
map,并与新程序原子切换,以减轻「旧 map 缺身份 →
已有连接丢包」类问题(上游 PR 叙述与注释一致)。挂载轴与 Map
轴在此交汇:换程序往往伴随换 map 世代。
endpoint 重建(Pod 重启、策略大变更触发 reload)会再次走过「加载 → attach → map 填充」。若填充慢于业务流量涌入,窗口表现类似第 2 篇的拒绝窗口,但根因在程序/map 世代,不在标签哈希本身。复盘时问:是身份变了,还是同一身份下程序刚被替换?
与 iptables 回退
Iptables Usage 文档给出 kube-proxy 与 Cilium iptables 规则的集成示意。排障含义:看到宿主机上仍有 iptables 规则,不等于「Cilium 没在用 eBPF」——可能是互操作、回退或主机防火墙路径。先确认 datapath 模式与内核特性,再决定规则是否仍在关键路径上。
回退还改变观测坐标:原本应在 TC drop reason / Hubble verdict 上看到的拒绝,可能变成 netfilter 计数。升级内核或开启更多 eBPF 能力后,同一故障的「正确抓取点」会迁移——第 13 篇排障坐标系会要求先声明当前主路径是 BPF 还是回退。
与代理系列排除树的衔接
Envoy 16 与 HAProxy 14 在「只要 L3/L4 与身份」时指向 eBPF。落地到本篇:那意味着策略与 LB 岗位应落在 TC/XDP/cgroup,而不是再挂一层用户态 stream 代理。一旦 Intro 中的 L7 Policy 对象把流量重定向到 Envoy,挂载轴就出现分叉——内核岗位只负责送到代理,HTTP 语义停顿点改用 Envoy 坐标系。混用合法,但必须在工单里写清「包在哪一层离开了 eBPF 主路径」。
五、学术谱系、争论与开放问题
谱系:McCanne & Jacobson(USENIX 1993)给出内核包过滤 VM;扩展 BPF 把程序挂到更多内核事件。XDP(Høiland-Jørgensen et al., CoNEXT 2018)把「最早可编程点」推到驱动,论文假设包括:在内核内处理相对用户态绕路的收益,以及驱动/硬件能力差异带来的可移植边界。Cilium 选择多 hook 分工而非「一切都进 XDP」:策略与连接状态需要的元数据与上下文,往往在 TC/socket 层更合适;XDP 承担早过滤与部分 LB 加速。
工程映射要诚实:CoNEXT 2018 的实验平台与驱动集合,并不等于你集群里每张云网卡的 XDP 能力。官方系统要求用内核版本与特性矩阵表达「哪些功能可纯 eBPF」——把论文里的加速曲线直接写成生产承诺,属于证据错位。本系列因此只把 XDP 写成有条件的早岗位,并把回退写进挂载轴。
争论:完全旁路 netfilter vs 与 iptables 共存
| 侧 | 主张 | 工程现实(文档已承认) |
|---|---|---|
| 完全旁路 | 缩短路径、减少 netfilter 锁与规则刷新 | 依赖内核特性矩阵;缺失时回退 iptables |
| 共存 / 渐进 | 运维可理解、兼容 kube-proxy 迁移 | 双路径心智负担;排障易看错层 |
站内 k8s-network/21 讨论复杂度与更新路径;本系列把争论收束到可观察的挂载事实:程序在哪个 ifindex/cgroup、回退是否启用。
另一处常被营销话语抹平的争论是:「eBPF 替代 kube-proxy」是否等于「节点上不再有任何 iptables」。文档中的互操作图说明二者可以同时存在。可检验命题变成:关键 Service/策略路径是否仍进入某条链;而不是规则表是否为空。第 5–6 篇会用包停顿点继续钉这件事情。
开放问题:
- 多程序替换的就绪顺序如何被统一观测(host vs lxc vs xdp)——指向第 12–13 篇。
- 驱动 XDP 模式差异(generic / native / offload)如何改变「早丢包」的可观测性——需结合内核与网卡,不做未实测排名。
- 与用户态代理挂载的边界:L7 重定向后,策略半在内核半在 Envoy——第 10 篇;对照 envoy/16。
- 程序复杂度与功能开关的组合爆炸:每打开加密、WireGuard、某些
LB 模式,都可能改变
bpf_lxc可加载性;如何在功能矩阵与 verifier 限制之间做可预测的发布——外链 ebpf/ 的复杂度讨论,本系列在第 12 篇回收运维信号。
六、小结
- Cilium 用 XDP / TC / socket(cgroup) 组成岗位,而不是单一巨型 hook。
bpf_lxc等源码入口对应 endpoint 策略与 LB 交汇;Go loader 负责挂载。- Life of a Packet 三场景决定哪些岗位被穿越;socket 加速改变 ESTABLISHED 后的路径。
- 加载/替换与 map 世代耦合;能力不足时可能 iptables 回退。
- 下一篇进入 Map 轴:挂载解决「代码在哪跑」,map 解决「状态在哪查」。
七、参考资料
规范 / 官方文档(A)
- Cilium v1.20 eBPF Datapath Introduction —
docs.cilium.io/en/v1.20/network/ebpf/intro/。 - Cilium v1.20 Life of a Packet —
docs.cilium.io/en/v1.20/network/ebpf/lifeofapacket/。 - Cilium v1.20 Iptables Usage —
docs.cilium.io/en/v1.20/network/ebpf/iptables/。 - Cilium BPF and XDP Reference Guide —
docs.cilium.io/en/v1.20/reference-guides/bpf/。
源码(A)
bpf/bpf_{xdp,host,lxc,sock,overlay,wireguard}.c@ v1.20.0pkg/datapath/loader、pkg/datapath/linux、pkg/datapath/xdp@ v1.20.0pkg/maps/policymap(程序替换与 map 改名耦合)@ v1.20.0
核心论文
- McCanne & Jacobson, The BSD Packet Filter, USENIX Winter 1993。
- Høiland-Jørgensen et al., The eXpress Data Path, CoNEXT 2018。
站内对照
- ebpf/ 系列(verifier / JIT / Map 内核)
- k8s-network/13
- k8s-network/21 eBPF vs netfilter
实验台账
- 本篇无
bpftool/cilium bpf输出;有集群后再补加载证据。
→ 上一篇:Endpoint 与 Identity · 系列目录 · 下一篇:关键 BPF Map
读完这篇,下一步读什么
优先读同系列或同问题的下一篇,把单篇消费变成主题集群。
【Cilium / eBPF】数据面全景:五轴坐标系与 16 篇路线
相对 k8s-network/13、ebpf/ 与 Envoy/HAProxy 排除树,钉清 Cilium eBPF 数据面内核缺口;定义 Identity、BPF 挂载、Map 状态、包路径、策略与观测五条坐标系,给出 16 篇阅读路线。
【Cilium / eBPF】Endpoint 与 Identity:数字身份、标签选择与生命周期
钉清 Cilium Endpoint 与 Numeric Identity 的关系:安全相关标签如何导出集群范围数字身份、保留身份与 well-known 身份、标签变更时的短暂 deny/allow 窗口,以及相对 IP 策略消除了什么。
【Cilium / eBPF】关键 BPF Map:policy、service、CT 的职责与失败表象
按 Cilium v1.20 Maps 文档钉清 policy、Service LB、CT、NAT、ipcache 等 map 的职责、默认容量与满表后果;说明 v3 policy map 语义变更,内核 map 实现外链 ebpf/ 系列。
【Cilium / eBPF】东西向包路径:Pod→Pod 停顿点与 netfilter 旁路
沿 Cilium v1.20 Life of a Packet 钉清同节点与跨节点东西向停顿点:Endpoint Policy、Service、socket 加速、加密与 L7 重定向;说明与 netfilter/kube-proxy 旁路关系,并为 kube-proxy 替代篇铺路。