数据包在哪里被抓住,又被弹到哪里
一句话总结
Cilium 会把 Kubernetes 的语义(服务、标签、策略)直接下发到内核中的数据结构。因此,即使服务增加,查找成本也不会增长,但这并不意味着一切都会变快。
为什么需要了解这一点
在 kube-proxy 的 iptables 模式中,一次服务请求会遍历 KUBE-SERVICES 链,在 KUBE-SVC-* 中经过概率分支,再于 KUBE-SEP-* 中执行 DNAT。规则数量与服务数和后端数成正比,内核对每个数据包都会近似遍历这份列表。
更棘手的是更新成本。iptables 即使只修改一条规则,实际上也会重写整张表。 在频繁部署的集群中,这会表现为 CPU 峰值和规则生效延迟。在拥有数千个服务的环境里,“Pod 已经启动,但流量还没到”的数秒空档就源于此处。
eBPF 会把这两个维度都变为常数时间。查找通过 hash map 完成,与服务数量无关;更新则是以 map entry 为单位的增量更新,不会触碰其他 entry。
工作原理
以下是从外部通过 NodePort 进入的数据包所经历的路径。
NIC 수신
-> [XDP 훅] 드라이버 수준. sk_buff 할당 전이라 가장 빠름
-> [tc ingress 훅] 서비스 변환(lb4_services -> lb4_backends), conntrack,
ipcache 룩업으로 목적지 아이덴티티 확인
-> bpf_redirect_peer 호스트 veth 에서 파드 네임스페이스 안 피어로 직행
-> [파드 lxc 인터페이스] 정책 평가: (소스 아이덴티티, 포트, 프로토콜, 방향)
-> 애플리케이션 소켓
需要抓住三点。第一,XDP 位于分配内存之前的阶段,因此可用于 DDoS 过滤和 NodePort 加速,但需要受支持的 NIC driver。第二,数据路径的主体是 tc hook,服务转换、conntrack 和策略评估都在这里发生。第三,bpf_redirect_peer 会跳过数据通过 veth pair 时产生的一轮 softIRQ 重新调度,一次跨越 namespace 边界。
策略不是按 IP,而是按身份评估。每组 Pod 标签对应一个数字,这个数字会成为内核 map 的 key。考试会直接涉及下面这些保留身份,最好记住。
| 编号 | 名称 | 含义 |
|---|---|---|
| 0 | unknown | 未知来源 |
| 1 | host | 本地节点自身 |
| 2 | world | 集群外部的全部对象 |
| 3 | unmanaged | 不受 Cilium 管理的 endpoint |
| 4 | health | 健康检查 endpoint |
| 5 | init | 正在初始化的 endpoint |
| 6 | remote-node | 其他节点 |
| 7 | kube-apiserver | API server |
| 8 | ingress | ingress |
职责分工也要梳理清楚。Cilium Agent 以 DaemonSet 形式运行在每个节点上,负责加载 eBPF 程序、管理 endpoint、应用策略和处理 conntrack。Cilium Operator 在每个集群运行一份,负责集群范围的 IPAM、CRD garbage collection 和节点发现。Agent 要直接操作节点数据路径,所以必须是 DaemonSet;Operator 处理集群全局状态,因此一份即可。
最后也要坦诚说明代价。换成 eBPF 后一切都会变快,这种说法并不正确。
- 应用了 L7 策略的流量会离开内核,经过 userspace Envoy,因此会增加延迟。
- tunnel 模式(VXLAN/Geneve)会为每个数据包增加约 50 字节的封装开销,并减小 MTU。
- eBPF 程序载入内核前必须通过 verifier。无法保证终止的循环或错误的内存访问会被拒绝,指令数限制也是为了强制确保程序结束的安全机制。
了解“启用什么功能会付出什么代价”,是运维的核心。
实际工作中的表现
作者在一个由 7 个节点组成的 home lab(cp-1/2/3 + gpu-a/b/c/d)上运行 Kubernetes v1.34.10、containerd 1.7.27、kernel 6.14 和 Cilium 1.20.1。这个集群使用 kubeadm init --skip-phases=addon/kube-proxy,从一开始就没有安装 kube-proxy。这与安装后再删除不同。只要 kube-proxy 曾经运行过一次,就会在节点上刻下 KUBE-SERVICES / KUBE-SVC-* / KUBE-SEP-* 链;即使删除 DaemonSet,这些规则仍会保留,并与 eBPF 数据路径冲突。
以下结果来自测量,而不是主张。
kube-proxy 파드 수: 0
노드의 iptables KUBE- 체인 개수: 0
服务则以如下形式位于内核 map 中。
SERVICE ADDRESS BACKEND ADDRESS (REVNAT_ID) (SLOT)
10.96.0.10:53/TCP (1) 10.244.0.150:53/TCP (4) (1)
10.96.0.1:443/TCP (1) 10.0.0.120:6443/TCP (1) (1)
cilium status 报告了 KubeProxyReplacement: True、Modules Health: OK 92 / Degraded 0;包括节点状态、控制平面、CNI、CoreDNS、调度和服务 DNS 在内的 14 项基本验证也全部 14/14 通过。这些数字之所以重要,理由很简单:证明 eBPF 数据路径正在工作的,不是文档,而是链数量和 map dump。
下个测验将检查什么
本模块只讲概念。下一模块会介绍身份模型和 kube-proxy 替代方案,让你把上面看到的值直接写入 Helm values 文件,并创建验证其状态的脚本。