特百惠:Facebook 的 Kubernetes 杀手?

使用 Tupperware 对任何规模的集群进行高效、可靠的管理

特百惠:Facebook 的 Kubernetes 杀手?

今天在 系统@规模会议 我们推出了 Tupperware,这是我们的集群管理系统,可以在运行几乎所有服务的数百万台服务器上编排容器。 我们于 2011 年首次部署 Tupperware,从那时起,我们的基础设施已从 1 个数据中心 直至整体 15 个地理分布式数据中心。 一直以来,特百惠并没有停滞不前,并与我们一起发展。 我们将向您展示特百惠如何提供一流的集群管理,包括对有状态服务的便捷支持、适用于所有数据中心的单一控制面板以及在服务之间实时分配容量的能力。 我们还将分享随着基础设施的发展所吸取的经验教训。

特百惠执行不同的任务。 应用程序开发人员使用它来交付和管理应用程序。 它将应用程序代码和依赖项打包到镜像中,并将其作为容器传递到服务器。 容器在同一服务器上的应用程序之间提供隔离,以便开发人员处理应用程序逻辑,而不必担心查找服务器或管理更新。 特百惠还监控服务器的性能,如果发现故障,则会从有问题的服务器传输容器。

容量规划工程师使用 Tupperware 根据预算和限制向团队分配服务器容量。 他们还使用它来提高服务器利用率。 数据中心运营商求助于特百惠在数据中心之间正确分配容器,并在维护期间停止或移动容器。 因此,维护服务器、网络和设备需要最少的人工干预。

特百惠架构

特百惠:Facebook 的 Kubernetes 杀手?

特百惠 PRN 架构是我们数据中心的区域之一。 该区域由附近的几座数据中心大楼(PRN1 和 PRN2)组成。 我们计划制作一个控制面板来管理一个地区的所有服务器。

应用程序开发人员以 Tupperware 作业的形式提供服务。 一个作业由多个容器组成,它们通常都运行相同的应用程序代码。

特百惠负责配置容器并管理其生命周期。 它由几个组件组成:

  • Tupperware 前端提供用于用户界面、CLI 和其他自动化工具的 API,您可以通过它们与 Tupperware 进行交互。 他们向特百惠工作所有者隐藏了整个内部结构。
  • Tupperware Scheduler 是一个控制面板,负责管理容器和作业生命周期。 它分为区域级和全局级部署,区域调度器管理一个区域内的服务器,全局调度器管理不同区域的服务器。 调度程序分为多个分片,每个分片管理一组作业。
  • Tupperware 的 Scheduler Proxy 隐藏了内部分片,并为 Tupperware 用户提供了方便的单一管理平台。
  • Tupperware 分配器将容器分配给服务器。 调度程序处理容器的停止、启动、更新和故障转移。 目前,一个分配器可以管理整个区域,而无需拆分为分片。 (注意术语上的差异。例如,Tupperware 中的调度程序对应于 Kubernetes,Tupperware 分配器在 Kubernetes 中称为调度器。)
  • 资源代理存储服务器和服务事件的真实来源。 我们为每个数据中心运行一个资源代理,它存储有关该数据中心中服务器的所有信息。 资源代理和容量管理系统或资源供应系统动态地决定哪个调度程序交付控制哪个服务器。 健康检查服务监视服务器并将有关其健康状况的数据存储在资源代理中。 如果服务器出现问题或需要维护,资源代理会告诉分配器和调度程序停止容器或将它们移动到其他服务器。
  • Tupperware 代理是在每台服务器上运行的守护进程,用于处理容器的配置和删除。 应用程序在容器内运行,这为它们提供了更多的隔离性和可重复性。 在 去年的 Systems @Scale 会议 我们已经描述了如何使用图像、btrfs、cgroupv2 和 systemd 创建单个 Tupperware 容器。

特百惠的显着特点

