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

【Cilium / eBPF】BPF 挂载与程序生命周期:TC、XDP、cgroup 在路径上的角色

文章导航

分类入口
kubernetesnetwork
标签入口
#cilium#ebpf#tc#xdp#cgroup#bpf-lxc#datapath#loader#v1.20.0

目录

第 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}.cpkg/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.hlib/lb.hlib/identity.hlib/nat.hlib/nodeport.h 等,说明 endpoint 程序是策略、LB、身份、NAT 的交汇点,而不是「只做隔离」的瘦过滤器。加载与编排在 Go 侧 pkg/datapath/(含 loaderlinuxxdp 等包)完成:把编译产物挂到正确的 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 加速,避免反复跑完整策略块。

失败表象对照:

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 16HAProxy 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 篇会用包停顿点继续钉这件事情。

开放问题

  1. 多程序替换的就绪顺序如何被统一观测(host vs lxc vs xdp)——指向第 12–13 篇。
  2. 驱动 XDP 模式差异(generic / native / offload)如何改变「早丢包」的可观测性——需结合内核与网卡,不做未实测排名。
  3. 与用户态代理挂载的边界:L7 重定向后,策略半在内核半在 Envoy——第 10 篇;对照 envoy/16
  4. 程序复杂度与功能开关的组合爆炸:每打开加密、WireGuard、某些 LB 模式,都可能改变 bpf_lxc 可加载性;如何在功能矩阵与 verifier 限制之间做可预测的发布——外链 ebpf/ 的复杂度讨论,本系列在第 12 篇回收运维信号。

六、小结

  1. Cilium 用 XDP / TC / socket(cgroup) 组成岗位,而不是单一巨型 hook。
  2. bpf_lxc 等源码入口对应 endpoint 策略与 LB 交汇;Go loader 负责挂载。
  3. Life of a Packet 三场景决定哪些岗位被穿越;socket 加速改变 ESTABLISHED 后的路径。
  4. 加载/替换与 map 世代耦合;能力不足时可能 iptables 回退。
  5. 下一篇进入 Map 轴:挂载解决「代码在哪跑」,map 解决「状态在哪查」。

七、参考资料

规范 / 官方文档(A)

源码(A)

核心论文

站内对照

实验台账


上一篇:Endpoint 与 Identity · 系列目录 · 下一篇:关键 BPF Map

读完这篇,下一步读什么

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


By .