资讯动态

Cilium Cluster Mesh 全局服务(Global Services)指南:跨 Kubernetes 集群的服务发现与负载均衡

发布时间:2026/9/14 8:02:01 来源:尧图企业网站定制
Cilium Cluster Mesh 全局服务Global Services指南跨 Kubernetes 集群的服务发现与负载均衡【免费下载链接】ciliumeBPF-based Networking, Security, and Observability项目地址: https://gitcode.com/GitHub_Trending/ci/cilium导读本文是 Cilium Cluster Mesh 的 Global Services 实战指南讲解如何通过 Kubernetes 注解annotation把多个集群中同名同命名空间的 Service 声明为全局服务从而让 Cilium 自动在多个集群的后端 Pod 之间进行跨集群负载均衡与服务发现。读完本文你将掌握service.cilium.io/global、service.cilium.io/shared、service.cilium.io/global-sync-endpoint-slices三类注解的语义与组合效果、EndpointSlice 跨集群同步Beta的开启方式、不可达集群的缓存 TTL 治理方案以及 Global Services 的已知限制与规避手段并能在自己的 Cluster Mesh 环境中直接复现部署示例。前置条件可用的 Cluster MeshGlobal Services 是 Cluster Mesh 之上的一层能力因此动手之前必须先有一个运行正常的 Cluster Mesh 环境。请先按照仓库内的 Cluster Mesh 安装与配置指南 完成集群网格的搭建与拨号验证确保多个集群之间能够互相发现服务。只有集群间共享了服务信息Global Services 的跨集群负载均衡才有数据基础。用 Global Services 实现跨集群负载均衡核心思路同名服务 全局注解跨集群负载均衡的实现方式非常简洁在每个集群中定义一个名称与命名空间完全相同的 Kubernetes Service并加上注解service.cilium.io/global: true将其声明为全局服务。Cilium 随即会跨集群收集该服务的后端 Pod并在所有集群的后端之间自动执行负载均衡。以下是一个最小可用的全局服务定义原文档示例apiVersion: v1 kind: Service metadata: name: rebel-base annotations: service.cilium.io/global: true spec: type: ClusterIP ports: - port: 80 selector: name: rebel-base将该 YAML 分别应用到两个或多个已加入同一 Cluster Mesh 的集群后任意集群中访问rebel-base:80的流量都会被 Cilium 分发到所有集群里匹配name: rebel-base标签的 Pod 上。注解在源码中的定义这些注解并非魔法字符串而是由 Cilium 源码统一定义和维护的。在 pkg/annotation/k8s.go 中可以找到它们的完整定义与语义注释// GlobalService / GlobalServiceAlias if set to true, marks a service to // become a global service. GlobalService ServicePrefix /global GlobalServiceAlias Prefix /global-service // GlobalServiceSyncEndpointSlice if set to true, marks a service to // synchronize remote clusters endpoint slices to the local Kubernetes API GlobalServiceSyncEndpointSlices ServicePrefix /global-sync-endpoint-slices // SharedService / SharedServiceAlias if set to false, prevents a service // from being shared, the default is true if GlobalService is set, otherwise // false. Setting the annotation SharedService to false while setting // GlobalService to true allows to expose remote endpoints without // sharing local endpoints. SharedService ServicePrefix /shared SharedServiceAlias Prefix /shared-service值得注意的两点每个注解都带有一个历史别名Alias例如service.cilium.io/global的别名为io.cilium/global-service便于旧版本兼容源码注释明确给出了shared注解的默认行为只要设置了globalshared默认为 true。底层的全局服务缓存从源码结构看跨集群服务信息的汇聚发生在 pkg/clustermesh/common/services.goGlobalService结构体按集群名保存每个集群的ClusterService而GlobalServiceCache以NamespacedName为键管理所有全局服务type GlobalService struct { ClusterServices map[string]*serviceStore.ClusterService } type GlobalServiceCache struct { logger *slog.Logger mutex lock.RWMutex byName map[types.NamespacedName]*GlobalService }GlobalServiceCache.OnUpdate负责把来自各集群含本地集群的服务更新合并进缓存OnDelete负责在某个集群删除服务时摘除对应条目。Cilium 的数据路径BPF 负载均衡正是基于这份合并后的全局视图进行跨集群转发决策的。相关的转换与过滤逻辑位于NewSharedServicesObserverpkg/clustermesh/common/services.go它会只把Shared true的远程服务纳入全局缓存非共享服务更新会被直接忽略——这正好与下文禁用共享的语义一一对应。禁用全局服务的后端共享为什么需要关闭共享默认情况下全局服务会跨集群共享后端——每个集群都能看到其他集群暴露的后端。如果你只希望单向暴露让本集群消费其他集群的后端但不把本集群的后端共享出去就需要显式把service.cilium.io/shared设置为false。下面的示例原文档提供声明了一个全局服务但它只暴露远程端点、不共享本地端点apiVersion: v1 kind: Service metadata: name: rebel-base annotations: service.cilium.io/global: true service.cilium.io/shared: false spec: type: ClusterIP ports: - port: 80 selector: name: rebel-base结合源码看当shared: false时该集群的ClusterService会以Shared: false的身份进入网格NewSharedServicesObserver会将其从其他集群的全局缓存中过滤掉pkg/clustermesh/common/services.go从而实现了远端可见、本地不出网的效果。运行时动态调整global与shared注解都可以在服务存续期间动态增删无需重建 Service。例如在集群 1 中临时关闭共享kubectl annotate service rebel-base service.cilium.io/sharedfalse --overwrite恢复共享则删除该注解让默认值true重新生效kubectl annotate service rebel-base service.cilium.io/shared-同步跨集群 EndpointSliceBeta适用场景默认情况下非 Headless 的全局服务不会同步 EndpointSlice。只有当你需要让 DNS 或第三方控制器例如非 Cilium 的 Ingress Controller发现远端集群的端点时才需要为服务开启 EndpointSlice 同步metadata: annotations: service.cilium.io/global: true service.cilium.io/global-sync-endpoint-slices: true行为差异总结如下服务类型默认行为显式控制方式非 Headless 全局服务不同步加注解service.cilium.io/global-sync-endpoint-slices: true开启Headless 全局服务clusterIP: None默认开启同步加注解service.cilium.io/global-sync-endpoint-slices: false显式关闭需要澄清的是该功能不服务于 Cilium 自身的其他功能也不被它们依赖——例如 Cilium Ingress Controller 在不开启该功能的情况下也能在 Cluster Mesh 中正常工作。它只解决第三方控制器需要从 Kubernetes API 读取远端 EndpointSlice这一需求。通过特性开关安装与启用该功能当前由特性开关控制、默认关闭。安装 Cilium 时开启cilium install --namespace kube-system \ --set clustermesh.enableEndpointSliceSynchronizationtrue对已有的 Cilium 安装启用并重启 operator 使配置生效cilium upgrade --namespace kube-system \ --set clustermesh.enableEndpointSliceSynchronizationtrue \ --reuse-values kubectl -n kube-system rollout restart deployment/cilium-operator已知限制该功能仍处于Beta阶段可能遇到缺陷或能力欠缺主机名原样同步没有任何冲突消解机制多个 StatefulSet 如果共用一个治理 Servicegoverning Service并跨集群同步 EndpointSlice它们的名称必须不同。官方建议直接把集群名拼进 StatefulSet 名称例如用cluster1-my-statefulset代替my-statefulset。完整示例部署一个跨集群的 rebel-base 服务仓库的 examples/kubernetes/clustermesh/ 目录提供了可直接运行的演示资源其中cluster1.yaml与cluster2.yaml是两个集群的差异化部署清单各含rebel-base工作负载、x-wing客户端以及标识本集群身份的 ConfigMapglobal-service-example.yaml则是全局服务定义含普通全局服务和 Headless 全局服务各一个。核心内容如下# global-service-example.yaml节选 apiVersion: v1 kind: Service metadata: name: rebel-base annotations: service.cilium.io/global: true spec: type: ClusterIP ports: - port: 80 selector: name: rebel-base --- apiVersion: v1 kind: Service metadata: name: rebel-base-headless annotations: service.cilium.io/global: true service.cilium.io/global-sync-endpoint-slices: true spec: type: ClusterIP clusterIP: None ports: - port: 80 selector: name: rebel-base操作步骤在集群 1 部署工作负载与全局服务kubectl apply -f examples/kubernetes/clustermesh/cluster1.yaml kubectl apply -f examples/kubernetes/clustermesh/global-service-example.yaml在集群 2 重复部署清单内容一致仅 ConfigMap 中的集群标识不同kubectl apply -f examples/kubernetes/clustermesh/cluster2.yaml kubectl apply -f examples/kubernetes/clustermesh/global-service-example.yaml从任意集群访问全局服务观察返回内容kubectl exec -ti deployment/x-wing -- curl rebel-base由于两个集群的rebel-basePod 都会以不同的{Cluster: Cluster-1/Cluster-2}内容应答你会看到来自两个集群Pod 的交替回复——这就是跨集群负载均衡的直接证据。在集群 1 关闭共享kubectl annotate service rebel-base service.cilium.io/sharedfalse --overwrite从集群 1 再次访问由于集群 1 仍能消费远端端点你依然会看到两个集群的回复。从集群 2 访问此时集群 1 的后端已不再共享给集群 2因此只会看到集群 2 自己Pod 的回复。在集群 1 删除shared注解恢复默认共享kubectl annotate service rebel-base service.cilium.io/shared-从任意集群访问两个集群的回复再次交替出现全局负载均衡恢复。Global 与 Shared 组合行为参考当同一个服务存在于两个集群Cluster1 与 Cluster2时service.cilium.io/global与service.cilium.io/shared的取值组合决定了各集群实际使用的端点集合。原文档用下面的流程图总结了全部组合的最终效果终止节点表示该组合下两个集群各自使用的端点各组合的结果可以归纳为两集群都global: true、且都shared: true双方都使用本地 远端端点Cluster1shared: falseCluster1 只使用本地端点Cluster2 仍使用本地 远端端点即 Cluster1 的远端可见性被切断双方都shared: false两个集群都只使用各自的本地端点任一集群不是global两个集群都只使用本地端点全局能力整体失效。这与源码中SharedService注解的注释语义完全一致shared默认值为 true当设置了global时设为 false 则阻止本集群后端被共享。处理不可达集群缓存 TTL问题陈旧缓存的幽灵后端默认情况下如果某个远端集群失联Cilium 会在缓存中保留最后一次看到的服务信息。这会导致流量被继续发送到陈旧或已不可达的后端上。解决方案配置缓存 TTL可以配置一个缓存 TTLclustermesh.cacheTTL远端集群连接断开后如果在 TTL 时间内没有重新建立连接Cilium 就会自动吊销该集群的缓存数据。对全局服务而言这意味着Cilium 将停止向不可达集群中的服务后端分发流量待连接恢复后远端服务重新填充缓存负载均衡自动恢复。默认值为0s即关闭该特性、缓存永不吊销启用方式把clustermesh.cacheTTL设为大于零的时长例如15m。cilium upgrade --namespace kube-system \ --set clustermesh.cacheTTL15m \ --reuse-values源码视角TTL 检查器如何工作TTL 机制在源码中有完整实现。配置项定义于 pkg/clustermesh/common/config.go对应的 CLI flag 为--clustermesh-cache-ttl默认值0永不吊销flag 帮助文本明确说明若未指定或设为 0s缓存永不吊销flags.Duration(clustermesh-cache-ttl, def.ClusterMeshCacheTTL, The time to live for the cache of a remote cluster after connectivity is lost. If the connection is not re-established within this duration, the cached data is revoked to prevent stale state. If not specified or set to 0s, the cache is never revoked.)连接断开时Cilium 会创建cacheTTLCheckerpkg/clustermesh/common/remote_cluster.go并启动倒计时newTTLChecker在 pkg/clustermesh/common/clustermesh.go 中被接入远端集群生命周期。TTL 到期且连接未恢复时触发onExpiration回调从全局缓存中移除该集群的服务数据使数据路径立即停止向该集群后端转发。这正是失联集群自动摘除、恢复后自动重新填充的底层实现。已知限制与规避方案原文档明确了以下限制规划架构时需要提前考虑Global NodePort 服务的限制只有将 Cilium 配置为替换 kube-proxykubeProxyReplacementtrue时Global NodePort 服务才会同时负载均衡到本地与远端后端否则通过 NodePort 访问时只有本地后端参与负载均衡。宿主机网络访问的限制由 Node 或运行在宿主机网络命名空间host network中的 Pod 访问全局服务时同样只有在kubeProxyReplacementtrue的情况下才能跨集群负载均衡。该限制可以通过在宿主机命名空间启用 SocketLB 来规避cilium install --namespace kube-system \ --set socketLB.enabledtrue \ --set socketLB.hostNamespaceOnlytrue否则这类流量只能命中本地后端。进阶方向Global Services 还支持**服务亲和性Service Affinity**控制通过注解service.cilium.io/affinity取值local、remote、none可以表达端点偏好例如优先使用本集群端点以减少跨集群延迟。其定义同样位于 pkg/annotation/k8s.go详细配置说明见 Cluster Mesh 服务亲和性指南。此外多集群服务MCS-API是另一条基于标准 API 的跨集群服务方案可参考 MCS-API 文档 对比选型。总结本文围绕 Cilium Global Services 展开覆盖了从最小配置、单向共享、EndpointSlice 同步、缓存 TTL 到限制规避的完整实践链路。核心要点回顾声明即用同名服务 service.cilium.io/global: true即可获得跨集群负载均衡共享可控service.cilium.io/shared: false可阻断本集群后端外泄实现单向消费第三方集成靠 EndpointSlice 同步Beta 功能按需开启注意 StatefulSet 命名冲突失联自治合理设置clustermesh.cacheTTL避免向不可达集群后端继续分发流量限制明确NodePort 与宿主机网络流量需kubeProxyReplacementtrue必要时配合宿主机命名空间 SocketLB。以上每一项均有仓库内文档与源码实现支撑注解语义见 pkg/annotation/k8s.go缓存实现见 pkg/clustermesh/common/services.goTTL 配置见 pkg/clustermesh/common/config.go可运行示例见 examples/kubernetes/clustermesh/感兴趣的读者可以直接基于这些路径深入阅读与复现。【免费下载链接】ciliumeBPF-based Networking, Security, and Observability项目地址: https://gitcode.com/GitHub_Trending/ci/cilium创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价