Skip to main content

Command Palette

Search for a command to run...

Kubernetes Semaphore:模块化、无侵入的跨集群通信框架

Updated
3 min read

原文:Kubernetes Semaphore: A modular and nonintrusive framework for cross cluster communication

作者:UW Labs

问题

我们有一个环境,其中包含分属三个不同供应商(AWS、GCP 和私有云)的三个集群,我们希望不同集群中运行的应用能够互相通信,以及:

  • 跨集群的 Pod 网络和加密能力;

  • 访问远端 Kubernetes Service 的能力;

  • 用策略来放行远端集群特定应用,使之能够访问本地端点。

我们有一个跨集群的三层网络,这样三个集群的节点就能互相访问了。每个集群都是在各个供应商子网中申请的节点:

  • AWS:10.66.21.0/24

  • GCP:10.22.20.0/24

  • 私有云:10.88.0.0/24

三个集群的 Pod 网络分配如下:

  • AWS:10.2.0.0/16

  • GCP:10.4.0.0/16

  • 私有云:10.6.0.0/16

依赖项

  • Calico CNI:在所有集群中使用 Calico CNI,方案中对 Calico 具有一定依赖;

  • CoreDNS:Semaphore-Service-Mirror 对此有依赖;

  • 跨集群的三层网络。

现有方案

我们对 Istio、Linkerd、Consul 进行了评估,还直接编写了自己的 Envoy Proxy 配置工具。这些方案都能提供上述大部分甚至全部的功能。但是我们认为他们的性价比并不完全适合我们的环境。不同集群之中运行的不同应用构成的网格结构并不总是让人有兴趣的,其中提供的大量功能也无法让所有人受益。我们希望避免使用 Sidecar Proxy,也回避随之而来的额外开销,并确保我们的程序保持尽可能的独立,不受跨集群通信解决方案的影响。

设计

上面既然提到要避开 Sidecar 代理,我们希望用一种对运维人员和用户都较为简单的方式来解决问题。

理想情况下,每个目标都应该以相互隔离的方法来达成——假设用户只是需要对 Pod 通信进行加密,那么只要进行单独的部署即可。对于新用户来说,只需要少量的配置就可以对方案进行试用,并且可以轻松回退。

方案

Kube-Semaphore 是一个轻量级框架,为不同 Kubernetes 集群之间的应用,提供了简单安全的通信能力,并且无需对应用和清单进行修改。

这不是一个服务网格方案,而是要为远端集群提供服务端点和防火墙规则。

方案由三个独立的工具组成

  • Semaphore-Wireguard:负责 Kubernetes 集群之间的流量加密;

  • Semaphore-Service-Mirror:负责在无需外部负载均衡器参与的情况下,将一个集群中的服务暴露到另一个集群之中;

  • Semaphore-Policy:负载在跨集群的 Pod 间通信里创建防火墙规则。

为了小型、轻量和尽可能的安全,这个组件是用 Go 编写的,并使用了 Kubernetes 和 Calico 的客户端。远端集群上的部署内容很小,本地控制器仅需要一系列的 Service Account,满足 Watch 资源的权限需求即可。

路由和加密

Semaphore-Wireguard 负责在不同集群的节点之间进行加密通信,并在本地主机上加入访问远端 Pod 子网的路由。每个集群的每个节点上都会运行一个 WireGuard 管理器,负责节点之间的点到点通信。它负责生成本地密钥并发现所有远端密钥和端点,并配置与所有远程节点的对等关系。此外,它还负责更新本地路由表,以便通过主机的 WireGuard 接口将所有流量导向远程 Pod 子网。因此,Pod 可以利用所有集群中的节点之间创建的 WireGuard 网状结构,触达远程集群上的 Pod。

WireGuard 和 Calico 的集群内通信管理协作,形成了所有集群所有节点之间的网状结构,WireGuard 网络承担了节点之间的通信。

Semaphore WireGuard 部署样例

下图表达了 WireGuard 形成的主机网格,其中的 merit 就是我们的私有集群:

Service

Semaphore-Service-Mirror 是一个控制器,负责在不同 Kubernetes 集群之间复制服务。此处的镜像服务代表的是一个本地服务,其端点处于远端集群。

镜像控制器会在本地集群创建服务,并用远程集群中 Pod 的地址来更新端点列表,最终形成一个 ClusterIP 类型的 Service。

控制器部署样例

例如 AWS 集群上有一个 Service 对象:

$ kubectl --context=aws --namespace=sys-log get service fluentd
NAME      TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)             AGE
fluentd   ClusterIP   10.3.88.18   <none>        8888/TCP,8889/TCP   164d

它包含的端点:

$ kubectl --context=aws --namespace=sys-log get endpoints fluentd
NAME      ENDPOINTS                                                  AGE
fluentd   10.2.3.19:8889,10.2.4.19:8889,10.2.7.18:8889 + 3 more...   164d

镜像控制器会在 semaphore-service-mirror 所在的命名空间 sys-semaphore 中创建对应的 Service 和 Endpoint:

