Cilium 架构与数据面组件
Cilium 架构与数据面组件
组件全景
┌──────────────────────────────────────────┐
│ Kubernetes API Server │
└───────────────▲──────────────────┬─────────┘
│ watch │ watch
┌───────────────┴──────┐ ┌───────▼──────────────┐
│ cilium-operator │ │ cilium-agent │
│ (集群级: IPAM/身份/ │ │ (每节点: 加载 BPF、 │
│ ClusterMesh/CA) │ │ 管 Endpoint/策略) │
└───────────────▲──────┘ └───────▲──────────────┘
│ │ 写 BPF map
┌──────────────────────┴───┐ ┌──────────▼───────────┐
│ CiliumEndpoint (CEP) CRD │ │ eBPF 程序 (内核 hook) │
│ (Pod→IP→标签 同步) │ │ tc/xdp/socket/cgroup │
└───────────────────────────┘ └──────────▲───────────┘
│ 流日志
┌──────────────────────────────────────────┴───────────┐
│ Hubble (Relay + UI) — 从 eBPF 拿 L3/L4/L7 流事件 │
└──────────────────────────────────────────────────────┘
核心组件职责
cilium-agent(每节点 DaemonSet)
节点上的”大脑”,负责:
- 加载/管理 eBPF 程序:启动时根据配置把一套 BPF 程序挂到对应 hook(见下表)
- 维护 BPF Map:Service 映射、Endpoint 身份、策略、连接跟踪都存这里
- 监听 CEP/Policy/CIDR:K8s 里 Pod 一变,agent 更新本地 eBPF 状态
- 响应 kube-apiserver:通过 CiliumEndpoint CRD 把本节点 Pod 的身份/标签上报
- Host 网络栈接管:开启 KPR 后接管 NodePort/Service 转发;开启 Host Firewall 后管 host 命名空间流量
启动关键参数(Helm values.yaml):
kubeProxyReplacement: true # 启用 KPR(替代 kube-proxy)
kubeProxyReplacement: false # 保留 kube-proxy,只做网络策略
bpf:
masquerade: true # 出网做 SNAT(默认 eBPF 实现,不用 iptables MASQUERADE)
hostRouting: true # 用 host 路由而非隧道(配合 native routing)
cilium-operator(集群级,可多副本)
- IPAM 分配:多池 IPAM(Multi-pool)、节点 CIDR 分配
- 身份管理:维护
security identities(标签组合 → 数字 identity 的全局映射) - ClusterMesh 协调:跨集群服务同步
- 证书/CA:为 Hubble mTLS、节点间通信签发证书
- Ingress/Gateway API 控制器:当 Cilium 作为 Ingress/Gateway 实现时由它管
cilium-cni(CNI 插件二进制)
kubelet 创建 Pod 时调用的二进制(挂到 /opt/cni/bin/cilium-cni)。它:
- 调 cilium-agent 的 Unix socket 申请 IP(走 IPAM)
- 创建 veth pair,一端进 Pod netns,一端留 host
- 向 agent 注册 Endpoint,agent 据此生成该 Endpoint 的 eBPF 策略
注意:cilium-cni 只做”建连”,真正的转发/策略是 cilium-agent 加载的 eBPF 程序在做。
Hubble(可观测层)
- hubble 内嵌在 cilium-agent 里,从 eBPF 的
eventsmap 拿流事件 - hubble-relay 聚合所有节点的流,提供统一 gRPC 接口
- hubble-ui 提供服务拓扑图(浏览器访问)
- hubble observe CLI 实时看流日志
envoy(L7 代理,按需)
- 只有当策略用到 L7(HTTP/gRPC/Kafka) 时才需要
- Cilium 把 envoy 内嵌为 agent 的 sidecar 进程(不是每个 Pod 一个 sidecar!),由 agent 用 eBPF 把匹配 L7 的流量重定向给本节点的 envoy 实例
- 这就是 Cilium 的 sidecar-less service mesh:L7 策略能力 ≈ Istio,但无需给每个 Pod 注入 envoy
eBPF 程序清单(数据面挂了什么)
cilium-agent 加载的核心 BPF 程序(按 hook 点分组):
| Hook 点 | 程序/Section | 作用 |
|---|---|---|
| TC (ingress/egress) | cil_from_container / cil_to_container | Pod 进出流量的主处理:路由、NAT、策略、负载均衡 |
| TC (host) | cil_from_host / cil_to_host | 节点本机流量处理(host routing) |
| XDP | cil_xdp_entry | 网卡最早收包点做 LB / DROP(KPR 的 NodePort/XDP LB) |
| Socket (sockops) | cil_sock_ops | 连接建立时记录到连接跟踪、Socket LB 用 |
| Socket (sk_msg) | cil_sock_sendmsg / redir | Socket LB:connect()/sendmsg() 时直接选本地 backend |
| cgroup (sendmsg/recvmsg) | cil_cgroup_sendmsg | Pod 内应用发往 Service VIP 时,eBPF 直接解析成 backend IP |
| LXC / netdev | cil_lxc | 容器 netns 内最后一跳 |
用 ../linux/ebpf/eBPF 工具链实战 里的
bpftool net/bpftool prog list可以实际看到这些程序挂在哪些接口、哪些 hook 上。
Endpoint 模型(Cilium 的”身份”抽象)
Cilium 不给每个 Pod 直接套 iptables 规则,而是抽象成 Endpoint:
Pod 创建
→ cilium-cni 注册 Endpoint(拿到 IP + 标签)
→ agent 给 Endpoint 分配 security identity(标签组合的哈希)
→ 生成该 Endpoint 的 eBPF 策略程序(cil_from_container 等带 endpoint ID)
→ 策略以 "identity A → identity B 允许 port X" 表达,存 BPF map
- Endpoint 是策略执行的单元:网络策略编译成对 (src identity, dst identity, port, proto) 的允许列表
- CEP (CiliumEndpoint) CRD:每个 Pod 对应一个 CEP 对象,记录 IP、identity、策略状态,供 Hubble/其他节点消费
- 好处:Pod 扩缩容只是 identity 映射变化,不需要重写海量规则(对比 iptables 模式每加一个 Pod 都可能触发规则重算)
BPF 文件系统布局
Cilium 把 BPF Map 和程序挂在 bpffs(通常 /sys/fs/bpf):
ls /sys/fs/bpf/tc/globals/ # 全局 BPF map
# cilium_policy_* 策略 map(按 endpoint)
# cilium_lb4_services Service → backend 映射(KPR 核心)
# cilium_lb4_reverse_nat 反向 NAT 记录
# cilium_ct4_* 连接跟踪(conntrack 替代)
# cilium_ipcache Pod IP → identity 缓存
# cilium_sockets Socket LB 状态
排障时常直接 bpftool map dump 这些来看(详见 Cilium Hubble 可观测性与运维排障)。
启动加载流程(排障时理解顺序)
1. cilium-agent 启动
2. 探测内核特性(bpf, cgroup v2, sockops...)→ 决定能开哪些能力
3. 挂载 bpffs,加载全局 BPF map
4. 加载 eBPF 程序到 TC/XDP/socket/cgroup hook
5. 接管 kube-proxy(KPR):清理 iptables 规则,Service 改走 eBPF
6. 监听 K8s,为每个已有 Pod 创建 Endpoint + 加载策略
7. 暴露健康端口 /healthz,就绪
第 5 步是常见冲突点:如果旧 kube-proxy 没禁,会出现”双份转发”,表现为偶发连接重置。见 Cilium Hubble 可观测性与运维排障 的故障表。
关联知识
- Cilium 知识总览 — 本系列入口
- ../linux/ebpf/eBPF 核心机制与安全 — eBPF 程序/Map/verifier 原理
- ../linux/ebpf/eBPF 性能模型 — 为什么 eBPF 数据面比 iptables 快
- Cilium Service 与 KPR 深入 — 第 5 步接管 kube-proxy 的细节
- ../k8s/特性详解/nftables kube-proxy 详解 — 被替代的 iptables/nftables 实现
学习时间
| 阶段 | 时间 | 备注 |
|---|---|---|
| 架构组件 | 2026-07-16 | 完成:组件全景、eBPF 程序清单、Endpoint 模型、bpffs 布局、启动流程 |