文章

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)。它:

  1. 调 cilium-agent 的 Unix socket 申请 IP(走 IPAM)
  2. 创建 veth pair,一端进 Pod netns,一端留 host
  3. 向 agent 注册 Endpoint,agent 据此生成该 Endpoint 的 eBPF 策略

注意:cilium-cni 只做”建连”,真正的转发/策略是 cilium-agent 加载的 eBPF 程序在做

Hubble(可观测层)

  • hubble 内嵌在 cilium-agent 里,从 eBPF 的 events map 拿流事件
  • 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_containerPod 进出流量的主处理:路由、NAT、策略、负载均衡
TC (host)cil_from_host / cil_to_host节点本机流量处理(host routing)
XDPcil_xdp_entry网卡最早收包点做 LB / DROP(KPR 的 NodePort/XDP LB)
Socket (sockops)cil_sock_ops连接建立时记录到连接跟踪、Socket LB 用
Socket (sk_msg)cil_sock_sendmsg / redirSocket LB:connect()/sendmsg() 时直接选本地 backend
cgroup (sendmsg/recvmsg)cil_cgroup_sendmsgPod 内应用发往 Service VIP 时,eBPF 直接解析成 backend IP
LXC / netdevcil_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 可观测性与运维排障 的故障表。

关联知识

学习时间

阶段时间备注
架构组件2026-07-16完成:组件全景、eBPF 程序清单、Endpoint 模型、bpffs 布局、启动流程