特百惠:Facebook杀手Kubernetes?

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



今天在Systems @ Scale会议上,我们介绍了Tupperware,这是我们的集群管理系统,可以在数百万台服务器上协调容器,几乎所有服务都在其中工作。 我们于2011年首次推出了Tupperware,自那时以来,我们的基础设施已从1个数据中心增长到多达15个地理分布的数据中心 。 一直以来,特百惠公司都没有停滞不前,并与我们一起发展。 我们将告诉您在哪种情况下Tupperware提供一流的群集管理,包括对有状态服务的便捷支持,用于所有数据中心的单个控制面板以及实时在服务之间分配功率的能力。 我们将分享我们在基础架构发展过程中吸取的经验教训。


特百惠执行各种任务。 应用程序开发人员使用它来交付和管理应用程序。 它将代码和应用程​​序依赖关系打包到一个映像中,并以容器的形式将其交付给服务器。 容器在同一服务器上的应用程序之间提供隔离,因此开发人员忙于应用程序逻辑,而不考虑如何查找服务器或控制更新。 特百惠还监视服务器的性能,如果发现故障,它将从有问题的服务器中转移容器。


容量规划工程师使用Tupperware根据预算和约束将服务器容量分配给团队。 他们还使用它来提高服务器利用率。 数据中心操作员转向Tupperware,以在数据中心之间正确分配容器,并在维护期间停止或移动容器。 因此,维修服务器,网络和设备所需的人力最少。


特百惠架构



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


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


特百惠负责容器配置和生命周期管理。 它由几个部分组成:


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

特百惠的特色


Tupperware与其他集群管理系统(例如Kubernetes和Mesos )非常相似,但是有一些区别:


  • 对状态服务的本地支持。
  • 单个控制面板,用于不同数据中心中的服务器,以根据意图,停用集群和维护来自动化容器的交付。
  • 清晰地分开控制面板进行缩放。
  • 灵活的计算使您可以在服务之间实时分配功能。

我们设计了这些很酷的功能,以支持巨大的全局共享服务器园区中的各种无状态和有状态应用程序。


对状态服务的本地支持。


特百惠(Tupperware)管理许多重要的有状态服务,这些服务为Facebook,Instagram,Messenger和WhatsApp存储持久性产品数据。 这些可以是大型键值对(例如ZippyDB )和监视数据存储(例如ODS GorillaScuba )。 维护有状态服务并不容易,因为系统必须确保容器交付可以承受大规模故障,包括断电或断电。 尽管诸如在故障域之间分布容器之类的常规方法非常适合无状态服务,但是有状态服务需要额外的支持。


例如,如果由于服务器故障而导致数据库的一个副本不可用,是否有必要允许自动维护以从1万个池中更新50台服务器上的内核? 这取决于情况。 如果在这50台服务器中的一台上有同一数据库的另一个副本,则最好等待并且不要一次丢失2个副本。 为了动态地做出有关系统维护和运行状况的决策,您需要有关内部数据复制和每个有状态服务的位置逻辑的信息。


TaskControl接口允许状态服务影响影响数据可用性的决策。 调度程序使用此接口将容器操作(重新启动,更新,迁移,维护)通知外部应用程序。 有状态服务实现了一个控制器,该控制器告诉Tupperware什么时候可以安全地执行每个操作,并且这些操作可以交换或暂时延迟。 在上面的示例中,数据库控制器可以指示Tupperware升级50台服务器中的49台,但到目前为止尚未触摸特定的服务器(X)。 因此,如果内核更新期过去了,并且数据库仍然无法还原问题副本,则Tupperware仍将升级X服务器。



特百惠中的许多有状态服务并不直接使用TaskControl,而是通过ShardManager(一种在Facebook上创建有状态服务的通用平台)使用的。 借助特百惠,开发人员可以表明他们打算如何在数据中心之间分配容器。 使用ShardManager,开发人员可以表明他们打算如何在容器之间分配数据碎片。 ShardManager知道其应用程序的数据托管和复制,并通过TaskControl接口与Tupperware交互以计划容器操作,而无需直接涉及应用程序。 这种集成大大简化了有状态服务的管理,但是TaskControl可以提供更多功能。 例如,我们广泛的Web层是无状态的,并使用TaskControl动态调整容器中更新的速度。 因此, Web层每天可以快速完成多个软件版本 ,而不会影响可用性。


数据中心的服务器管理


当Tupperware于2011年首次出现时,一个单独的调度程序控制着每个服务器群集。 然后,Facebook群集是一组连接到一个网络交换机的服务器机架,数据中心包含多个群集。 调度程序只能管理一个群集中的服务器,也就是说,该任务不能扩展到多个群集中。 我们的基础架构在不断发展,我们在逐步注销集群。 由于Tupperware无法在不做任何更改的情况下将任务从退役的群集转移到其他群集,因此在应用程序开发人员和数据中心操作员之间进行了大量的工作并进行了认真的协调。 当服务器由于停用程序而闲置数月时,此过程导致资源浪费。


