本文发表于一年多前。旧文章可能包含过时内容。请检查页面中的信息自发布以来是否已变得不正确。

Kubernetes Federation 演进

Kubernetes 为将应用程序部署到集群提供了出色的原语:它可以像 kubectl create -f app.yaml 一样简单。在多个集群中部署应用程序从未如此简单。应用程序工作负载应该如何分配?应用程序资源应该复制到所有集群、复制到选定的集群,还是分区到集群中?如何管理对集群的访问?如果用户想要分发的一些资源以某种形式预先存在于部分或所有集群中,会发生什么?

在 SIG Multicluster 中,我们的探索表明存在多种可能的模型来解决这些问题,并且可能没有一个单一的最佳解决方案。然而,Kubernetes Cluster Federation (简称 KubeFed) 是最大的 Kubernetes 开源子项目,并且在这个问题领域获得了社区最大的兴趣和贡献。该项目最初重用了 Kubernetes API,以消除现有 Kubernetes 用户的额外使用复杂性。这种方法不可行,原因总结如下:

  • 在集群级别重新实现 Kubernetes API 存在困难,因为联邦特定的扩展存储在注解中。
  • 由于 Kubernetes API 的 1:1 模拟,联邦类型、放置和协调的灵活性有限。
  • 没有明确的 GA 路径,并且对 API 成熟度普遍存在困惑;例如,Deployments 在 Kubernetes 中是 GA 状态,但在 Federation v1 中甚至不是 Beta 状态。

这些想法随着联邦特定的 API 架构和社区努力而进一步发展,目前以 Federation v2 的形式继续。

概念概述

由于联邦试图解决一系列复杂问题,因此有必要将这些问题的不同部分分解开来。让我们看看所涉及的不同高级领域:

Kubernetes Federation v2 Concepts

Kubernetes Federation v2 概念

联邦任意资源

联邦的主要目标之一是能够定义 API 和 API 组,这些 API 和 API 组包含联邦任何给定 Kubernetes 资源所需的基本原则。这至关重要,因为 CustomResourceDefinitions 作为一种用新 API 扩展 Kubernetes 的方式非常流行。

工作组就联邦 API 和 API 组的共同定义达成一致,即“一种将‘普通’Kubernetes API 资源分发到不同集群的机制”。最简单的分发形式可以想象为将这种“普通 Kubernetes API 资源”简单地传播到联邦集群中。细心的读者当然可以辨别出比这种简单的 Kubernetes 资源传播更复杂的机制。

在定义联邦 API 的构建块的过程中,一个近期目标也演变为“能够创建简单的联邦,即任何 Kubernetes 资源或 CRD 的简单传播,几乎无需编写代码”。随后,一个核心 API 组定义了构建块,包括每个给定 Kubernetes 资源的 `Template` 资源、`Placement` 资源和 `Override` 资源,以及一个 `TypeConfig` 用于指定给定资源是否同步,以及执行同步的关联控制器。更多详细信息请参阅下一节。后续章节还将讨论如何通过更高级别的联邦 API 消耗这些核心构建块的行为来实现分层行为,以及用户能够消费 API 的全部或部分以及关联的控制器。最后,这种架构还允许用户编写额外的控制器或用自己的控制器替换可用的参考控制器,以实现所需行为。

能够“轻松联邦任意 Kubernetes 资源”,以及解耦的 API,分为构建块 API、高级 API 和可能的面向用户类型,以便不同用户可以消费部分并编写控制器以组成特定于他们的解决方案,这些都为 Federation v2 提供了令人信服的理由。

联邦资源:详细信息

从根本上说,联邦必须配置两种类型的信息:

  • 联邦应该处理哪些 API 类型
  • 联邦应该针对哪些集群来分发这些资源。

对于联邦处理的每种 API 类型,声明状态的不同部分存在于不同的 API 资源中:

  • Template 类型保存资源的基本规范——例如,一个名为 FederatedReplicaSet 的类型保存了应该分发到目标集群的 ReplicaSet 的基本规范。
  • Placement 类型保存资源应该分发到的集群的规范——例如,一个名为 FederatedReplicaSetPlacement 的类型保存了关于 FederatedReplicaSets 应该分发到哪些集群的信息。
  • 可选的 Overrides 类型保存了在某些集群中如何更改 Template 资源的规范——例如,一个名为 FederatedReplicaSetOverrides 的类型保存了关于在某些集群中如何更改 FederatedReplicaSet 的信息。

这些类型都通过名称关联起来——这意味着对于一个名称为 `foo` 的特定 Template 资源,该资源的 Placement 和 Override 信息包含在名称为 `foo` 且与 Template 位于同一命名空间中的 Override 和 Placement 资源中。

高级行为

v2 API 的架构允许为给定资源构建更高层次的 API,这些 API 利用了核心 API 类型(`Template`、`Placement` 和 `Override`)及其关联控制器提供的机制。在社区中,我们发现了几个用例,并为这些用例实现了有用的更高层次 API 和关联控制器。在后续章节中描述的一些类型也为任何有兴趣解决更复杂用例的人提供了有用的参考,这些用例基于 v2 API 已有的机制构建。

副本调度偏好

ReplicaSchedulingPreference 提供了一种自动化机制,用于将基于 Deployment 或 ReplicaSet 的联邦工作负载的总副本数分配并维护到联邦集群中。这基于用户给出的高级用户偏好。这些偏好包括加权分配和分发副本的限制(最小和最大值)的语义。它们还包括在某些副本 Pod 在某些集群中未调度的情况下(例如,由于该集群资源不足)动态重新分配副本的语义。更多详细信息可以在 ReplicaSchedulingPreferences 用户指南中找到。