Tupperware 在很多方面与其他集群管理系统(例如 Kubernetes 和 梅索斯,但也存在差异:

  • 对有状态服务的内置支持。
  • 适用于不同数据中心服务器的单一控制面板,可根据意图自动交付容器、停用集群和维护。
  • 控制面板的缩放划分清晰。
  • 弹性计算允许您在服务之间实时分配电力。

我们开发了这些很酷的功能来支持庞大的全球共享服务器群中的各种无状态和有状态应用程序。

对有状态服务的内置支持。

特百惠运营各种关键的有状态服务,为 Facebook、Instagram、Messenger 和 WhatsApp 存储持久产品数据。 这些可能是大量键值对存储(例如 Zippy数据库)和监控数据存储库(例如, 消耗臭氧层物质大猩猩 и 水肺)。 维护有状态的服务并不容易,因为系统必须确保容器的供应能够承受大规模的中断,包括网络中断或断电。 虽然传统技术(例如跨故障域分配容器)对于无状态服务效果很好,但有状态服务需要额外的支持。

例如,如果服务器故障导致一个数据库副本不可用,您是否应该启用自动维护来更新 50 个服务器池中 10 个服务器上的核心? 视情况而定。 如果这 50 台服务器中的一台有同一数据库的另一个副本,最好等待,不要一次丢失 2 个副本。 为了动态地做出有关系统维护和性能的决策,我们需要有关内部数据复制和每个有状态服务的放置逻辑的信息。

TaskControl 接口允许有状态服务影响影响数据可用性的决策。 使用此接口,调度程序通知外部应用程序有关容器操作(重新启动、更新、迁移、维护)。 有状态服务实现一个控制器,该控制器告诉 Tupperware 何时可以安全地执行每个操作,并且这些操作可以暂时交换或延迟。 在上面的示例中,数据库控制器可以告诉 Tupperware 更新 49 台服务器中的 50 台,但暂时保留特定服务器 (X)。 因此,如果内核更新周期过去并且数据库仍然无法恢复有问题的副本,Tupperware 仍将更新 X 服务器。

特百惠:Facebook 的 Kubernetes 杀手?

Tupperware 中的许多有状态服务不是直接使用 TaskControl,而是通过 ShardManager(用于在 Facebook 上创建有状态服务的通用平台)使用 TaskControl。 借助特百惠,开发人员可以准确指定容器如何跨数据中心分布的意图。 使用 ShardManager,开发人员可以指定数据分片如何跨容器分布的意图。 ShardManager 了解其应用程序的数据放置和复制,并通过 TaskControl 接口与 Tupperware 进行通信,以安排容器操作,而无需应用程序直接参与。 这种集成极大地简化了有状态服务的管理,但 TaskControl 的能力还不止于此。 例如,我们广泛的 Web 层是无状态的,并使用 TaskControl 动态调整容器的更新速率。 最终 Web层能够快速完成多个软件发布 每天,而不影响可用性。

管理数据中心的服务器

当特百惠于 2011 年首次推出时,每个服务器集群都由单独的调度程序管理。 当时,Facebook 集群是一组连接到一个网络交换机的服务器机架,数据中心容纳了多个集群。 调度程序只能管理一个集群中的服务器,这意味着作业无法跨多个集群分布。 我们的基础设施不断发展,我们越来越多地取消集群。 由于特百惠无法在不进行任何更改的情况下将作业从退役集群转移到其他集群,因此需要应用程序开发人员和数据中心运营商之间进行大量努力和仔细协调。 当服务器由于退役程序而闲置数月时,此过程会导致资源浪费。

我们创建了一个资源代理来解决集群退役问题并协调其他类型的维护任务。 资源代理跟踪与服务器关联的所有物理信息,并动态决定由哪个调度程序控制每个服务器。 将服务器动态链接到调度程序允许调度程序管理不同数据中心的服务器。 由于 Tupperware 作业不再局限于单个集群,Tupperware 用户可以指定容器如何跨故障域分布。 例如,开发人员可以声明他的意图(例如:“在 PRN 区域的 2 个故障域上运行我的作业”),而无需指定特定的可用区域。 即使集群或服务退役,特百惠本身也会找到合适的服务器来实现这一意图。

可扩展以支持整个全球系统

从历史上看,我们的基础设施已分为数百个供各个团队使用的专用服务器池。 由于碎片化和缺乏标准,我们的运营成本很高,闲置的服务器更难以再次使用。 在去年的会议上 系统@规模 我们提出了 基础设施即服务 (IaaS),这应该将我们的基础设施整合到一个大型的单一服务器园区中。 但单一服务器园区也有其自身的困难。 它必须满足某些要求:

  • 可扩展性。 随着我们在每个地区增加数据中心,我们的基础设施不断发展。 服务器变得更小、更节能,因此每个区域的服务器数量都更多。 因此,每个区域的单个调度程序无法处理每个区域中数十万台服务器上可以运行的容器数量。
  • 可靠性。 即使调度程序可以扩展那么多,调度程序的大范围也意味着出现错误的风险更高,并且整个容器区域可能变得难以管理。
  • 容错性。 如果发生巨大的基础设施故障(例如,运行调度程序的服务器由于网络故障或断电而发生故障),负面后果应该只会影响该区域的一部分服务器。
  • 使用方便。 您可能看起来需要为一个区域运行多个独立的调度程序。 但从便利的角度来看,区域共享池的单点入口可以更轻松地管理容量和作业。

我们将调度器划分为分片来解决维护大型共享池的问题。 每个调度程序分片管理该区域中自己的一组作业,这降低了与调度程序相关的风险。 随着共享池的增长,我们可以添加更多的调度程序分片。 对于特百惠用户来说,分片和调度程序代理看起来就像一个控制面板。 他们不必使用一堆编排任务的分片。 调度器分片与我们之前使用的集群调度器有根本的不同,当时的控制面板是分区的,没有根据网络拓扑静态划分服务器的共享池。

通过弹性计算提高使用效率

我们的基础设施规模越大,有效使用我们的服务器来优化基础设施成本和减少负载就越重要。 提高服务器使用效率有两种方法:

  • 弹性计算 - 在安静时段缩减在线服务规模,并使用释放的服务器来处理离线工作负载,例如机器学习和 MapReduce 作业。
  • 过载 - 将在线服务和批处理工作负载放在同一服务器上,以便批处理工作负载以低优先级运行。

我们数据中心的瓶颈是 用电量。 因此,我们更喜欢小型、节能的服务器,它们可以提供更多的处理能力。 不幸的是,在 CPU 和内存很少的小型服务器上,过载的效果较差。 当然,我们可以将多个小型服务的容器放置在一台小型节能服务器上,该服务器消耗很少的处理器资源和内存,但在这种情况下大型服务的性能会很低。 因此,我们建议大型服务的开发人员对其进行优化,以便他们使用整个服务器。


基本上,我们通过弹性计算来提高使用效率。 我们的许多主要服务,例如新闻源、消息传递功能和前端 Web 层,都会根据一天中的时间而有所不同。 我们有意在安静时段缩减在线服务规模,并使用空闲的服务器来处理离线工作负载,例如机器学习和 MapReduce 作业。

特百惠:Facebook 的 Kubernetes 杀手?

我们从经验中知道,最好将整个服务器配置为弹性容量单元,因为大型服务既是弹性容量的主要提供者也是主要消费者,并且经过优化以使用整个服务器。 当服务器在空闲时间从在线服务中释放时,资源代理将服务器租给调度程序以在其上运行离线工作负载。 如果在线服务遇到峰值负载,资源代理会快速召回借用的服务器,并与调度程序一起将其返回给在线服务。

吸取的教训和未来的计划

在过去的 8 年里,我们一直在开发 Tupperware,以跟上 Facebook 的快速增长。 我们分享我们所学到的知识,并希望它能帮助其他人管理快速增长的基础设施:

  • 在控制面板与其管理的服务器之间建立灵活的连接。 这种灵活性允许控制面板管理不同数据中心的服务器,有助于自动化集群的退役和维护,并使用弹性计算实现动态容量分配。
  • 通过该区域的单个控制面板,可以更方便地处理任务并更轻松地管理大型共享服务器群。 请注意,控制面板保持单个入口点,即使其内部结构由于规模或容错的原因而被分离。
  • 使用插件模型,控制面板可以通知外部应用程序即将进行的容器操作。 而且,有状态服务可以使用插件接口来定制容器管理。 通过这个插件模型,控制面板提供了简单性,同时有效地服务于许多不同的有状态服务。
  • 我们相信,弹性计算(将整个服务器从批处理作业、机器学习和其他非紧急服务的捐赠服务中拿走)是提高小型节能服务器效率的最佳方式。

我们刚刚开始实施 单一全球共享服务器群。 目前,我们大约 20% 的服务器位于共享池中。 为了实现 100%,需要解决许多问题,包括维护共享存储池、自动化维护、管理跨租户需求、提高服务器利用率以及改进对机器学习工作负载的支持。 我们迫不及待地想迎接这些挑战并分享我们的成功。

来源: habr.com

添加评论