本博客是系列博客中的第一篇,涵盖了我们构建和运营SaaS服务的各个方面:
正如我们在之前的博客中所描述的,我们的客户正在构建复杂多样的业务解决方案——例如智能制造、公共安全视频取证、算法交易、电信 5G 网络——因此我们需要为这些applications及其最终用户提供始终在线、连接且可靠的体验。
由于这些applications可以在跨云提供商或客户边缘位置的多个集群中运行,我们的平台团队必须构建分布式控制平面和 PaaS 服务来部署、保护和操作多个多租户 Kubernetes 集群。 该分布式控制平面提供了许多操作、扩展和性能优势,我们将在演示(视频链接)中介绍这些优势 - 例如如何使用 GitOps 管理数千个边缘 K8s 集群 - 并且将在未来几周内作为单独的博客文章发布。
我们选择 Kubernetes (K8s) 作为我们管理分布式applications平台的核心,因为它提供了丰富的功能但又不会过于规范,让我们能够灵活地对我们认为对客户重要的事情进行创新。 我们以此为基础开始构建我们的服务,随着 K8s 的日益普及,也更容易找到熟悉它的开发人员和运营商。
也就是说,在混合环境(多个云、网络 POP 和边缘位置)中部署和管理大量生产级 Kubernetes 集群并不是一件容易的事,因为 Kubernetes 没有可以实现以下功能的开箱即用的解决方案:
在与多个云提供商和开源平台(如 GKE、AKS、EKS 和 RKE 以及 OpenShift 和 Cloud Foundry)进行多次概念验证之后,我们意识到它们都无法满足上述所有五个要求。 因此,我们决定构建自己的 PaaS——从“原始” Kubernetes 开始,并做了一些添加——用于身份、网络、安全、多租户、日志记录、指标等。 虽然我们使用 Kubernetes 来满足我们的内部需求,但我们不得不做出一些艰难的决定,例如不将这些 Kubernetes 集群直接暴露给我们的内部用户和/或客户来运行他们的工作负载(稍后会详细介绍,因为多租户是我们的一个关键目标)。
除了我们需要添加的多个新功能之外,还需要在边缘、我们的网络以及公共/私有云的许多位置与客户工作负载一起运行我们的工作负载/服务。 这意味着我们必须构建额外的功能来管理多个环境中的多个集群......所有这些都使用我们的全球网络和分布式应用网关连接,以在这些集群之间提供零信任和应用程序级连接。
即使使用云提供商管理的集群,构建和操作在单个 Kubernetes 集群中运行的applications也不是一件容易的事。 这就是为什么 DevOps 和 SRE 团队通常会尽量减少开销并且不处理许多集群的复杂性。 团队构建一个大型 Kubernetes 集群并将所有类型的资源放在同一个集群中是很常见的。 虽然这看起来很棒,因为他们可以简化操作并运行集群以实现最大的计算效率和成本,但由于多种原因,这并不是最好的主意。 首先,生产工作负载的需求与开发测试和登台有很大不同——不稳定的开发工作负载可能会给更稳定的生产工作负载带来问题。
除了多样化工作负载的需求之外,K8s 的安全性和隔离限制是多集群的另一个驱动因素。 解决 K8s 安全性和资源隔离问题的典型方法是使用多租户模型为每个租户启动独立的集群。 虽然这在云中是可行的,但在边缘运行多个集群是不可能的。 边缘站点具有计算和存储资源限制以及受限的网络带宽,无法将每个附加集群的日志和指标发送到中央云。
为了解决多个 Kubernetes 集群的问题,我们评估了 Rancher 来集中管理我们的 Kubernetes 集群(当我们开始时,Anthos 和 Azure Arc 还不存在)和 KubeFed。 当时有两种可用的方法(现在的情况仍然相同):
在最近发布 GCP Anthos 和 Azure Arc 之后,我们重新评估了构建分布式控制平面的原始决定,结论是,即使是这两种新产品也无法解决分布式集群的两个关键问题。 我们的平台需要以下两个关键功能:
为了解决这两个问题,我们必须提出一种新技术——分布式控制平面,来解决“多”集群的运营开销,并为资源受限环境中的多租户提供“多集群”的等价物。
我们的平台团队决定为 Kubernetes 构建一个分布式控制平面,向我们的团队公开 Kubernetes API,然而这些 API 来自仅存在于我们的控制平面中的“虚拟”集群——虚拟 K8s 集群的虚拟 K8s (vK8s) API 服务器(如图 1所示)。 该控制平面将用户的意图映射到在我们的边缘、网络 POP 和公共云位置运行的多个物理 Kubernetes 集群。 这些物理集群仅可供我们的分布式控制平面访问,而不能供任何单个租户/用户访问。
该控制平面为每个租户提供一个或多个“虚拟”应用集群,他们可以在其中部署他们的应用,并且根据配置,控制平面将在多个物理 Kubernetes 集群中复制和管理它。 除了配置和部署操作之外,监控操作也遵循这个“虚拟”集群,而无需构建工具来收集和分析来自多个物理集群的数据。
让我们以一个名为 productpage 的示例 UI应用为例,用户意图是让它分布在 3 个位置——pa2-par、ny8-nyc 和 ams9-ams,每个位置有 2 个副本。 当用户创建 vK8s 对象并将其附加到虚拟集群时,它会立即提供可与标准 kubectl 一起使用的 vK8s API 服务器。
接下来,用户下载此虚拟集群的 kubeconfig 并创建标准 yaml 来描述 productpage 的 K8s 部署。
创建部署规范后,用户可以继续在此虚拟集群上创建部署:
现在,如果用户检查他的部署,他会看到已经启动了 6 个副本,每个位置有 2 个(pa2-par、ny8-nyc 和 ams9-ams)。
以下输出显示每个位置运行 2 个 pod,并映射到特定的物理节点
这个简单的例子说明了在几分钟内实现任何应用程序的多集群复制是多么简单,而且无需任何安装和管理负担。 除了映射意图之外,分布式控制平面还为虚拟集群提供可观察性,而不是基于单个集群。
如图 2所示,我们的集中管理平面跨两个公共云提供商(每个区域)运行 - 一个在 AWS,一个在 Azure(为了实现冗余)。 该管理平面允许我们的 SRE 创建具有硬多租户的租户 - 例如,从事我们的 VoltMesh 服务的开发团队可以成为租户,而从事客户 POC 的客户解决方案团队可以成为自己的租户,并拥有自己的一组用户。
每个租户可以创建多个命名空间,并指定一组用户在这些命名空间上进行协作。 这些命名空间不是 Kubernetes 命名空间——它们是我们平台中针对用户的 RBAC 规则和 IAM 策略的隔离边界。
当命名空间内的用户想要创建应用集群时,他们会创建一个 vK8s 对象,然后在我们的管理平面中创建一个 vK8s API 服务器。 使用这个 vK8s 对象,用户可以创建部署、状态集、PVC 等,控制平面将确保这些操作根据与 vK8s 对象关联的站点在一个或多个物理集群上发生。
由于每个租户和用户都使用标准的 K8s 操作而无需进行任何修改,因此系统可以与许多受运营商欢迎的工具兼容 - 例如 Spinnaker、Helm、Jenkins 等。
分布式控制平面的一大优势是它解决了我们的 SRE 和 DevOps 团队的运营开销。 他们现在可以在虚拟集群中执行操作(配置、部署、监控、策略等),并且控制平面将自动将其映射到多个物理集群。 控制平面除了简化多集群的操作之外,还解决了多租户的安全和隔离问题。
这个分布式控制平面还提高了想要向我们的平台添加新功能的开发人员的工作效率——他们不必在每次添加影响多个集群的配置或操作的新功能时都构建新的自动化。 他们使用基于意图的配置模型,控制平面知道需要做什么。 此外,他们可以继续使用 kubectl 而不是其他 CLI 与这个分布式多集群对象(虚拟 kubernetes)进行交互。
在我们的开发测试、登台和生产环境中运行了一年多之后,我们意识到这个全球分布式控制平面(在我们的网络 POP 中运行)还提供了显著的规模、性能和可靠性优势——这是我们早期完全没有想象到的。 我们将在即将举行的 KubeCon 演示中以及未来几周的单独博客文章中介绍这一发现。
本系列博客将涵盖我们构建和运营全球分布式 SaaS 服务的各个方面,该服务在公共云、我们的私有网络 PoP 和边缘站点中拥有许多应用集群。 接下来是分布式应用程序的全局服务网格……