联邦服务和跨集群服务发现

Kubernetes 服务在构建微服务架构中非常有用。人们强烈希望在集群、区域、地区和云边界之间部署服务。跨集群的服务提供地理分布,支持混合云和多云场景,并提高了超越单个集群部署的高可用性水平。希望其服务跨一个或多个(可能是远程的)集群的客户需要能够以一致的方式从集群内部和外部访问这些服务。

联邦 Service 的核心包含一个 Template(Kubernetes Service 的定义)、一个 Placement(要部署到的集群)、一个 Override(特定集群中的可选变体)和一个 ServiceDNSRecord(指定如何发现它的详细信息)。

注意:联邦服务必须是 LoadBalancer 类型,才能在集群之间被发现。

从联邦集群中的 Pod 发现联邦服务

默认情况下,Kubernetes 集群预先配置了集群本地 DNS 服务器,以及一个智能构建的 DNS 搜索路径,它们共同确保 Pod 内运行的软件发出的 DNS 查询(如 `myservice`、`myservice.mynamespace` 或 `some-other-service.other-namespace`)会自动展开并正确解析为在本地集群中运行的服务的相应 IP。

随着联邦服务和跨集群服务发现的引入,这一概念得到了扩展,以涵盖在全球范围内跨集群联邦的任何其他集群中运行的 Kubernetes 服务。要利用这一扩展范围,您需要使用略有不同的 DNS 名称(例如 `myservice.mynamespace.myfederation`)来解析联邦服务。使用不同的 DNS 名称还可以避免您的现有应用程序意外地遍历跨区域或跨区域网络,并且在您没有明确选择此行为的情况下,您可能不会产生不必要的网络费用或延迟。

让我们考虑一个使用名为 nginx 的服务的例子。

us-central1-a 可用区中的一个 Pod 需要联系我们的 nginx 服务。它可以使用服务的联邦 DNS 名称 nginx.mynamespace.myfederation,而不是使用服务传统的集群本地 DNS 名称(nginx.mynamespace,它会自动扩展为 nginx.mynamespace.svc.cluster.local)。这将被自动扩展并解析到我的 nginx 服务最近的健康分片,无论它位于世界的哪个地方。如果本地集群中存在健康分片,将返回该服务的集群本地 IP 地址(由集群本地 DNS)。这与非联邦服务解析完全相同。

如果服务在本地集群中不存在(或者存在但没有健康的后端 Pod),DNS 查询会自动扩展为 `nginx.mynamespace.myfederation.svc.us-central1-a.us-central1.example.com`。在后台,这会找到离我的可用区最近的分片的外部 IP。此扩展由集群本地 DNS 服务器自动执行,该服务器返回关联的 CNAME 记录。这导致遍历 DNS 记录的层次结构,并最终到达附近联邦服务的某个外部 IP。

通过明确指定适当的 DNS 名称,并且不依赖自动 DNS 扩展,还可以将服务分片定位到 Pod 所在可用区和区域之外的可用区和区域。例如,`nginx.mynamespace.myfederation.svc.europe-west1.example.com` 将解析到欧洲所有当前健康的服务分片,即使发出查找的 Pod 位于美国,并且无论服务在美国是否有健康的分片。这对于远程监控和其他类似应用程序非常有用。

从联邦集群之外的其他客户端发现联邦服务

对于外部客户端,目前无法实现自动 DNS 扩展。外部客户端需要指定联邦服务的完整合格 DNS 名称之一,无论是区域、区域或全局名称。为了方便起见,通常最好手动配置您服务中的额外静态 CNAME 记录,例如:

短名称CNAME
eu.nginx.acme.comnginx.mynamespace.myfederation.svc.europe-west1.example.com
us.nginx.acme.comnginx.mynamespace.myfederation.svc.us-central1.example.com
nginx.acme.comnginx.mynamespace.myfederation.svc.example.com

这样,您的客户就可以始终使用左侧的简短形式,并始终自动路由到其本洲最近的健康分片。所有必要的故障转移都由 Kubernetes 集群联邦自动为您处理。

作为进一步阅读,Multi-Cluster Service DNS with ExternalDNS 指南中提供了更详细的用户示例

亲身体验

要开始使用 Federation v2,请参考用户指南。部署可以通过 Helm chart 完成,一旦控制平面可用,可以使用用户指南的示例来亲身体验 Federation V2 的使用。

Federation v2 可以部署为集群范围命名空间范围配置。集群范围部署将需要主机集群和成员集群的集群管理员权限,可能适合在未运行关键工作负载的集群上评估联邦。命名空间范围部署只需要主机集群和成员集群上单个命名空间的访问权限,更适合在运行工作负载的集群上评估联邦。用户指南的大部分内容都涉及集群范围部署,而命名空间联邦部分则说明了命名空间部署的不同之处。同一个集群可以托管多个联邦,并且在使用命名空间联邦时,集群可以成为多个联邦的一部分。

后续步骤

正如我们在本文开头指出的那样,多集群问题空间非常广泛。如果没有具体的软件来围绕这些对话进行框架,很难确切地知道如何处理如此广泛的问题空间。我们希望在联邦工作组中,Federation v2 能够成为一个具体的构件,以围绕其展开讨论。我们很乐意了解人们在这个问题空间中的经验,他们对 Federation v2 的看法,以及他们未来有兴趣探索的用例。

欢迎加入我们的 sig-multicluster slack 频道或参加每周三太平洋时间 07:30 举行的 联邦工作组会议