是否选择多集群——使用服务网格的集群间通信

是否该使用服务网格构建多集群?本文会给你答案。

作者 Andrew Jenkins 译者 宋净超(Jimmy Song) 发表于 2021年3月31日

本文翻译自 To Multicluster, or Not to Multicluster: Inter-Cluster Communication Using a Service Mesh。Istio 服务网格是解决 Kubernetes 集群间通信的一个关键,虽然翻译这篇文章距离原文发表也有快 2 年时间了,但是其中的很多观点仍不过时。

主要观点

  • Kubernetes 已经成为容器编排的事实标准,许多组织都运行着多个集群。集群内的通信是一个解决了的问题,但是跨集群的通信需要更多的设计和操作开销。
  • 在决定是否实施多集群支持之前,你应该了解你的通信用例。
  • 你还应该确定你想要从解决方案中获得什么(单一界面的观察性、统一信任域等),然后制定一个关于如何实现这些的计划。
  • 有几种多集群服务网格方法,如共同管理、集群感知服务通过网关路由、扁平网络和 split-horizon 端点发现服务(EDS)。
  • Istio 有现有的多集群支持,在 1.1 中还有额外的新功能,甚至未来还会有更多的功能出现。

Kubernetes 已经成为企业中容器编排的事实标准。这是有充分理由的 —— 它提供了一系列功能,使管理容器化应用变得更加容易。Kubernetes 也带来了一些新的挑战,一个主要的挑战就是需要部署和管理多个 Kubernetes 集群,以便有效地管理大规模分布式系统。

想象一下,你已经设计和编码了一个应用,并且你已经构建了容器 —— 你只需要运行它们。从代码到运行应用是令人振奋的,但正如任何构建了容器化应用的人所知道的那样,它并不像乍看起来那样简单。在部署到生产之前,有各种开发 / 测试 / 阶段周期。此外,还有一个扩展方面的问题 —— 你的生产应用可能需要在许多不同的地方运行,原因包括水平扩展性、弹性或接近最终用户。

环境越多,(集群)问题越多

即使是一个简单的绿地应用概念,最终也需要多个部署环境。如果你正在迁移一个现有的应用,你一定会遇到更多的挑战,比如不同的安全域,不同的组织 / 计费,以及对一个云供应商的机器学习工具包的亲和力。

解决这个问题最常见的方法是创建多个 Kubernetes 集群,每个集群都致力于在其特定环境中运行你的应用组件。在高安全领域,你将广泛使用基于角色的访问控制(RBAC),并具有审计功能。测试环境应该重现很多生产行为,但要为便于调试和检查而定制。对于你的开发环境…… 好吧,也许你像我一样,你就打开 Docker 偏好设置,然后勾选 Kubernetes 框。易用性和短暂性是常态。

你很可能最终会有多个 Kubernetes 集群,每个集群都会托管微服务。集群中这些微服务之间的通信可以通过服务网格来加强。在集群内部,Istio 提供了通用的通信模式来提高弹性、安全性和可观察性。那么集群之间和跨集群呢?

运行多个 Kubernetes 集群并不一定可怕,但运行多个集群确实需要你考虑它们如何通信和交互,以便轻松交付运行在上面的优秀应用。像 Istio 这样的服务网格可以让多集群通信变得毫无痛苦。Istio 拥有多集群支持,在 1.1 中增加了新功能,并计划在未来增加更多的功能。团队也应该考虑采用服务网格来简化跨多个集群的通信。

常见的使用案例

运行多集群服务网格最常见的是这些用户需求。

  • 由于我的组织规模,我有多个集群,我想在一个地方查看和管理它们。我的集群一般不做集群间的流量,或者当它们做的时候,是通过定义好的 API。
  • 我有多个集群以实现高可用性,它们是彼此的克隆,如果一个集群发生故障,另一个集群可以接管,这一点非常重要。
  • 我有多个集群,它们组合成一个更高级别的应用。其中一个集群中的微服务需要与另一个集群中的微服务进行通信,以提供适当的端到端应用体验。

