Cilium Cluster Mesh 多集群实操:启用流程、Global Service 与 Native Routing 注意点
Cilium Cluster Mesh 把多个以 Cilium 为 CNI 的 Kubernetes 集群在网络上组成统一网格,跨集群 Pod 可以像同集群内一样直接通信。相比 Istio 多集群方案,它工作在更底层的网络层,基于 eBPF 转发,性能开销更低。
工作方式与故障域边界
每个集群仍然维护自己的 etcd,状态不混。集群通过 clustermesh-apiserver 对外提供配置,该组件内部包含两个容器:apiserver 负责写入集群信息,etcd 容器作为代理暴露给其它集群。对端集群的 Cilium Agent 连接这个 etcd 代理来监听本集群的变化。
关键点是跨集群访问始终是只读的,所以一个集群的故障不会通过状态同步扩散到其它集群。
启用 Cluster Mesh
以 kind 两个集群 kind-c1、kind-c2 为例:
cilium clustermesh enable --create-ca --context kind-c1 --service-type LoadBalancer
cilium clustermesh enable --context kind-c2 --service-type LoadBalancer
cilium clustermesh connect --context kind-c1 --destination-context kind-c2
--create-ca 只在第一个集群上执行。两个集群必须共享同一组 CA 证书,否则 mTLS 建立不起来。
启用前需要满足几个条件:
- 每个集群分配唯一的
cluster.id(范围 1-255)和cluster.name - Cilium 使用 etcd 作为 KV 存储
- 集群之间的网络必须互通
全局 Service 与本地优先
要让 Service 在 Cluster Mesh 内做跨集群负载均衡,给它加上注解:
apiVersion: v1
kind: Service
metadata:
name: demo
namespace: default
annotations:
io.cilium/global-service: "true"
service.cilium.io/affinity: local
spec:
selector:
app: demo
ports:
- port: 80
前提是两个集群中 Service 的名称和命名空间必须完全一致。加注解后,从任一集群访问该 Service,流量会自动分发到两边集群的后端 Pod。
如果希望跨集群场景下的流量尽量留在本地,用另一个注解控制亲和性:
service.cilium.io/affinity: local|remote|none
设为 local 时,全局 Service 优先在健康的本地后端之间负载均衡;只有当本地后端全部不可用时,才会把请求转发给远程端点。这个策略主要用来避免跨集群远程调用带来的额外延迟。
跨集群网络策略
Cluster Mesh 场景下的跨集群访问控制需要用 CiliumNetworkPolicy。它支持通过集群标签精确选择来源和目标,例如只允许 cluster1 中带 x-wing 标签的 Pod 访问 cluster2 中带 rebel-base 标签的 Pod。这类策略使用 io.cilium.k8s.policy.cluster: cluster1 之类的标签来匹配流量来自哪个集群。
这里有两点容易踩:
- Kubernetes 原生
NetworkPolicy不会自动同步到所有集群,必须在每个集群都部署相同的策略 - 如果策略没有放行 DNS 流量,跨集群通过 Service 域名访问会直接失败
数据路径与 Native Routing 的代价
跨集群流量在数据包进入 Pod 网络接口时就开始处理。在 veth-pair 的 tc ingress hook 上,Cilium 直接把 Global Service 的 IP 转换为最终目标 Pod 的 IP。
数据路径支持隧道(Tunneling)和原生路由(Native Routing)两种模式。如果选择 Native Routing,先决条件比较严格:
- 各成员集群内部网络模式必须是 Native Routing
- 所有集群的 PodCIDR 必须被
ipv4NativeRoutingCIDR覆盖 - 任何目标地址不在该 CIDR 范围内的流量,会被 Cilium 做 SNAT,伪装成节点 IP 发出
大规模流量下,SNAT 涉及 conntrack 表维护和地址转换,会带来明显的性能损耗,这是原生路由模式下最需要关注的取舍。
另外,底层网络必须具备直接处理 Pod 到 Pod 流量的能力。如果需要跨集群路由,可以将各集群的 Cilium Agent 作为 BGP Speaker,向路由反射器宣告各自集群的 PodCIDR。
参考
- 项目:https://github.com/cilium/cilium
- 文档:https://docs.cilium.io/en/stable/network/clustermesh/