[大厂实践] Odin:Uber 有状态平台实践

本文介绍了 Uber 的有状态平台 Odin 的背景和基本原理。Odin 作为通用的、与技术栈无关的有状态平台,能够管理不同技术栈对数据库运维方式的特殊要求。原文:Odin: Uber’s Stateful Platform

简介

Uber 采用了各种数据存储技术,包括 Kafka、Cassandra 以及 MySQL 等知名开源产品,还有内部开发的解决方案。2014 年,Uber 经历了快速扩张,与许多初创公司一样,技术团队基于执行手册手动执行配置和运维操作。随着存储需求迅速增加,这种方法让运维很麻烦。因此,Uber 创建了一个与技术栈无关的管理平台,名为 Odin,通过自动化提高运维效率,让团队可以毫不费力的管理数千个数据库。

Odin 平台旨在通过涵盖管理有状态工作负载的所有方面来提供统一的运维体验,包括主机生命周期、工作负载调度、集群管理、监控、状态传播、操作用户界面、告警、自动扩容和自动化。Uber 在全球、地区和区域层面部署了有状态系统,而 Odin 旨在以一种与技术栈无关的方式一致的管理这些系统。此外,Odin 支持本地化,以提高硬件成本效率。所有有状态工作负载都必须完全容器化,这在平台创建时是一个相对新颖且有争议的概念。

本文是 Uber 有状态平台系列文章的第一篇,该系列旨在帮助没有构建容器平台的先验知识,但具备广泛专业知识的读者了解相关平台知识。这篇文章概述了 Odin 的起源、基本原则以及早期遇到的挑战。下一篇文章将探讨如何安全扩展运维效率,通过工作流程显著改善对大规模、全公司运营以及升级执行手册的处理。请继续关注本系列的更多文章。


平台规模

自 2014 年以来,Uber 的存储和数据基础设施急剧增长,从几百台主机发展到今天的 10 万多台,支持跨不同存储集群运行 300,000 个工作负载。Odin 平台上的每个工作负载都类似于 Kubernetes pod,由一组容器组成。目前,该平台管理着 380 万个独立容器,存储容量达到若干 EiB(1 EiB = 2^60 B),拥有数百万个计算核心。

该平台支持 23 种技术栈,从 MySQL、Cassandra 等传统在线数据库到 HDFS、Presto、Kafka 等高级数据平台技术。由于该平台强大的容量管理和可扩展解决方案,还集成了资源调度框架,如 Yarn 和 Buildkite。

该平台尽量实现本地化,以便最好的利用主机上的可用资源。Uber 为所有有状态工作负载使用本地附加驱动器以提高性能。因此调度器必须进行优化,以在所有三个维度(即CPU、内存和磁盘)上保持较高的分配率,从而提高效率。我们在瓶颈资源上可以达到 95% 以上的高分配率,并且运维超过 100 个数据库。

通过 Uber 的云抽象,Odin 平台既与技术栈无关,也与云无关,目前在 OCI、GCP 和 Uber 的本地服务器中运行。


自修复平台

Odin 被构建为完全声明式和基于意图的,从而较好的支持了容错、可伸缩性和自愈等特性。平台基于大量小的自动化变更回路来实现目标状态自动收敛到实际状态,从而将期望状态表示为目标状态。这些变更回路旨在通过不断推动系统朝着“正确方向”前进,确保系统实际状态向声明的目标状态收敛。

现在看来,Odin 和 Kubernetes 有许多相似之处,这种思维模式在阅读本系列博客时将有所帮助。

下面的示例说明了变更回路的结构。变更回路从检查目标状态开始,然后收集实际状态,识别两者之间的差异,并通过 Cadence 工作流来调整系统状态以缩小差距。这类似于 Kubernetes 控制器的工作方式,区别只在于 Kubernetes 是直接通过 APIServer 操作状态。


图1: Odin 变更回路高级概述。

变更回路优先考虑模块化和松耦合,从而有助于横向扩展并简化开发,以便每个回路都可以作为独立的微服务进行开发。

在 Odin 平台上,通过数据集成平台 Grail 提供了全局系统状态的最新视图,从而简化了回路的开发。Grail 提供了涵盖所有技术栈的统一数据模型,并提供了平台目标和实际状态的最新视图,包括主机、容器,甚至特定技术栈的内部状态。Grail 还允许在全局范围内执行查询,获取 Uber 在全球各地运营的所有数据中心和地区提供的数据。本质上,可以把 Grail 看作是 Kubernetes APIServer 中的资源模型。