第三类多集群需要集群间的流量。如果你想要集群间流量支持,你的实现将取决于集群之间的网络,以及你对容错的要求。

你能从多集群中得到什么?

当你考虑多集群和服务网格时,你应该从确定你想要什么开始,然后转移到如何获得它。

单一界面

你的多个服务网格从一个地方操作。你可以在一个单一的接口中查看所有集群的配置、指标和跟踪。

统一信任域

你使用服务网格来提供工作负载识别,并由强大的 mTLS 加密保护。这种零信任模型比基于源 IP 等拓扑信息来信任工作负载更好:你依靠的是它们是什么的加密证明,而不是脆弱的外围堆栈来控制它们的来源。

统一的信任域意味着所有的工作负载都可以通过绑定到一个共同的信任根来相互认证(它们是什么)。服务网格控制平面都是为这个共同的信任根配置的,无论这些平面有一个还是几个。

独立的故障域

一个不依赖其他集群和相关基础设施,本身就可以正常运行的集群是一个独立的故障域。我是把服务网格列为相关基础设施 —— 如果你要安装服务网格,你是为了把通信弹性转移到应用下面的基础设施层。如果一个集群中的服务网格的故障可以破坏另一个集群中的服务网格,那么它就不能算是一个独立的故障域。

集群间的流量

如果你想让一个集群中的服务与另一个集群中的服务直接通信,并且你想让这种通信具有服务网格的好处,如高级路由、可观察性或透明加密,那么你需要集群之间的流量保持为服务网格的一部分。换句话说,你希望你的东/西流量离开一个集群,中转一些中间网络,比如互联网,然后进入另一个集群。

这可能是大多数人在考虑多集群服务网格时的第一想法,但我在这里单独把它列出来,因为它对容错有影响。

异构/非扁平化的网络

非平面网络支持跨多个集群的服务,没有平面网络的要求。这意味着你可以做一些事情,比如在一个网格中分配 IP,而不考虑另一个网格,你不需要 VPN 或网络隧道来进行跨网格的通信。

如果你的组织已经创建了一堆不同的集群,而没有冲突的 pod IP 地址范围,或者你只是永远不想再进入这种泥潭,这将是一个对你有吸引力的属性。

多集群服务网格方法

在阐述了你可能需要从多集群中寻找的不同属性之后,我可以介绍一下各种方法所带来的好处。

独立集群

这就是解多集群。仅仅因为你有多个集群,而且每个集群都使用一个服务网格,并不意味着你必须采用统一的多集群服务网格。扪心自问,你当初为什么会有多个集群。如果你希望每个集群都是自己独立的故障域,那么隔离和消除跨集群的依赖关系是有意义的。 如果这能满足你的需求,那么把服务网格当作另一个单集群的服务,比如 pod 调度或持久性磁盘管理,也没有什么坏处。

共同管理

在独立集群方法之上的下一步是多个集群的共同管理系统。在这种模式下,每个集群都是独立运行的,但你通过一个共同的管理界面来管理这套网格。让你用来监控和调试系统(或者,在这种情况下,系统)的东西驻留在系统本身之外是一个很好的设计,这样当系统坏了的时候,你仍然可以检查和修复它。

如果你选择在这些集群中使用一个共同的信任根(证书授权或签名证书),那么你也可以拥有一个统一的信任域。

如果独立的故障域是首要任务,那么这是一个不错的选择。这种选择很适合将软件作为服务来消费,因为你可以得到一个外部的接口来统一一切,并得到服务级别协议的支持。

通过网关进行集群感知的服务路由选择

Istio 中的这种方法涉及多个独立的服务网格,每个集群中一个,以及一些配置技巧,以允许一个集群中的服务与另一个集群中的服务通信。首先,你要为所有网格创建一个统一的信任域。接下来,你配置一个入口网关,以接受来自另一个对等集群中的服务的可信流量。最后,配置服务条目,以允许某些服务的流量从一个集群路由出来并发送到另一个集群。

