Cilium 是 eBPF 技术在云原生领域最成功的实践——它不仅替代了 kube-proxy 和 iptables,更重新定义了 Kubernetes 网络安全模型。从 Google、Apple、Meta 到字节跳动、阿里巴巴,Cilium 已成为大规模 Kubernetes 集群网络的事实标准。
这一章的主角是Cilium 的核心架构——理解它如何用 eBPF 构建高性能、可编程、身份驱动的网络方案。
一、Cilium 架构总览
1.1 核心组件
1.2 Cilium 的 eBPF 管线
Cilium 在每个 Node 上部署一组 eBPF 程序,形成完整的网络处理管线:
| 阶段 | eBPF 程序 | 功能 |
|---|---|---|
| XDP | xdp.c | DDoS 防护、NodePort 加速 |
| TC ingress | bpf_lxc.c | 连接跟踪、DNAT、策略检查 |
| TC egress | bpf_lxc.c | SNAT、策略检查 |
| Socket | bpf_sock.c | Socket 短路优化 |
二、身份安全模型
2.1 传统 IP vs Cilium 身份
传统网络安全基于 IP 地址——防火墙规则匹配源/目标 IP。但在 Kubernetes 中,Pod IP 是动态的,基于 IP 的安全规则不可靠。
Cilium 引入了**基于身份(Identity)**的安全模型:
2.2 身份的工作原理
- 身份分配:Cilium 根据 Pod 的标签(Labels)计算身份 ID
- 身份传播:身份信息通过 KV Store 在集群中传播
- eBPF 查找:eBPF 程序根据数据包的源/目标 IP 查找身份
- 策略匹配:基于身份匹配 NetworkPolicy 规则
# 查看 Cilium 身份cilium identity list
# 输出示例:# ID LABELS# 1 reserved:host# 2 reserved:world# 10001 app=frontend,env=prod# 10002 app=backend,env=prod# 10003 app=database,env=prod2.3 NetworkPolicy 实现
# Cilium NetworkPolicy(基于身份)apiVersion: cilium.io/v2kind: CiliumNetworkPolicymetadata: name: frontend-to-backendspec: endpointSelector: matchLabels: app: backend ingress: - fromEndpoints: - matchLabels: app: frontend toPorts: - ports: - port: "8080" protocol: TCPCilium 将此策略编译为 eBPF 规则:
Identity 10001 (frontend) → Identity 10002 (backend) : TCP/8080 → ALLOW其他 → Identity 10002 (backend) : DROP2.4 L7 策略与 Envoy 集成
L3/L4 策略仅能基于 IP 和端口做访问控制,但生产环境往往需要 HTTP 路径、gRPC 方法等应用层维度的精细策略。Cilium 通过嵌入 Envoy 代理实现 L7 策略:
当 TC eBPF 程序检测到某个连接命中了 L7 策略,会通过 Socket 级重定向将流量导入 Envoy。Envoy 解析 HTTP/gRPC 协议后,根据 Cilium 下发的 L7 规则做路径匹配、方法过滤、Header 检查,最终决定放行或拒绝。整个过程对应用透明——应用代码无需任何修改。
2.5 身份分配详解
Cilium 的身份 ID 是一个 32 位无符号整数,由标签组合的哈希值决定。分配算法的核心流程:
- 收集 Pod 的全部标签,按字典序排列
- 对排序后的标签字符串计算 SHA256 哈希
- 取哈希值的前 32 位作为身份 ID
- 若与已有身份冲突,递增重试
| 属性 | 说明 |
|---|---|
| 身份范围 | 1–65535(保留 1–255 给系统身份) |
| 保留身份 | 1=host, 2=world, 3=cluster, 4=health |
| 冲突概率 | 标签组合空间远大于 65536,实际冲突率低 |
| 传播方式 | 通过 etcd/KV Store 在集群间同步 |
身份 ID 上限为 65535。在标签组合极多的大规模集群中(如多租户平台),可能面临身份耗尽。监控 cilium identity list | wc -l,当接近上限时需要合并标签策略以减少身份数量。
三、Cilium eBPF 管线详解
3.1 数据包处理流程
3.2 连接跟踪表
Cilium 维护自己的连接跟踪表(而非使用 Netfilter conntrack):
// Cilium 连接跟踪条目(简化)struct ct_entry { __u16 src_port; __u16 dst_port; __u32 src_ip; __u32 dst_ip; __u8 protocol; __u8 state; // SYN_ESTABLISHED, ESTABLISHED, FIN, etc. __u32 src_identity; // 源身份 ID __u32 dst_identity; // 目标身份 ID __u64 last_seen; // 最后活跃时间 __u32 backend_ip; // 后端 IP(DNAT) __u16 backend_port; // 后端端口};3.3 eBPF Map 结构
| Map | 类型 | 用途 |
|---|---|---|
| CT_MAP | LRU_HASH | 连接跟踪表 |
| LB_MAP | HASH | Service 负载均衡 |
| IDENTITY_MAP | HASH | IP → 身份映射 |
| POLICY_MAP | HASH | 身份 → 策略规则 |
| METRICS_MAP | PERCPU_ARRAY | 统计指标 |
| TUNNEL_MAP | HASH | 隧道端点映射 |
| NODE_MAP | HASH | 节点信息 |
3.4 Egress 数据路径
出方向处理是 Cilium 管线中容易忽视的环节。当 Pod 发出的数据包离开节点时,TC egress 程序依次执行:
- 策略检查:基于源身份和目标身份匹配 egress 规则
- SNAT:将 Pod IP 替换为节点 IP(跨节点通信时)
- 连接跟踪记录:写入 egress 方向的 CT 条目,用于回程匹配
- Bandwidth Manager:应用 EDT 时间戳进行速率控制
// egress 方向简化处理逻辑SEC("tc")int tc_egress(struct __sk_buff *skb){ // 查找源身份 __u32 src_id = lookup_identity(skb->local_ip4); __u32 dst_id = lookup_identity(skb->remote_ip4);
// egress 策略检查 if (!policy_allow(src_id, dst_id, skb->protocol)) return TC_ACT_SHOT;
// SNAT:Pod IP → Node IP if (needs_snat(skb)) do_snat(skb);
return TC_ACT_OK;}3.5 Bandwidth Manager 与 EDT
Cilium 的 Bandwidth Manager 使用 EDT(Earliest Departure Time)机制实现容器速率限制,比传统的 TBF(Token Bucket Filter)和 HTB 更高效:
传统方式在每个 qdisc 中排队数据包,EDT 则为每个数据包打上一个时间戳,表示”最早可发送时间”。网卡驱动在发送时检查时间戳,未到时间的包延迟发送。这种方式避免了 qdisc 排队带来的额外延迟和锁竞争。
# 启用 Bandwidth Managerhelm install cilium cilium/cilium \ --set bandwidthManager.enabled=true \ --set bandwidthManager.bbr=true| 机制 | 原理 | 优势 | 限制 |
|---|---|---|---|
| TBF/HTB | 令牌桶排队 | 成熟稳定 | 多 qdisc 锁竞争 |
| EDT | 时间戳调度 | 无锁、低延迟 | 需要 5.1+ 内核 |
四、Hubble:网络可观测性
4.1 Hubble 架构
4.2 Hubble 事件类型
| 事件 | 来源 | 信息 |
|---|---|---|
| DROP | TC eBPF | 丢弃原因、身份、策略 |
| TRACE | TC eBPF | 数据包路径追踪 |
| L7 | Envoy | HTTP/gRPC 请求/响应 |
| DEBUG | 各组件 | 调试信息 |
4.3 Hubble CLI 使用
# 查看 Pod 间流量hubble observe --since 1m
# 过滤特定 Pod 的流量hubble observe --to-pod app=backend
# 查看 DROP 事件hubble observe --type drop
# 查看特定身份的流量hubble observe --from-identity 10001
# 输出 JSON 格式hubble observe -o json五、ClusterMesh:多集群网络
5.1 ClusterMesh 架构
5.2 ClusterMesh 的能力
| 能力 | 说明 |
|---|---|
| 跨集群 Pod 通信 | Pod 可以直接访问其他集群的 Service |
| 跨集群 NetworkPolicy | 策略可以引用其他集群的身份 |
| 全局 Service | Service 可以跨集群负载均衡 |
| 身份全局一致 | 同一标签在不同集群有相同身份 ID |
5.3 ClusterMesh 部署
# 启用 ClusterMeshcilium clustermesh enable
# 连接两个集群cilium clustermesh connect --destination-context cluster-b
# 验证连接cilium clustermesh statuscilium clustermesh vm list5.4 ClusterMesh 限制与调试
ClusterMesh 在实际部署中存在一些限制,需要提前了解:
| 限制 | 说明 |
|---|---|
| 跨集群延迟 | 隧道封装增加 ~0.5–2ms 延迟,取决于物理距离 |
| 最大集群数 | 官方测试至 255 个集群,生产建议 ≤ 10 |
| etcd 认证 | 跨集群 etcd 访问需要配置 TLS 证书 |
| 身份冲突 | 不同集群的标签策略必须协调,避免身份 ID 碰撞 |
调试 ClusterMesh 连接问题的常用命令:
# 检查跨集群连通性cilium clustermesh connectivity status
# 查看远程集群的身份同步cilium identity list --cluster
# 检查 etcd 连接状态cilium clustermesh status --verbose六、Cilium 替代 kube-proxy
6.1 替代模式
| 模式 | 说明 |
|---|---|
| disabled | 不替代,保留 kube-proxy |
| partial | 部分 Service 由 eBPF 处理 |
| strict | 完全替代,移除 kube-proxy |
6.2 完全替代的配置
# Helm 安装 Cilium,完全替代 kube-proxyhelm install cilium cilium/cilium \ --set kubeProxyReplacement=strict \ --set hubble.enabled=true \ --set hubble.relay.enabled=true \ --set hubble.ui.enabled=true \ --namespace kube-system完全替代 kube-proxy(strict 模式)需要内核 5.10+ 和 BTF 支持。在生产环境部署前,务必在测试环境验证所有 Service 类型(ClusterIP、NodePort、LoadBalancer、ExternalName)的功能。
七、动手实践
7.1 部署 Cilium
# 使用 Helm 部署 Ciliumhelm repo add cilium https://helm.cilium.io/helm install cilium cilium/cilium \ --set kubeProxyReplacement=partial \ --set hubble.enabled=true \ --namespace kube-system
# 验证 Cilium 状态cilium statuscilium connectivity test7.2 使用 Hubble 可观测性
# 启用 Hubblecilium hubble port-forward&
# 查看实时流量hubble observe --since 1m
# 查看 DROP 事件hubble observe --type drop
# 查看 DNS 查询hubble observe --type l7 --verdict ERROR7.3 Cilium NetworkPolicy
# 创建 CiliumNetworkPolicykubectl apply -f - <<EOFapiVersion: cilium.io/v2kind: CiliumNetworkPolicymetadata: name: l7-rulespec: endpointSelector: matchLabels: app: backend ingress: - fromEndpoints: - matchLabels: app: frontend toPorts: - ports: - port: "80" protocol: TCP rules: http: - method: GET path: "/api/.*"EOF
# 验证策略cilium policy get7.4 故障排查
Cilium 集群的常见问题排查流程:
# 1. 检查 Cilium Agent 状态cilium status
# 2. 查看 eBPF 程序加载情况cilium bpf lb list # Service 负载均衡规则cilium bpf ct list global # 全局连接跟踪表cilium bpf tunnel list # 隧道映射
# 3. 导出连接跟踪表cilium bpf ct dump global
# 4. 查看身份映射cilium bpf identity list7.5 cilium bpf 调试命令参考
| 命令 | 用途 |
|---|---|
cilium bpf lb list | 列出 Service 负载均衡规则 |
cilium bpf ct list global | 查看连接跟踪表 |
cilium bpf ct dump global | 导出完整连接跟踪数据 |
cilium bpf tunnel list | 查看隧道端点映射 |
cilium bpf identity list | 查看 IP → 身份映射 |
cilium bpf policy list | 查看已加载的策略规则 |
cilium bpf endpoint list | 查看端点信息 |
cilium bpf ipcache list | 查看 IP 缓存(含身份和节点信息) |
八、本章小结
上一章建立了eBPF 可观测性工具的认知框架。
| 主题 | 关键要点 |
|---|---|
| 身份安全模型 | 基于标签的身份替代 IP 地址,Pod 重建后策略不变;L7 策略通过 Envoy 集成实现 |
| 身份分配 | SHA256 哈希生成,上限 65535,大规模集群需监控耗尽风险 |
| eBPF 管线 | XDP → TC ingress → 连接跟踪 → 策略 → NAT → 协议栈 → TC egress |
| Egress 路径 | 策略检查 → SNAT → CT 记录 → EDT 速率控制 |
| Bandwidth Manager | EDT 时间戳调度替代传统令牌桶,无锁低延迟 |
| Hubble | 实时网络可观测性,可视化 Pod 间流量 |
| ClusterMesh | 多集群网络,全局身份和跨集群 Service,注意延迟和规模限制 |
| kube-proxy 替代 | eBPF Map 查找替代 iptables 线性匹配 |
| 故障排查 | cilium bpf 系列命令是调试的核心工具 |
支持与分享
如果这篇文章对你有帮助,欢迎支持作者或分享给更多人
部分信息可能已经过时