我们创建了资源代理来解决集群停用问题并协调其他类型的维护任务。 资源代理监视与服务器关联的所有物理信息,并动态决定由哪个调度程序管理每个服务器。 服务器与调度程序的动态绑定使调度程序可以管理不同数据中心中的服务器。 由于Tupperware作业不再局限于一个群集,因此Tupperware用户可以指定如何在故障域之间分配容器。 例如,开发人员可以声明他的意图(例如:“在PRN区域中的2个故障域上运行我的任务”),而无需指定特定的可用区域。 即使在停用集群或服务的情况下,Tupperware本身也会找到合适的服务器来体现这一意图。


扩展以支持整个全球系统


从历史上看,我们的基础架构已分为数百个专用于各个团队的服务器池。 由于碎片化和缺乏标准,我们的交易成本很高,并且闲置的服务器很难再使用。 在去年的Systems @Scale会议上,我们介绍了基础架构即服务(IaaS) ,该基础架构应将我们的基础架构集成到一个大型统一服务器群中。 但是单个服务器机队有其自身的困难。 它必须满足某些要求:


  • 可扩展性。 随着每个地区的数据中心的增加,我们的基础架构也得到了发展。 服务器变得更小,更节能,因此在每个区域中都有更多。 结果,一个区域的单个调度程序无法应对每个区域中可以在成千上万的服务器上运行的容器数量。
  • 可靠度 即使可以如此增加调度程序的规模,但由于调度程序的范围较大,因此出错的风险会更高,并且整个容器区域可能变得难以管理。
  • 容错能力。 万一基础设施发生重大故障(例如,由于网络故障或电源中断,运行调度程序的服务器将发生故障),则该地区的服务器中只有一部分会产生负面影响。
  • 易于使用。 似乎您需要在一个区域中运行多个独立的调度程序。 但是就便利性而言,进入该区域公共池的单个入口点简化了容量和作业管理。

我们将调度程序分为多个碎片,以解决支持大型共享池的问题。 每个调度程序分片管理该区域中的一组任务,这降低了与调度程序相关的风险。 随着总池的增加,我们可以添加更多调度程序分片。 对于Tupperware用户而言,分片和代理调度程序看起来像一个控制面板。 他们不必处理一堆编排任务的碎片。 调度程序分片与我们之前使用的群集调度程序有根本的不同,当时控制面板被划分而没有根据网络拓扑静态隔离公共服务器池。


通过弹性计算提高利用率


我们的基础架构越大,有效地使用我们的服务器来优化基础架构成本并减少负载就越重要。 有两种提高服务器利用率的方法:


  • 灵活的计算-减少安静时段的在线服务规模,并将释放的服务器用于离线负载,例如用于机器学习和MapReduce任务。
  • 过多的负载-在同一台服务器上托管在线服务和批处理工作负载,因此以低优先级执行批处理负载。

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


基本上,我们通过弹性计算来提高利用率。 我们许多大型服务(例如新闻提要,消息功能和前端Web级别)的使用强度取决于一天中的时间。 我们有意减少安静时段的在线服务规模,并将释放的服务器用于离线负载,例如用于机器学习和MapReduce任务。



根据经验,我们知道最好将整个服务器作为弹性力量的单位来提供,因为大型服务既是弹性力量的主要捐助者又是主要使用者,并且为使用整个服务器进行了优化。 当服务器在安静时间从联机服务中释放时,资源代理将服务器交给调度程序以供临时使用,以便它在其上运行脱机负载。 如果在线服务中出现负载高峰,则资源代理会快速重新调用借出服务器,并与调度程序一起将其返回到在线服务。


经验教训和未来计划


在过去的8年中,我们开发了Tupperware以跟上Facebook的快速发展。 我们谈论我们所学到的东西,并希望它能帮助其他人管理快速增长的基础架构:


  • 在控制面板与其管理的服务器之间建立灵活的通信。 这种灵活性使控制面板可以管理不同数据中心中的服务器,帮助自动化停用和维护集群,并使用灵活的计算功能提供动态电源分配。
  • 使用该区域中的单个控制面板,可以更加方便地处理任务,并且更易于管理大型的通用服务器群。 请注意,即使控制面板的内部结构因比例或容错原因而分开,它也支持单个入口点。
  • 使用插件模型,控制面板可以将即将进行的容器操作通知外部应用程序。 而且,有状态服务可以使用插件接口来配置容器管理。 使用此插件模型,控制面板可简化操作并有效地提供许多不同的有状态服务。
  • 我们认为,弹性计算可将整个服务器用于批处理作业,机器学习和其他来自捐助者服务的非紧急服务,这是提高使用小型节能型服务器效率的最佳方法。

我们才刚刚开始实施一个全球通用服务器园区 。 现在,我们约有20%的服务器位于公共池中。 要达到100%,您需要解决许多问题,包括为存储系统支持通用池,自动维护,管理不同客户端的需求,提高服务器利用率以及改善对机器学习工作负载的支持。 我们迫不及待地要解决这些任务并分享我们的成功。

Source: https://habr.com/ru/post/zh-CN455579/


All Articles