这是第一种允许不同集群中的服务直接相互通信的方法。同时,每个集群仍然是一个独立的网格控制平面和故障域。 这意味着,如果集群 B 中的服务网格发生故障,集群 A 仍然可以工作,只是看起来集群 B 中的服务不可用。配置这种跨集群流量的负担就落在了用户身上。

扁平网络

这种模式决定了你所有集群的服务网格。你安排它,使每个集群中的 pod 具有非重叠的 IP 地址,因此任何 pod 可以将流量路由到任何集群中的其他 pod。你可能在一个共同的防火墙后面有一堆集群,或者你可能在集群间建立 VPN 隧道。你配置服务网格,以将发现的 pod、服务和来自每个集群的配置结合到一个整体视图中。

扁平化的网络使它看起来就像你有一个超级服务网格,横跨你的所有集群。也有一些缺点。这个超级服务网格由一个控制平面管理,所以如果它出现问题,所有集群的服务网格都会出现问题。如果你原来为了容错而划分成多个 Kubernetes 集群,这种方式就否定了这一点。另外一个考虑是控制平面必须要扩展来管理所有集群。而且你必须让这个扁平网络的性能足够好,以处理控制平面和跨集群的流量。

分割区域端点发现服务(EDS)

这种方法也可以在集群间创建一个服务网格,但不需要扁平网络。你仍然有一个控制平面,可以从每个集群中发现 pod、服务和配置,但 Istio 的 EDS,其功能类似于分裂水平 DNS,取代了对扁平网络的要求。

一个集群中的 pod 的 sidecar 被配置了它想要通信的每个服务的端点列表。如果 pod 在同一个集群中,它就会直接显示在 EDS 列表中。如果 pod 在另一个集群中,则会出现另一个集群的入口网关。pod 选择一个端点进行对话并发送流量 —— 如果端点是本地的,则通信是直接的 pod 到 pod。如果 pod 选择了一个远程端点,它就会将流量发送到相关入口网关的地址,并标记为 pod 想要访问的服务。入口网关接收流量,并将其发送到其集群中实现服务的 pod 之一。入口网关使用服务器名称指示(SNI)来了解流量的目的地。

与扁平网络方式一样,这种方式创建了一个统一的服务网格控制平面,并增加了一个单一故障域和单一信任域。它不需要扁平网络,只需要一个集群可以将流量发送到其他集群的入口网关的公共地址。

要不要多集群?

如果你出于开发和组织的原因要运行多个集群,那么了解你的需求并决定是否要在多集群环境中连接这些需求是很重要的,如果是这样,了解各种方法和每个选项的相关权衡。

如果你已经读到这里,你可能已经决定了多集群。真正的问题是什么是最好的实现方法。希望下面的表格能帮助你决定适合你的方法。

方法 统一管理 统一信任 异构网络 独立故障域 跨集群通信
独立集群
共同管理
扁平网络
分割区域端点发现服务(EDS)
通过网关进行集群感知的服务路由选择

像 Istio 这样的服务网格可以提供帮助,如果使用得当,可以让多集群通信变得不痛苦。如果你想了解更多关于我对为什么以及团队应该如何考虑采用服务网格来简化跨多个集群的通信的看法。

关于作者

Andrew Jenkins 是 Aspen Mesh 的首席技术官,他正在构建一个企业服务网格,以帮助企业减轻管理微服务的负担。作为容器环境(如 Kubernetes)的软件和网络架构师,Jenkins 曾担任技术领导,推动快速发展的团队取得切实成果。他的专长包括 C++、JavaScript(Node.js)、Python、C、Go 和 Java 的软件开发。Jenkins 还在软件和硬件测试、FPGA 和空间科学仪器的电路板设计方面拥有丰富的经验。