$ kubectl --context=gcp --namespace=sys-semaphore get service | grep fluentd
aws-sys-log-73736d-fluentd   ClusterIP   10.5.184.192   <none>        8888/TCP,8889/TCP   25d

$ kubectl --context=gcp --namespace=sys-semaphore get endpoints | grep fluentd
aws-sys-log-73736d-fluentd   10.2.3.19:8889,10.2.4.19:8889,10.2.7.18:8889 + 3 more...   17d

我们会发现,这个 Service 指向是远程集群:

$ kubectl --context=gcp --namespace=sys-semaphore describe service aws-sys-log-73736d-fluentd | grep Endpoints
Endpoints:         10.2.3.19:8888,10.2.4.19:8888,10.2.7.18:8888
Endpoints:         10.2.3.19:8889,10.2.4.19:8889,10.2.7.18:8889

控制器会监控远端资源,并根据事件进行更新,这样镜像服务就会及时地指向可用的端点。

最后对 CoreDNS 进行配置,就能够更好地进行解析了:

$ drill fluentd.sys-log.svc.cluster.aws
;; ->>HEADER<<- opcode: QUERY, rcode: NOERROR, id: 51067
;; flags: qr aa rd ; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0 
;; QUESTION SECTION:
;; fluentd.sys-log.svc.cluster.aws.     IN      A

;; ANSWER SECTION:
fluentd.sys-log.svc.cluster.aws.        5       IN      A       10.5.184.192

这样我们的 Pod 在无需关注镜像细节的情况下使用友好的服务名称了。

Policy

Semaphore-Policy 是一个用于创建防火墙策略的组件,用于限制来自远端集群的访问。这个组件会创建用于 Calico 网络策略的 IP 组,来定义允许发起的流量。控制器的唯一任务就是根据标签选择器来监控远端集群的 Pod,然后根据监控结果在本地创建 NetworkSets。接下来,可以使用简单的标签来描述 Calico Network Policy,方便地实现跨集群防火墙规则。

策略控制器部署样例

假设 GCP 集群中存在如下部署:

$ kubectl --context=gcp --namespace=sys-log get po -o wide -l policy.semaphore.uw.io/name=forwarder
NAME              READY   STATUS    RESTARTS   AGE     IP          NODE                                      NOMINATED NODE   READINESS GATES
forwarder-4jdm6   1/1     Running   0          3d20h   10.4.1.3    worker-k8s-exp-1-4l87.c.uw-dev.internal   <none>           <none>
forwarder-6ztl4   1/1     Running   0          3d20h   10.4.0.13   worker-k8s-exp-1-2868.c.uw-dev.internal   <none>           <none>
forwarder-klxdc   1/1     Running   0          4h27m   10.4.4.2    master-k8s-exp-1-j5f8.c.uw-dev.internal   <none>           <none>
forwarder-m9k27   1/1     Running   0          4h27m   10.4.5.2    master-k8s-exp-1-fc0b.c.uw-dev.internal   <none>           <none>
forwarder-n6nsn   1/1     Running   0          4h27m   10.4.3.3    master-k8s-exp-1-31rv.c.uw-dev.internal   <none>           <none>
forwarder-n8vnj   1/1     Running   0          3d20h   10.4.2.4    worker-k8s-exp-1-mdd7.c.uw-dev.internal   <none>           <none>

这是一个 sys-log 命名空间里名为 forwarder 的 DaemonSet。为了让控制器在远程集群中创建所需资源,需要给这个 Daemonset 中的 Pod 加入标签 policy.semaphore.uw.io/name=forwarder。加入标签之后,AWS 集群中的控制器就会创建对应的 GlobalNetworkSet

$ kubectl --context=aws describe GlobalNetworkSet gcp-sys-log-forwarder
Name:         gcp-sys-log-forwarder
Namespace:
Labels:       managed-by=semaphore-policy
              policy.semaphore.uw.io/cluster=gcp
              policy.semaphore.uw.io/name=forwarder
              policy.semaphore.uw.io/namespace=sys-log
Annotations:  projectcalico.org/metadata: {"uid":"c7569765-a47d-424c-9533-80e4a7c201d6","creationTimestamp":"2021-04-09T15:04:43Z"}
API Version:  crd.projectcalico.org/v1
Kind:         GlobalNetworkSet
Spec:
  Nets:
    10.4.5.2/32
    10.4.4.2/32
    10.4.1.3/32
    10.4.0.13/32
    10.4.3.3/32
    10.4.2.4/32
Events:  <none>

这个组合包含了远端对象的 IP 地址,可以用于 Calico 的网络策略,定义允许进入的流量:

apiVersion: crd.projectcalico.org/v1
kind: NetworkPolicy
metadata:
  name: allow-to-fluentd
