2. eBPF 基础回顾:eBPF 在内核中的工作原理,与 Cilium/Hubble 的关系
2.1 eBPF 在内核中的执行模型
eBPF(extended Berkeley Packet Filter)是一种在内核虚拟机中运行沙箱化程序的技术,允许用户在不修改内核源码或加载内核模块的前提下,安全地扩展内核行为。其核心执行流程可概括为:编写 → 验证 → JIT 编译 → 挂载 → 事件驱动执行。
关键概念: eBPF 程序不是“运行在用户态”的进程,而是“附着在内核事件钩子(Hook)上”的字节码,由内核事件(如系统调用、网络包到达、函数进入/退出)触发执行。
下图展示了 eBPF 程序从用户态编写到内核态执行的完整生命周期:
2.2 eBPF 与 Cilium 的关系
Cilium 是 eBPF 在云原生领域最成功的落地实践。它利用 eBPF 替代了传统容器网络方案(如 Calico、Flannel)中的 iptables 和内核模块,实现了更高效、更灵活的网络、安全和可观测性能力。
| 维度 | 传统方案(iptables) | Cilium(eBPF) |
|---|---|---|
| 数据路径 | 线性遍历规则链,O(n) 复杂度 | 哈希表 + 程序化决策,O(1) 复杂度 |
| 网络策略 | 依赖 iptables 规则,Pod IP 变动需重写 | 基于身份(Identity)的 L3/L4/L7 策略,无需关心 IP |
| 负载均衡 | kube-proxy 通过 iptables 实现,性能随规则数下降 | eBPF 原生实现 XDP/TC 负载均衡,直接操作 socket |
| 可观测性 | 依赖外部工具(tcpdump、netstat) | 内置 Hubble,通过 eBPF 采集流、DNS、HTTP 指标 |
| 安全能力 | 网络层隔离,无应用层感知 | 基于 eBPF 的 L7 协议解析与策略执行(HTTP/gRPC/Kafka) |
升级场景提示: 在集群升级过程中,Cilium 的 eBPF 数据路径可能因内核版本变化而出现兼容性问题。例如,某些内核 API 在 5.10 到 5.15 之间发生了结构性变化,导致 eBPF 程序加载失败或行为异常。这正是我们后续章节中“节点池巡检”需要重点覆盖的检查项。
2.3 Hubble 与 eBPF 的关系
Hubble 是 Cilium 的可观测性层,本质上是 eBPF 数据采集能力的“用户态消费者”。它不直接编写 eBPF 程序,而是通过 Cilium Agent 暴露的 gRPC 接口,消费由 eBPF 程序在内核中采集的流数据。
Hubble 的架构可概括为三层:
- eBPF 采集层(内核态):Cilium Agent 加载的 eBPF 程序挂载在 TC、XDP、kprobe 等钩子上,捕获网络包、DNS 请求、TCP 状态变化等事件,写入 Perf Ring Buffer 或 BPF Map。
- Hubble Server(用户态):运行在每个节点上的 Hubble 实例,通过 gRPC 从 Cilium Agent 读取 eBPF 事件流,进行聚合、过滤、缓存,并提供流式 API。
- Hubble UI / CLI / Metrics:上层消费端,将流数据转化为可视化拓扑、流量日志、Prometheus 指标。
2.4 本章小结:eBPF 在集群升级中的关键角色
- eBPF 是底层引擎:提供安全、高性能的内核扩展能力,是 Cilium 网络、安全和可观测性的基石。
- Cilium 是 eBPF 的云原生封装:将 eBPF 的复杂性抽象为 Kubernetes 原生的 CRD(CiliumNetworkPolicy、CiliumEndpoint 等),让运维人员无需直接编写 eBPF 代码。
- Hubble 是 eBPF 数据的可观测性出口:将内核态的事件流转化为可消费的流量基线,是升级巡检中“对比”环节的数据来源。
- 升级风险点:内核版本变更可能导致 eBPF 辅助函数签名变化、BPF 类型格式(BTF)不兼容、或特定钩子行为差异。Hubble 流量基线对比正是为了快速发现这些底层变化对业务流量的影响。
常见误区: 不要将 Hubble 视为一个独立的“抓包工具”。它依赖 Cilium Agent 加载的 eBPF 程序,如果 Cilium 升级后 eBPF 程序加载失败,Hubble 将直接失去数据源。因此,在节点池巡检中,第一步永远是确认 eBPF 程序状态(
cilium status),而非直接查看 Hubble 数据。