Twine — Facebook 把整个数据中心当一台机器调度
待复核Twine 是 Facebook(现 Meta)2020 年公开的集群管理系统,管着公司内部超过 100 万台机器。它的目标只有一句:把分布在十几个数据中心的所有机器,当成一台超大计算机来调度。
日常类比:把整个公司的会议室连成一个共享池,员工不再说 我要 3 楼的 207 室,只说 我下午 2 点要一间能坐 10 人的房间,哪个楼都行,由总调度系统自动分配。Twine 干的就是这件事——只是房间换成了 CPU、内存、GPU。
它不是「再做一个更大的 K8s 集群」,而是换了一层抽象:应用先拿跨地域配额,再谈具体落点;宿主机也可以按应用画像重装。理解这层抽象,后面五个设计才说得通。
不理解 Twine,下面这些事会想不通:
- 为什么 Facebook、Google 内部都自研调度,而不是直接跑 Kubernetes(K8s)——K8s 更像 Borg 面向通用场景的开源简化
- 为什么 K8s 一个集群当时常见支持上限约 5000 节点,Twine 论文语境下却能调度十万台量级
- 为什么
把 K8s 集群继续做大这条路在某个规模会撞墙,需要换思路 - 为什么数据中心调度论文 2020 年还在产生新结构,没有
终极答案
K8s/Borg 是教科书答案,Twine 是 超大规模下教科书怎么演化 的真实样本。
Twine 和 Borg/K8s 拉开差距的设计有 5 个:
-
Entitlement(配额承诺):应用拿到的不是
某个集群里的 100 个 pod,而是跨地域的资源承诺。类比:先批你「亚洲区 50 间会议室额度」,具体哪间稍后排。 -
Host Profile(宿主机定制):应用能声明内核版本、HugePages(把内存页从 4KB 合成更大块,少翻页表)、sysctl(系统旋钮)。类比:开会前把房间重装成「放映厅」再交付;K8s 的 DaemonSet 改不动这一层。
-
TaskControl 双向协商:重启/迁移前先问应用「现在能动你吗」。类比:物业要检修,先问住户能不能停水,而不是直接关闸。K8s 的 preStop 只是单向通知。
-
Power Capping(功耗调度):数据中心总功耗有上限,功率和 CPU、内存平级调度。类比:整栋楼电表有上限,调度器要决定哪几间先开灯。
-
单插槽小机器:Facebook 偏好 single-socket(一块 CPU)小机器——故障域小、粒度细、功耗好管。这是和 Borg 常见 dual-socket 大机器哲学差异最大的硬件选型。
案例 1:entitlement 怎么发挥作用
Section titled “案例 1:entitlement 怎么发挥作用”传统做法(K8s):
应用方: 我要在 us-east 集群启 100 个 pod集群: 我这只剩 60 个槽位应用方: 那我去 us-west 自己再申请一遍Twine 做法:
应用方: 我要 us-east 5000 vCPU + us-west 3000 vCPUTwine: 收到,配额已就绪应用方: 现在我想跑 100 个实例Twine: 自动分配——80 个去 us-east、20 个去 us-west逐部分解释:配额和「具体放哪」解耦后,调度器才有空间做全局优化(功耗、网络、故障域)。应用不再自己当跨集群调度员。
案例 2:host profile 解决的痛点
Section titled “案例 2:host profile 解决的痛点”ML 训练要 HugePages(大块内存页)+ 特定内核;Web 前端要普通 4KB 页 + 长期支持内核。K8s 里这两类任务很难共享同一台宿主机。
- 应用声明
host profile = ml-training-v3 - 调度器找一台空闲机器
- 重装这台机器成该 profile(分钟级,不是秒级)
- 把容器交付上去
代价是交付变慢,收益是同一批硬件能服务差异化需求。
案例 3:TaskControl 救数据库
Section titled “案例 3:TaskControl 救数据库”Twine: 我想重启你这个实例,可以吗?数据库: 现在不行,我有 3 笔事务在飞(正在 fsync=把数据刷到磁盘),给我 90 秒Twine: 好,90 秒后再问数据库: 可以了,我已经把 leader(主副本)切给同伴Twine: 开始重启若应用一直拒绝、超过强制超时:Twine 仍会迁移,应用侧应把「被强制」当成故障演练——副本接管、连接重试,不能假设协商永远成功。
与 Borg / K8s 的对比
Section titled “与 Borg / K8s 的对比”| 维度 | Borg (2015) | Kubernetes | Twine (2020) |
|---|---|---|---|
| 单集群规模 | 约 1 万台/cell | 约 5000 节点 | 跨 cell,十万台量级 |
| 配额单元 | cell 内 | namespace quota | 跨 region entitlement |
| 宿主机定制 | 有限 | 不支持重装级 | host profile |
| 重启协商 | 单向通知 | preStop(单向) | TaskControl(双向) |
| 功耗调度 | 弱 | 无 | 一等公民 |
| 硬件偏好 | dual-socket | 不限 | single-socket 小机器 |
踩过的坑(论文里说的)
Section titled “踩过的坑(论文里说的)”- 跨 region 调度的延迟成本:entitlement 跨域听起来美,placement 决策会被网络放大;Twine 用多级缓存和异步预分配。
- host profile 切换是分钟级:必须预测需求提前切换,否则交付延迟会让应用方抓狂。
- TaskControl 拒绝过多:早期滥用「拒绝重启」让资源收不回;后来加了强制超时和 SLO 兜底。
- profile 碎片化:太多定制 profile 会让空闲机器对不上号,看起来有机器却派不出去。
适用 vs 不适用
Section titled “适用 vs 不适用”适用:
- 单家公司、内部基建、机器规模 5 万+ 台
- 工作负载差异大(前端 + ML + 数据库 + Cache 共存)
- 愿意付出
不通用的代价换极致优化
不适用:
- 通用云服务(要卖给外部,host profile 这种侵入式设计不能做)
- 千台规模以下(K8s 已经够,自造系统不划算)
- 工作负载单一(比如全是无状态 Web,K8s 简单且足够)
历史小故事(可跳过)
Section titled “历史小故事(可跳过)”- 2015 年:Google 公开 Borg——cell/job/task 成了行业共同语言。
- 2014–2016 年:K8s 开源并快速成为外部默认答案;内部超大规模玩家仍自研。
- 2020 年:Facebook 在 OSDI 发表 Twine,把 entitlement、host profile、TaskControl、功耗调度写成一套统一系统。
- 之后:行业继续在「通用编排」和「内部极致优化」两条路上分叉,没有单一终局。
一个集群不是必然抽象:规模到十万台量级,cell/cluster 边界要打开,资源要跨域流动。- 教科书答案有边界:K8s 在中等规模是好答案,再往上往往要换思路。
不通用是一种武器:不卖云就可以做侵入式设计——这是 Twine 和 K8s 的根本区别。- 功耗是新维度:硬件红利变薄后,功率要和 CPU、内存一起进调度器。
- 双向协商 > 单向通知:状态服务要平稳调度,必须给应用「说不」的权力,也要有超时兜底。
- 论文 PDF:Twine OSDI 2020(18 页,可读)
- borg-2015 —— Borg — Google 2015 公开的集群管理原型
- kubernetes-2014 —— Kubernetes — Borg 思路的开源通用化
- mesos-2011 —— Mesos — 双层调度的另一种解法
- omega-2013 —— Omega — Google 并行共享状态调度
- borg-2015 —— Borg 提供 cell/job/task 基本概念,Twine 把 cell 边界打开
- kubernetes-2014 —— K8s 是面向通用场景的开源路径,Twine 是内部极致优化路径
- mesos-2011 —— Mesos 的双层调度思路在 Twine 里以 entitlement 形式回归
- firmament-2016 —— Firmament — 把调度建模成最小费用流的另一种思路
- omega-2013 —— Omega — Google 并行调度器,和 Twine 同属「打破单集群墙」一族
(暂无反向链接)