spec:
  selector: app.kubernetes.io/name == 'fluentd'
  types:
    - Ingress
  ingress:
    - action: Allow
      protocol: TCP
      source:
        selector: >-
          policy.semaphore.uw.io/name == 'forwarder' &&
          policy.semaphore.uw.io/namespace == 'sys-log' &&
          policy.semaphore.uw.io/cluster == 'gcp'
        namespaceSelector: global()
      destination:
        ports:
          - 8889

上边的规则允许来自远端 forwarder 到本地 fluentd 的访问。

后记

这套东西对我们来说很有用,但是它的局限性也是显而易见的——如果恰巧适用于读者的环境和需求,那自然很好;如果不是,也希望读者在本文中得到一点启发。

没有 Calico 和 WireGuard,这个方案可能就难于落地了,方案的复杂部分主要是由这两个项目完成的,也正因为此,我们对我们的方案充满信心,这里对他们致以崇高敬意。

相关链接

  • Semaphore WireGuard:https://github.com/utilitywarehouse/semaphore-wireguard

  • Semaphore WireGuard 部署示例:https://github.com/utilitywarehouse/semaphore-wireguard/tree/main/deploy/example

  • Semaphore Service Mirror:https://github.com/utilitywarehouse/semaphore-service-mirror

  • Semaphore Service Mirror 部署示例:https://github.com/utilitywarehouse/semaphore-service-mirror/tree/master/deploy/example

  • Semaphore Policy:https://github.com/utilitywarehouse/semaphore-policy

  • Semaphore Policy 部署示例:https://github.com/utilitywarehouse/semaphore-policy/tree/main/deploy

More from this blog

龙虾恐慌:AIOps 又要改名了?

ChatGPT 开始,把 AI 拉近到普罗大众的面前,让无数人感受到 AI 的亲民魅力。而龙虾,则把大模型驱动的自动化能力,突然间变得水灵灵、活泼泼地走进千家万户。它不只是“风口上的猪”,而是风口本身。热度高到让 Mac mini 一度断货,不知道这在不在库克的预料之内。 每代人都有每代人的鸡蛋,春节期间,我就领了我的鸡蛋。翻出古老的 MacBook Air M1,充值各种大模型。当然了,这个工具

Mar 9, 20261 min read

再见 2025

我猜不少人以为这个号废了吧?并没有,只是今年变化有点大,一直有种抄起键盘,无从说起的感觉,所以一直偷懒到今天,2025 的最后一天。 今年是我的第四个本命年,去年末一期播客里,大内说本命年不是灾年,是变化年,有危也有机。可是讲真啊,只看到危,没看到机。 各种因缘际会,从鹅厂跳槽到前东家,已经接近四年,第一个合同期已经进入尾声。除了前两年还在云原生领域嗷嗷叫,后两年基本都是些鸡零狗碎的东西了,用老东家的术语说是——偏离主航道,可谓是前景暗淡了。 一旦确定要滚蛋,反倒心思轻松起来,每天骑着我的小红车...

Jan 5, 20261 min read

辅助编程?dora 说:我知道你很急可是请你别急

从 OpenGPT 把大模型的火烧旺了之后,这三年来,相信很多组织或摩拳擦掌、或躬身入局,希望借助聪明能干的大模型,或想偿还技术宅,或想降本增效,或想弯道超车。一时间,沉寂许久的 AIxx 又活过来了,LLM Ops、Vibe Coding、中医大模型、GPT 算命等等,全都老树发新芽,焕发了勃勃生机。那么视角拉回从业者最关注的饭碗相关的领域之一——AI 辅助开发,产生了什么触动,应该如何拥抱呢? DORA 的年度报告中给出了很有意思的结论——强者恒强。 执行摘要部分总结了几个有趣的点: 问题...

Oct 6, 20251 min read

[译]dora:ai 辅助软件开发状态报告

执行摘要 在 2025 年,科技领导者面临的核心问题已不再是“是否要采用 AI”,而是“如何实现其价值”。 DORA 的研究基于超过 100 小时的定性访谈和来自全球近 5,000 名技术专业人士的问卷调查。研究揭示了一个关键事实:AI 在软件开发中的主要角色是“放大器”。它会放大高效能组织的优势,也会凸显组织的缺陷。 关键结论:AI 是放大器 AI 投资的最大回报并非来自工具本身,而是来自组织底层系统的战略性建设: 高质量的内部平台 清晰的工作流 团队的协同能力 缺少这些基础,AI ...

Oct 2, 202514 min read

僭越了,有人在用 Rust 写 Kubernetes

一个新语言问世,最爱做的事情之一,就是重写存量软件了。 云原生喝酒 SIG 重点扶持项目——rk8s(https://github.com/rk8s-dev/rk8s) 也可以归在这个范畴里,只不过这个项目重写的东西比较大,是 Kubernetes。 从 2025 年 1 月第一个 Commit 开始,到现在有了 200 多次 Commit,十几万行代码。当然距离 Kubernetes 的几百万行代码还差得远——老马就是喜欢整这种大无畏项目。 另外该项目也是国内第一个脱离 Cargo 转向使用 ...

Sep 27, 20253 min read

【伪】架构师

342 posts