平台的控制平面只关注高层决策,例如工作负载调度和管理集群拓扑。用于操作目标状态的 API 会触发执行工作流。变更回路和人工操作都会启动工作流。平台提供了 UI,让操作人员可以快速查看数据库状态,并在需要时应用操作。

工作流提供了深刻的洞见,因此非常有价值。更新目标状态的工作流通常包括两个步骤。首先更新目标状态,然后工作流将监视实际状态,直到其收敛于指定的目标状态。因此,当收敛没有完成时,哪些操作没有收敛是很清楚的,包括为什么首先执行该操作的上下文。由于实际状态并不会立即收敛,系统必须防止变更回路不断启动试图做出相同变更的工作流。


图1: Odin 全局架构

管理通用存储集群

Odin 建立在与技术栈无关的集群模型上,该模型提供了管理任何类型工作负载集群的通用操作。该模型支持通用操作,如添加或删除工作负载、升级容器镜像,以及跨技术栈统一处理其他与集群相关的任务。由于模型、操作与技术栈无关,因此需要通过插件来支持扩展,以根据其特定需求定制集群管理的各个方面。

两个主机代理

Odin 控制平面分为两部分。到目前为止,我们只讨论了全局部分。在主机级别,有两个代理。一个是主机上的所有工作负载共享的,与技术栈无关。我们称之为 odin-agent。另一个代理特定于技术栈,并作为工作负载的一部分被容器化运行。这两个代理结合在一起,提供与 kubelet 相同的功能。


图3:使用与全局控制平面通信的两个主机级代理的 Odin 主机剖面图。

主机代理与全局控制平面通信,同步最新目标和实际状态,主要职责是管理主机级资源分配,例如为工作负载调度 cpu,创建和管理磁盘卷/cgroup,以及在分配主机时引导工作负载。

特定于技术栈的代理称为 worker,是和工作负载运行在同一个容器中的管理进程,主要作用是确保正在运行的容器与目标状态保持一致,并收集运行状态以及其他相关数据,以便向控制平面的全局部分报告。worker 的通用功能包括启动和停止容器。可以将 worker 视为平台可理解的通用集群状态与工作负载中运行的数据库容器之间的转换器。

技术团队可以定制 worker 以收集特定于技术栈的实际状态,并将目标状态应用于工作负载。例如,MySQL worker 的任务是确保 MySQL 主节点和副节点保持各自的角色,并将当前状态报告给全局控制平面。团队可以根据集群实际状态编写操作集群的新工作流。许多技术栈已经扩展了相应 worker,执行自我变更操作。例如,当集群拓扑发生变化时,协调 leader 选举或数据备份。

优化鲁棒性和弹性

将控制平面划分为主机本地组件和全局组件允许我们可以对不同工作负载的 worker 进行单独部署,从而将有问题的变更的影响范围限制在尽量小的单元上。这同样适用于工作负载中的每个容器,因为平台允许单独就地升级容器。

对于这两个代理,规则是在对运行的工作负载进行任何更改之前,必须首先将目标状态写入磁盘。这种方法保证了可以在没有活跃控制平面的情况下初始化自给自足的集群,从而有效解决了引导问题。此外,还提供强大的故障恢复能力,允许工作负载在控制平面降级期间正常工作,并简化应急工具的开发。

转换身份

随着我们不断优化效率并使主机群现代化,将工作负载从一台主机转移到另一台主机已经成为平台上最常见的操作之一。到目前为止,我们每月重新调度多达 60% 的有状态工作负载。有状态工作负载的关键需求是在调度时维持工作负载标识。例如,此功能允许将服务于同一分片的某个工作负载替换为另一个工作负载。在 Kubernetes 中,这是通过 StatefulSets 进行管理的,方法是分配一个持续存在的稳定的 pod 标识。删除 pod 时,将为新 pod 提供相同的标识。让我们来探讨一下为什么这种模式不适合 Uber 的用例。

如前所述,Uber 为所有有状态工作负载使用本地附加驱动器以提高性能。此设置要求在终止相应工作负载之前复制主机上的数据并在其他地方提供数据。如果在替代工作负载完全准备好之前关闭了该工作负载,则集群会暂时无法提供服务。这个延迟是不可忽略的,平均时间为 1 小时,增加了集群丢失数据或面临可用性问题的风险。此外,延迟还降低了集群处理请求的总体能力。

“替换”工作负载

