饮墨

子安饮墨馀三斗,留与卿儿作赋来

Kubernetes 多集群服务发现:Submariner vs Skupper vs Cilium ClusterMesh 生产选型指南

16 views

痛点:多集群互通的现实困境

随着业务规模扩大,单一 Kubernetes 集群已难以满足需求。多云部署、异地容灾、环境隔离都催生了多集群架构。但问题随之而来:集群 A 的 Pod 如何访问集群 B 的 Service?

传统方案要么走公网 + LoadBalancer(成本高、延迟大),要么手动维护 VPN + DNS(运维复杂、易出错)。社区涌现了三款主流方案:Submariner、Skupper、Cilium ClusterMesh。本文基于生产实践,给出选型建议。

方案对比:三大工具核心差异

特性 Submariner Skupper Cilium ClusterMesh
网络层 L3 隧道(IPsec/WireGuard) L7 应用层代理 L3 eBPF 直连
CNI 依赖 兼容主流 CNI CNI 无关 必须 Cilium
Service 发现 ServiceExport CRD 自动 Service 镜像 原生 Service 同步
安装复杂度 中等(需 Broker) 低(纯应用层) 高(需统一 CNI)
性能 中等(隧道开销) 较低(7 层代理) 最优(eBPF 直通)
适用场景 异构 CNI 多集群 轻量跨集群通信 Cilium 统一环境

实操步骤:三种方案快速部署

方案一:Submariner — 异构 CNI 的通用解

Submariner 通过 Broker 集群协调多个成员集群,建立 IPsec/WireGuard 隧道。

# 1. 安装 subctl CLI
curl -Ls https://get.submariner.io | bash
export PATH=$PATH:~/.local/bin

# 2. 在 Broker 集群部署(通常选一个集群充当)
subctl deploy-broker --kubeconfig kubeconfig-broker

# 3. 将成员集群加入
subctl join --kubeconfig kubeconfig-cluster-a broker-info.subm \
  --clusterid cluster-a --natt=false

subctl join --kubeconfig kubeconfig-cluster-b broker-info.subm \
  --clusterid cluster-b --natt=false

# 4. 导出 Service 供跨集群访问
kubectl --kubeconfig kubeconfig-cluster-a apply -f - <<EOF
apiVersion: multicluster.x-k8s.io/v1alpha1
kind: ServiceExport
metadata:
  name: my-service
  namespace: default
EOF

# 5. 在 cluster-b 通过 clusterset 域名访问
# my-service.default.svc.clusterset.local

方案二:Skupper — 零 CNI 依赖的轻量方案

Skupper 基于 AMQP 协议在应用层建立 Virtual Application Network,无需改动网络层。

# 1. 安装 Skupper CLI
curl https://skupper.io/install.sh | sh

# 2. 在 cluster-a 初始化
kubectl config use-context cluster-a
skupper init --site-name cluster-a

# 3. 生成连接令牌
skupper token create cluster-a-token.yaml

# 4. 在 cluster-b 连接
kubectl config use-context cluster-b
skupper init --site-name cluster-b
skupper link create cluster-a-token.yaml

# 5. 暴露 Service
kubectl config use-context cluster-a
skupper expose deployment/my-app --port 8080

# cluster-b 自动获得 my-app Service,直接访问

方案三:Cilium ClusterMesh — 性能最优解

如果所有集群都使用 Cilium CNI,ClusterMesh 提供原生级别的跨集群通信。

# 前提:所有集群已安装 Cilium,且 Pod CIDR 不重叠

# 1. 启用 ClusterMesh
cilium clustermesh enable --context cluster-a
cilium clustermesh enable --context cluster-b

# 2. 建立连接
cilium clustermesh connect --context cluster-a \
  --destination-context cluster-b

# 3. 验证状态
cilium clustermesh status --context cluster-a

# 4. 创建 Global Service(两端都可访问)
kubectl --context cluster-a annotate service my-service \
  service.cilium.io/global="true"

三个常见坑

坑一:Pod CIDR 冲突导致路由黑洞

现象:跨集群访问时丢包或路由到本地。

原因:两个集群的 Pod CIDR 重叠(如都用默认 10.244.0.0/16)。

解决: - 部署前规划 CIDR,每个集群使用独立网段 - Submariner 支持 Globalnet 做 NAT 转换,但会增加复杂度

# 集群规划示例
cluster-a: Pod CIDR 10.1.0.0/16, Service CIDR 172.21.0.0/16
cluster-b: Pod CIDR 10.2.0.0/16, Service CIDR 172.22.0.0/16

坑二:防火墙阻断隧道端口

现象:subctl diagnose 报 Gateway 连接失败。

原因:云厂商安全组未放行隧道端口。

解决:

# Submariner 需要放行的端口
# IPsec: UDP 500, 4500
# WireGuard: UDP 4800 (默认)
# VXLAN: UDP 4800

# AWS 安全组示例
aws ec2 authorize-security-group-ingress \
  --group-id sg-xxx \
  --protocol udp --port 4500 \
  --source-group sg-yyy

坑三:Skupper 高流量下性能瓶颈

现象:跨集群调用延迟突增,Skupper Router Pod CPU 飙高。

原因:Skupper 是 L7 代理,每个请求都经过 Router,高 QPS 场景成瓶颈。

解决: - 增加 Router 副本数:skupper update --routers 3 - 高性能需求切换到 Submariner 或 ClusterMesh

生产选型建议

场景 推荐方案
CNI 异构(如 Calico + Flannel 混用) Submariner
快速验证 / 开发测试环境 Skupper
全 Cilium 环境追求极致性能 ClusterMesh
跨云厂商(AWS + 阿里云) Submariner + WireGuard
只需少量 Service 互通 Skupper(最简单)

总结

多集群服务发现没有银弹。Submariner 胜在通用性,Skupper 胜在简单,Cilium ClusterMesh 胜在性能。选型核心看三点:

  1. CNI 是否统一 — 统一 Cilium 就上 ClusterMesh
  2. 性能要求 — 高 QPS 排除 Skupper
  3. 运维复杂度容忍度 — 怕麻烦先试 Skupper

生产环境建议先在非关键业务验证,重点监控跨集群延迟和隧道稳定性。多集群是趋势,选对工具事半功倍。

分享:

相关文章