要大规模地构建和维护基础设施,容易地访问系统的当前状态至关重要。随着Uber的业务不断扩张,我们的基础设施在规模和复杂性上都有所增长,这使得我们在需要的时候获得所需的所有信息变得更加困难。
为了解决这个问题,我们构建了Grail,这是一个使我们能够将我们基础架构的当前状态聚合到一个全局视图中的平台,遍布所有区域和地区。Grail使我们能够很容易地构建快速而有力地执行复杂操作任务的工具。
请继续阅读,了解Grail如何改变优步工程通过图形模型操作其存储的方式,使团队能够轻松地将数据从其他不同的源缝合在一起。
设计一种更容易的管理方式
2016年底,我们将所有数据库主机从旋转磁盘升级到SSD以支持越来越大的负载。该企业的一个重要部分涉及识别和跟踪仍然使用旧硬件的数千个数据库。
当时,我们无法访问当前状态,因此此过程涉及大量脚本和任务跟踪。这使我们能够在规模上查看建筑工程的不同方法。要求是:
- 整个基础设施状态的持续聚合。
- 单一的基础设施的全局视图。
- 水平可扩展的读取容量。
- 低延迟访问来自所有数据源的数据。
- 所有数据源中数据的相关性。
- 琐碎的添加和删除数据来源。
最后,应该容易地从其他来源重新创建数据。今天,Grail支持所有这些要求。
引入格拉林
不像公平博格那osquery.Grail不收集任何特定领域的信息,而是作为一个平台,在这里,来自不同数据源的基础设施概念(主机、数据库、部署、所有权等)可以以高可用性和响应性的方式进行聚合、互连和查询。Grail有效地隐藏了我们基础设施的所有实现细节。
此外,Grail可以让你获得近乎实时的问题答案,比如:
- 哪些主机目前拥有超过4TB的可用空间?
- 一个给定的团队在他们所有的数据库上使用了多少存储磁盘空间?
- 哪些数据库正在使用旋转磁盘上的主机上运行?
如果您有少量服务和主机,这些问题是微不足道的;在这些情况下,您只需要编写一个脚本,即在需要时直接收集状态。然而,在优步规模中,当您有几十个服务和数十万个主机时,这种方法不再可行。节点太多,响应缓慢,数据相关将会出错,当您的查询完成时,结果不再反映现实。即时状态集合根本不扩展。
一个关键的观察是,不存在“单一的真相来源”。“关于数据中心和系统的信息总是存在于多个地方,需要相互关联才能做出合理的决策。使事情更加复杂的是,这些系统的状态是不断变化的:主机的空闲磁盘空间一直在变化,提供新的存储集群,并且有100万件其他事情同时发生。一下子得到整个系统的状态是不可能的——你只能希望得到它的近似值。
大规模的维护
优步存储平台团队构建并维护持有关键任务数据的Petabytes的存储系统。我们的操作工具遵循一个简单的三个步骤过程:首先,我们收集系统状态,然后将其与所需的状态进行比较,最后对差异 - 标准的自我修复范例进行行动。
如上所述,状态集合在没有像Grail这样的聚合平台上很难。例如,当我们想要获取运行的所有主机的当前状态时,例如该旅行数据存储,我们首先需要弄清楚哪些主机包含数据存储。接下来,我们必须连接到所有主机来收集当前状态,最后,转换每个结果并呈现答案。
通过Grail,我们可以通过运行单个查询来访问我们需要的信息:
横数据存储:旅行(
扫描簇(
扫描D b(
扫描主办(
场hostinfo.
)
)
)
)
结果作为JSON文档返回,与查询的结构非常相似,使其通过代码轻松消耗。下面的代码段显示了在运行上面的示例查询时如何了解的蒸馏版本:
“__id” : “数据存储:旅行” 那
“簇” : [
{
“__id” : “集群 - 旅行-US1-44” 那
“D b” : [
{
“__id” : “cluster-trips-us1-44-db26” 那
“主办” : [
{
“__id” : “host:database862-sic1” 那
“hostinfo” : {
“cpucount” : 24. 那
“傀儡” : “数据库” 那
“记忆” : {
“frefbytes” : 1323212425 那
“totalBytes” : 137438953472
} 那
“磁盘” : {
“frefbytes” : 48289601723 那
“totalBytes” : 1598689906787
}
}
}
]
}
......
]
}
......
]
}
把拼图放在一起
Grail是在两个关于优步基础设施的观察中设计的。第一次观察是我们的基础架构可以自然地建模为节点之间的节点和节点之间的关联。
图中的节点由一个惟一键标识,该键在表单中组合了节点类型和名称类型:名称。数据源使用节点键将包含属性和关联的数据附加到节点上。数据同样由一个键标识。节点密钥空间是全局的,而属性和关联密钥空间是节点类型的局部密钥空间。
Grail的对象模型被设计成使得图表中的节点由数据源产生的属性和关联隐式定义。这意味着节点一种当至少有下列情况之一成立时存在:
- 数据源分配node的一个属性一种。
- 数据源关联节点一种使用至少一个其他节点。
- 数据源将至少一个其他节点与节点相关联一种。
第二个观察是关于我们的个人基础架构概念,如主机或数据库的信息是分散的。这意味着获得完整图像需要组合来自多个系统的信息。
Grail通过每个数据源提供图表的子源来处理此分散化。这些小节可以在多个数据源可以将属性或关联附加到同一节点的意义上重叠。
上面图4的顶部显示了三个这样的小节。实线和颜色确定哪些子源提供哪些子源,而虚线表示组合图。下面的组合图显示了如何从Grail的角度看数据。
这种方法允许我们以原子方式更新来自一个数据源的所有数据,并允许不同数据源以不同的速度并行更新。
在图5中,数据源1附上一个财产hostinfo.关键,而数据源2附上一个财产ServiceInfo.键并将节点与其他一系列相关联服务关联类型下图中的节点服务。
导航数据
在我们的设计就绪之后,我们需要一种方法来轻松地执行即席操作图形遍历在图上。我们回顾的选项似乎都不太合适。例如,GraphQL.需要模式,并且不支持节点之间的映射或命名关联,而格里蒙似乎很有希望,但实施支持它 - 更不用说使用它 - 是复杂的。所以,我们写了自己的。
我们的语言YQL,允许用户指定节点的起始集合,然后通过跟随关联的关联遍历图表,同时与沿途存储在属性中的属性中的字段。作为示例,以下查询列出了具有40GB的可用内存,100GB的可用磁盘空间的所有主机,以及使用SSD磁盘:
横主持人:*(
场hostinfo.
哪里hostinfo.。磁盘。媒体=“SSD.“
哪里hostinfo.。disk.free>(100 * 1024 ^ 3)
哪里hostinfo.。内存.Free>(40 * 1024 ^ 3)
)
走向记忆
自成立以来,Grail的架构已经发生了几个迭代。最初,它是我们旧数据库操作工具的内部组成部分。写在Python,这首次迭代使用了Redis进行了图形存储,并且部分受到启发涛。当此实现不足时,我们接下来将决定使用共享的Elasticsearch集群作为自己的服务重写它作为自己的服务。然而,随着时间的推移,这种解决方案还缺乏我们需要快速,高效的摄取和查询所需的可扩展性和延迟。
我们决定重新思考架构,将以前存储在共享的Elasticsearch集群中的内容移动到每个查询节点上的自定义内存数据存储中。
Grail当前的高级架构由三个组件组成:
- 摄取者:从已配置的数据源收集数据。
- 协调:确保数据更新的严格顺序。
- 查询节点:提供水平可扩展的数据访问。
摄取器周期性地从预配置的数据源收集数据,然后通过协调群集发送,并最终应用于位于每个查询节点上的数据存储。协调是使用自定义内存完成的筏群建立在顶部etcd筏图书馆。RAFT协议可确保严格排序数据更新如何应用于数据存储,并在重新启动中提供数据持久性。协调节点和查询节点都包含每个数据源的最新数据更新的内存内存表示。协调节点仅使用此数据作为创建当RAFT-LOGS截断时当前应用数据的快照的方法。
数据存储是一个简单的键/值抽象,其中每个数据源在唯一的键下存储最新的数据更新,数据源的名称。来自所有数据源的数据单独存储,仅在执行节点密钥查找时组合。
Grail通过在我们的每个区域运行一个单独的实例来实现我们的基础设施的全局视图;每个实例负责从本地主机和服务收集数据。查询节点跟踪来自本地和远程区域的raft-log,具体取决于配置。查询引擎在执行查询时结合了本地和远程信息。
要扩展Grail,我们可以部署多个协调群集并扩展查询引擎,支持进行分布式查询,从而允许我们将数据吞吐量和尺寸较好地进入未来。
处理准确性
当与分布式系统交互时,考虑信息不准确性是很重要的。无论信息是通过聚合平台还是直接从源提供的,都不可避免地会有一些延迟,在此期间观察到的系统可能发生了变化。分布式系统不是事务性的-您无法使用一致的快照捕获它。无论基础设施的规模,这些条件都是如此。
我们的操作工具使用Grail提供的信息来做出决策。当这些决策需要更改我们的系统时,我们始终确保在应用这些更改之前仔细检查源上的信息。作为示例,当主机端代理分配任务时,代理将检查原始的前提条件是否仍在执行任务之前保持,例如衡量主机是否仍然有足够的磁盘空间。
关键的外卖
如前所述,有效的基础设施管理需要强烈了解系统状态。使用较小的基础设施时,这通常不是那么重要;当您需要时,您只需查询真相源。但是,这种方法根本不适用于更大的比例系统。相反,您需要集中信息聚合。当我们学习第一手时,在处理数十万个主机和数十个真理系统时快速访问合理最新的系统状态是非常强大的。
为此,可以在三个关键点中总结Grail的优势
- 来自我们所有真实来源的数据都通过一个公共查询API聚合到一个共享模型中。
- 对所有区域和区域的当前状态进行低延迟查询。
- 团队可以附加他们自己领域特定的概念,并将它们与来自其他领域的相关概念连接起来。
如今,Grail为我们的存储解决方案提供了我们的大部分操作工具,并且对于我们基础架构的所有方面都存在几乎无限数量的使用情况。实际上,正在发现更多用例,因为所包含的信息的程度不断发展。
如果以全球影响利益为尺度建立自我修复的操作工具,请考虑申请职位我们的团队!!