因此,Odin 上最基本的操作就是将工作负载从一台主机迁移到另一台主机。用 Odin 的话说,就是“替换”工作负载。替换操作的目的是先创建后替换 (make-before-break)。这意味着它将创建一个新的工作负载,在可能的情况下,该工作负载可以在旧工作负载关闭之前携带它所替换的工作负载的标识和数据。技术集成可以选择在工作负载之间传播目标状态的哪些部分。目标状态模型使两种工作负载明确意识到彼此的存在。这点至关重要,因为它允许各自的 worker 协调数据复制和其他操作的过程。在极少数情况下,当替换前创建无法实现时(例如,旧工作负载在故障主机上),旧工作负载会在创建替换工作负载的同时被删除。

使用先创建后替换也有效率上的好处,因为替代方法要求始终提供多余的备份集群。而在我们的模型中,只是在必要时暂时提供多余资源。


成长的烦恼

Odin 平台的第一次迭代是团队运维存储集群能力的巨大飞跃。存储团队可以通过共享操作模型将所有的操作和见解集中在一个平台上。然而,这个平台仍然是以人为中心的,人是平台变革的主要参与者,而且至关重要的是,由人来保证所执行操作的安全性和适应性。变更回路的作用仅限于范围相对较小的操作,例如单一的替换工作流。

随着业务规模不断扩大,运维开销开始增长,以至于对不同技术栈的运维实际上不可能由人工来操作。需要我们转移工作负载的复杂、跨技术栈运维的例子有:

  • 优化工作负载调度,从而处理机架或域故障等基础设施问题
  • 主机功能封装,提高成本效益
  • 全团队主机升级,例如类似 LVM/cgroupv2 等新内核、固件或功能
  • 促进建立新数据中心或淘汰现有数据中心

此外,单个主机上的大量数据库使处理主机故障变得令人生畏。这些限制表明,必须通过开发比以前范围更广的新的变更回路来进一步自动化。

协调需要

如果不仔细协调,增加的运维负载可能很快导致中断。想象一下这样一种情况:某个 3 节点存储集群工作负载执行容器升级,而另一个变更回路已经确定该集群中的工作负载之一将因性能原因而被重新调度。如果允许,就会导致存储集群失去仲裁,从而影响写可用性。

我们一开始会通过增加变更循环的方式在内部执行并发控制(图3)。通过这种方式,可以防止相同类型的操作给存储集群带来问题。例如,容器升级回路会阻止重复升级。然而,这种方法也有缺陷,因为不能解决由不同的变更回路造成的冲突问题。图3显示了在同一个存储集群中,两个独立操作可以操作两个工作负载,从而导致可用性问题的情况。


图4:内部并发控制不能保护存储集群不受冲突操作的影响,而且会损害可用性。

不同技术栈对集群操作的容错能力差异很大。对于某些技术栈,特定工作负载可能是至关重要的,而其他工作负载都是平等的。有些技术栈只专注于确保集群中始终有一定数量的工作负载可用。需求的多样性使得我们必须支持针对每种技术栈的特定需求定制集群管理策略。

我们需要一个系统来确保全局、跨类型的运维协调,该系统可以根据当前工作负载运行状况和中断预算并利用特定技术栈的限制来保证集群可用性。此外,通过实施平台范围的全局并发性和流控来防止工程错误并避免内部平台系统过载。


总结

在本系列的这篇介绍性文章中,探讨了 Uber 的有状态平台 Odin 的背景和基本原理。Odin 作为通用的、与技术栈无关的平台脱颖而出,能够管理对数据库运维方式有特殊要求的各种技术栈。

我们讨论了 Uber 的数据库如何利用本地附加磁盘来提高性能和成本效益,以及由于存储的数据必须遵循工作负载标识所带来的挑战。

我们还研究了平台本质上是如何基于意图的,不同的变更回路不断努力使托管工作负载的实际状态与其预期目标状态保持一致。这些回路启动 Cadence 工作流来更新目标状态并等待收敛。这个过程需要仔细协调才能被安全的管理,而不会影响被管理数据库的可用性。

在下一篇文章中,我们将讨论如何集中协调所有业务,从而显著提高 Uber 大规模运营车队的能力。


你好,我是俞凡,在Motorola做过研发,现在在Mavenir做技术工作,对通信、网络、后端架构、云原生、DevOps、CICD、区块链、AI等技术始终保持着浓厚的兴趣,平时喜欢阅读、思考,相信持续学习、终身成长,欢迎一起交流学习。为了方便大家以后能第一时间看到文章,请朋友们关注公众号"DeepNoMind",并设个星标吧,如果能一键三连(转发、点赞、在看),则能给我带来更多的支持和动力,激励我持续写下去,和大家共同成长进步!

本文由mdnice多平台发布

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,734评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,931评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,133评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,532评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,585评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,462评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,262评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,153评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,587评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,792评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,919评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,635评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,237评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,855评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,983评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,048评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,864评论 2 354

推荐阅读更多精彩内容