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

Kubernetes Federation 的演进

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

在 SIG Multicluster 中,我们的探索发现解决这些问题有多种可能的模型,并且可能没有单一的最佳、全场景解决方案。然而,Kubernetes 集群联邦(简称 KubeFed)是 Kubernetes 开源子项目中规模最大的一个,并且在这个问题领域获得了社区最大的兴趣和贡献。该项目最初复用了 Kubernetes API,以避免给现有 Kubernetes 用户增加额外的使用复杂性。但这种方法不可行,原因总结如下:

  • 在集群级别重新实现 Kubernetes API 的困难,因为联邦特定的扩展存储在注解(annotation)中。
  • 由于对 Kubernetes API 的 1:1 仿真,导致联邦类型、放置和协调的灵活性有限。
  • 没有明确的正式发布(GA)路径,并且对 API 成熟度普遍感到困惑;例如,Deployment 在 Kubernetes 中已经正式发布,但在 Federation v1 中甚至还不是 Beta 版。

这些想法通过联邦特定的 API 架构和社区的努力得到了进一步演进,目前以 Federation v2 的形式继续发展。

概念概述

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

Kubernetes Federation v2 Concepts

Kubernetes Federation v2 概念

联邦任意资源

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

工作组对联邦 API 和 API 组达成了一个共同定义,即 “一种将‘常规’ Kubernetes API 资源分发到不同集群的机制”。其最简单的分发形式可以想象为将这种 “常规 Kubernetes API 资源” 在联邦集群中进行 简单传播。细心的读者肯定能辨别出比这种 Kubernetes 资源简单传播更复杂的机制。

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

“轻松联邦任意 Kubernetes 资源” 的能力,以及解耦的 API(分为构建块 API、更高级别 API 和可能的面向用户类型),使得不同的用户可以使用部分 API 并编写控制器来构建针对其特定需求的解决方案,这为 Federation v2 提供了令人信服的理由。

联邦资源:详细说明

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

  • 联邦应该处理哪些 API 类型
  • 联邦应该将这些资源分发到哪些目标集群。

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

  • Template 类型保存资源的基准规约 - 例如,一个名为 FederatedReplicaSet 的类型保存了应该分发到目标集群的 ReplicaSet 的基准规约
  • Placement 类型保存资源应该分发到哪些集群的规约 - 例如,一个名为 FederatedReplicaSetPlacement 的类型包含了关于 FederatedReplicaSet 应该分发到哪些集群的信息
  • 可选的 Overrides 类型保存了 Template 资源在某些集群中应该如何变化的规约 - 例如,一个名为 FederatedReplicaSetOverrides 的类型包含了关于如何在特定集群中调整 FederatedReplicaSet 的信息。

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

更高级别行为

v2 API 的架构允许使用核心 API 类型(TemplatePlacementOverride)及其相关控制器为给定资源提供的机制来构建更高级别的 API。在社区中,我们发现了一些用例,并为这些用例实现了有用的更高级别 API 和相关控制器。进一步章节中描述的其中一些类型也为任何有兴趣解决更复杂用例、并基于 v2 API 已有机制构建解决方案的人提供了有用的参考。

ReplicaSchedulingPreference(副本调度偏好)

ReplicaSchedulingPreference 提供了一种自动机制,用于将基于 Deployment 或 ReplicaSet 的联邦工作负载的总副本数分配和维护到联邦集群中。这是基于用户提供的高级用户偏好设置。

这些偏好设置包括用于分配副本的权重分布限制(最小和最大值)的语义。这些还包括允许在某些集群中因资源不足等原因导致部分副本 Pod 未被调度时动态重新分配副本的语义。更多详细信息可以在ReplicaSchedulingPreference 用户指南中找到。

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

Kubernetes Service 在构建微服务架构中非常有用。显而易见,需要在跨集群、区域、地域和云边界部署 Service。跨集群的 Service 提供了地理分布能力,实现了混合云和多云场景,并提高了超出单集群部署的高可用性级别。希望其服务跨越一个或多个(可能远程的)集群的客户,需要确保这些服务能够从集群内部和外部以一致的方式访问。

联邦的 Service,其核心包含一个 Template(Kubernetes Service 的定义)、一个 Placement(部署到哪些集群)、一个 Override(在特定集群中的可选变体)和一个 ServiceDNSRecord(指定如何发现它)。

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

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

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

让我们考虑一个示例,使用名为 nginx 的 Service。

位于 us-central1-a 可用区中集群内的 Pod 需要联系我们的 nginx Service。它现在可以使用 Service 的联邦 DNS 名称,即 nginx.mynamespace.myfederation,而不是使用 Service 传统的集群本地 DNS 名称(nginx.mynamespace,它会自动展开为 nginx.mynamespace.svc.cluster.local)。这个名称将自动展开并解析到我的 nginx Service 最近的健康分片,无论其在世界何处。如果在本地集群中存在健康的分片,则会返回该 Service 的集群本地 IP 地址(由集群本地 DNS 提供)。这与非联邦 Service 解析完全等效。

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

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

从联邦集群外部的其他客户端发现联邦 Service

对于外部客户端,目前无法实现所述的自动 DNS 展开。外部客户端需要指定联邦 Service 的完全限定 DNS 名称之一,无论是可用区、地域还是全局名称。为方便起见,通常手动为 Service 配置额外的静态 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 可以部署在集群范围 (cluster-scoped)命名空间范围 (namespace-scoped) 配置中。集群范围部署需要主机集群和成员集群的集群管理员权限,可能适合在未运行关键工作负载的集群上评估联邦。命名空间范围部署仅需访问主机集群和成员集群上的单个命名空间,更适合在运行工作负载的集群上评估联邦。大部分用户指南参考了集群范围部署,而namespaced federation 部分记录了命名空间范围部署的使用差异。同一个集群可以承载多个联邦,并且在使用命名空间范围联邦时,集群可以属于多个联邦。

后续步骤

正如我们在本文开头所提及,多集群问题空间非常广阔。如果没有具体的软件来构建围绕这些问题的讨论,很难确切知道如何处理如此广阔的问题空间。 Federation 工作组希望 Federation v2 能成为一个具体的成果来构建讨论。我们很想了解大家在此问题空间中的经验,他们对 Federation v2 有何看法,以及他们未来有兴趣探索哪些用例。

欢迎加入我们在sig-multicluster Slack 频道或每周三太平洋标准时间 07:30 参加Federation 工作组会议