Runway:News(网页)
精选
58AI 编辑部评分,满分 100

无闲置GPU:Runway的研究计算管理

2026-04-27 00:00· 100天前· Matt Kafonek and Brannon Dorsey, Platform Engineering
AI 导读

Runway通过采用Kueue作为Kubernetes准入控制器,将GPU利用率提升超过20%,同时保障团队容量。其核心机制是为关键工作预留配额,并设立共享队列借用闲置容量,当配额所有者需要时通过抢占回收资源。该系统运行于昂贵的多租户GPU集群,支持多节点训练的拓扑感知调度和弹性工作负载。具体实现中,团队拥有专用预留队列,而默认队列作为共享机会池,可借用闲置配额运行可中断工作负载。当预留队列需资源时,Kueue基于优先级和运行时间抢占默认队列中的任务,实现资源高效管理。

推荐理由

Runway 把 Kueue + Kubernetes 的 GPU 调度实战写成了保姆级工程笔记,利用率翻倍的方案和踩坑细节都有,做大规模训练集群调度的团队可以直接抄作业。

正文 · AI 翻译

我们通过将 Kueue 作为 Kubernetes 准入控制器使用,将 GPU 利用率提升了超过 20 个百分点,同时仍能保障团队的计算容量:为关键工作预留配额,设置可借用空闲容量的共享队列,并在资源所有者需要时通过抢占机制回收容量。保障容量,杜绝硬件闲置。

Runway 在大型 GPU 计算集群上训练最先进的视频生成模型。多个研究和生产团队在隔离环境中共享这些硬件:有些团队运行持续数周的预训练任务,有些团队提供实时生产推理服务,还有些团队进行短期实验迭代。该集群成本高昂且任务关键,因此调度成为重中之重。

我们需要两个通常相互冲突的目标:

  1. 保障容量。关键训练任务和对延迟敏感的服务需要可预测的 GPU 访问能力。
  2. 高利用率。闲置的 GPU 意味着预算浪费和研究进度损失。如果一个团队预留了 80 个节点但只使用了 50 个,那 30 个闲置节点每天可能代表数万美元的无效支出。

静态分区可以保障容量但浪费 GPU;完全自由竞争可以最大化利用率但无法提供任何保障。

你真正想要的是一个既能提供保障性预留,又能自动将空闲容量借给共享池,并在所属团队需要时回收的系统。为何选择 Kueue

Kueue 是一个 Kubernetes SIG 项目

kubernetes-sigs/kueue。它遵循 Kubernetes API 规范,作为准入控制器运行,而非替代调度器。这一点很重要:它在现有 Kubernetes 原语之上分层运行,而不是引入自己的调度二进制文件。其功能集涵盖了多租户 GPU 集群所需的一切:组调度、配额管理、抢占、工作负载优先级以及基于队列组的借用机制。

我们考虑过 Volcano 等替代方案,它们拥有更多功能。但 Kueue 凭借其简洁性和集成能力胜出:它与 kube-scheduler 协同工作,而非引入第二个调度器二进制文件。针对我们的使用场景(配额和准入控制,而非自定义放置算法),这个权衡是正确的选择。

Kueue 正在积极开发的两个领域对大规模训练尤为重要:拓扑感知调度(自 v0.14 起为 Beta 功能)。对于多节点训练任务,跨机架/区块/可用区的放置会影响吞吐量。弹性工作负载。在不暂停或重新排队的情况下动态扩缩已接纳任务(仍在完善中)。调度前接纳。

Kueue 位于任务提交和 Pod 创建之间。它决定一个工作负载是否应该启动。Kubernetes 的 kube-scheduler 决定已接纳的 Pod 运行在哪里。

当你提交一个任务时,Kueue 会在 Pod 被创建之前拦截它,并检查集群配额。如果配额可用,Kueue 会接纳该工作负载(将其标记为活跃状态),然后 kube-scheduler 会放置 Pod。如果配额不可用,Kueue 会将其保留在队列中。

当这两种视图一致时,系统运行得非常完美。当它们出现分歧时(而且它们一定会),你就会遇到你职业生涯中最令人困惑的调试过程。预留队列与默认池。

Kueue 的核心抽象是 ClusterQueue:一个带有资源配额以及关于如何使用该配额的规则的命名桶。

以下是我们如何在 Runway 构建队列的:

预留 ClusterQueue 专用于团队或项目。每个队列都有一个

nominalQuota(它拥有的 GPU 数量)。预留队列的 borrowingLimit 为 0:它们不从其他队列借用,但可以回收任何当前正被借用的自身配额。默认 ClusterQueue 是共享的、机会主义的池。它自身有一个较小的 nominalQuota,但可以从预留队列借用未使用的配额。当预留队列空闲或利用率不足时,默认队列会用可中断的工作来填补缺口。

思维模型:一个带有预留许可证的停车场。预留队列就是预留车位:许可证持有者保证有一个车位。默认队列是溢出停车:你可以停在任何一个空的预留车位上,但如果许可证持有者来了,你的车就会被拖走(被抢占),并且你得稍后再回来。

除了预留队列和默认队列,我们还保留了一些特殊用途的队列(例如,本地开发,以便工程师可以在真实的 GPU 上进行迭代,而无需与训练任务竞争;以及用于特征流水线和数据集准备的数据预处理)。出借空闲 GPU。

所有 ClusterQueue 都属于同一个队列组(一组可以共享资源的队列)。在队列组内,Kueue 会追踪每个队列的

名义配额和当前使用量;两者之差即为可借用的资源。示例:三个预留队列加上默认队列。

A 团队预留了 80 块 GPU,但只用了 64 块。B 团队预留了 40 块,但只用了 24 块。C 团队预留了 32 块,但一块都没用。默认队列可以借用这 64 块空闲 GPU,用于运行批量评估、实验和其他可被抢占的工作负载。

从外部看,默认队列的分配量可能很小,但实际的 GPU 使用量却很大。在底层,每一块被借用的 GPU 都归属于某个特定的预留队列,从而实现了资源回收路径。回收资源

当某个预留队列需要默认队列正在借用的容量时:

  1. Kueue 检测到该预留队列的配额不足。
  2. Kueue 会选择默认队列中的工作负载进行抢占(优先选择 Kueue 工作负载优先级最低的;若优先级相同,则选择运行时间最短的)。
  3. Kueue 会挂起被选中的工作负载(终止 Pod)。
  4. 一旦释放出足够的配额,Kueue 就会接纳该预留队列的工作负载。

这就是让这套系统运转起来的约定:团队获得保障,因为他们总能收回自己的配额;默认队列获得高利用率,因为它能接受中断。如果你将任务提交到默认队列,你的作业必须能够容忍被抢占。抢占并非瞬间完成

在实践中,从“发起抢占”到“预留作业开始运行”之间可能存在 20 到 30 分钟的间隔,原因包括:Pod 终止宽限期、由 Operator 驱动的拆除流程(例如 Ray)和排空序列,以及当默认队列大量借用资源时可能发生的级联抢占。

我们通过两种方式来缓解这个问题:Kubernetes 级别的抢占:我们给默认队列的工作负载分配一个负的 Pod 优先级类(例如 -500),这样当更高优先级的 Pod 处于待处理状态时,kube-scheduler 会主动驱逐它们。应用级别的容错:频繁的检查点、从检查点重启的逻辑以及优雅关闭处理器。两套优先级系统,两个层面

Kueue 和 Kubernetes 各自拥有一套优先级系统;它们是独立的,控制着工作负载生命周期的不同部分。

系统 控制内容 作用范围 示例
Kueue 工作负载优先级 准入排序以及队列内部/队列之间的 Kueue 级别抢占 Kueue 准入控制器 训练任务(优先级 1000)与常规评估任务(优先级 500)
Pod 优先级类别 kube-scheduler 抢占机制:节点回收的激进程度 kube-scheduler 默认 Pod(-500)会被快速驱逐;预留 Pod(0)则不会

在实践中,我们通常希望:默认队列:低 Pod 优先级(快速被驱逐)和不同的 Kueue 优先级(控制哪些任务存活最久)。预留队列:正常 Pod 优先级(0)和反映内部重要性的 Kueue 优先级(例如大型预训练任务)。当配额与现实脱节时

Kueue 基于配额而非物理节点进行决策。关键不变条件是:已分配的配额不得超过集群容量。

在我们的设置中,两个配置源必须保持同步:

  1. Kueue 预留配置(ClusterQueue 的 nominalQuota)。
  2. 节点池配置(物理容量)。

我们通过一个 CI 门禁来强制执行这一点,如果总预留量超过总静态容量,则阻止部署。

当这个不变条件被破坏时,症状会非常令人困惑:Kueue 接纳了一个工作负载(配额显示有空余),但 kube-scheduler 无法放置这些 Pod(实际上没有可用节点)。该工作负载在 Kueue 中显示为“已接纳”,但在 Kubernetes 中显示为“待处理”。抽象层断裂之处:已接纳但处于待处理状态

工作负载被 Kueue 接纳,但 Pod 始终无法调度。常见原因:配额与节点容量不一致。Kueue 未统计的 GPU 消费者(DaemonSet、调试 Pod、系统组件)。节点选择器不匹配(工作负载指向不存在或不可用的节点)。抢占速度缓慢

即使 Kueue 挂起了默认工作负载,拆除延迟也可能延迟预留任务的启动。瓶颈通常在于操作算子和关闭顺序。配额变更不会重新调度正在运行的任务

减少

nominalQuota 不会立即抢占正在运行的工作负载。Kueue 通常避免干扰已接纳的工作负载;协调操作仅在提交新任务需要时才会发生。幽灵接纳

Kueue 可能在配额在纸面上有空余时接纳一个工作负载,但物理资源尚未就绪(记账与节点现实之间存在时间差)。完整的接纳路径

分两遍阅读:正常路径:提交 → Kueue 准入(配额)→ kube-scheduler 调度(节点)→ 运行。争用路径:预留任务到达 → 默认策略是借用 → Kueue 抢占默认任务 → 准入预留任务。

反馈循环是关键:默认任务在借用的时间片内运行,当预留工作负载需要容量时便让出资源。我们学到的经验

准入与调度是清晰的边界划分,但你必须对两个层面都进行调试。大多数运维痛点源于 Kueue 的资源核算与集群物理状态之间的不匹配。能够并排展示两种视图的工具是操作体验方面最大的成功。

默认任务作为借用者的模式行之有效。为关键工作负载设置预留队列,其他一切使用默认队列并自动借用,这样无需人工管理即可保持高利用率。实践中我们的利用率约为行业标准的 2 倍。

对抢占的容忍度是文化问题。推广过程不仅仅是配置变更;它需要检查点机制、重启基础设施,以及明确告知默认任务可能被中断的预期。

保持配置同步,否则将自食其果。配额与容量之间的一致性是我们运行中最重要的约束条件。我们的 CI 门禁防止配置漂移,其避免的事故数量超过其他任何单一检查手段。

在此规模下进行 GPU 调度、分布式训练基础设施和集群编排,处于系统工程与机器学习的交叉领域。如果这些问题让你感兴趣,欢迎加入我们。这里有大量激动人心的工作等待完成。

产品 探索 示例 角色 GWM-1 通用世界模型 机器人 SDK Gen-4.5 Aleph Act-Two API

倡议 AI 峰会 2026 ↗ 工作室 AI 嘉年华 ↗ Gen:48 学院 ↗ 资源 创意合作伙伴计划 Runway Builders

公司 我们的研究 出版物 职业 关于我们 客户故事 新闻 人才网络 ↗ 安全

开始使用 面向企业 面向教育 登录 定价 帮助中心 ↗ 数据安全 更新日志

联系 媒体 合作伙伴关系 品牌指南 聚会 ↗ Twitter ↗ Instagram ↗ YouTube ↗ Discord ↗

来源:Runway:News(网页) · runwayml.com

无闲置GPU:Runway的研究计算管理

Runway:News(网页)·2026-04-27 00:00·100天前·Matt Kafonek and Brannon Dorsey, Platform Engineering
AI 导读

Runway通过采用Kueue作为Kubernetes准入控制器,将GPU利用率提升超过20%,同时保障团队容量。其核心机制是为关键工作预留配额,并设立共享队列借用闲置容量,当配额所有者需要时通过抢占回收资源。该系统运行于昂贵的多租户GPU集群,支持多节点训练的拓扑感知调度和弹性工作负载。具体实现中,团队拥有专用预留队列,而默认队列作为共享机会池,可借用闲置配额运行可中断工作负载。当预留队列需资源时,Kueue基于优先级和运行时间抢占默认队列中的任务,实现资源高效管理。

正文 · AI 翻译

我们通过将 Kueue 作为 Kubernetes 准入控制器使用,将 GPU 利用率提升了超过 20 个百分点,同时仍能保障团队的计算容量:为关键工作预留配额,设置可借用空闲容量的共享队列,并在资源所有者需要时通过抢占机制回收容量。保障容量,杜绝硬件闲置。

Runway 在大型 GPU 计算集群上训练最先进的视频生成模型。多个研究和生产团队在隔离环境中共享这些硬件:有些团队运行持续数周的预训练任务,有些团队提供实时生产推理服务,还有些团队进行短期实验迭代。该集群成本高昂且任务关键,因此调度成为重中之重。

我们需要两个通常相互冲突的目标:

  1. 保障容量。关键训练任务和对延迟敏感的服务需要可预测的 GPU 访问能力。
  2. 高利用率。闲置的 GPU 意味着预算浪费和研究进度损失。如果一个团队预留了 80 个节点但只使用了 50 个,那 30 个闲置节点每天可能代表数万美元的无效支出。

静态分区可以保障容量但浪费 GPU;完全自由竞争可以最大化利用率但无法提供任何保障。

你真正想要的是一个既能提供保障性预留,又能自动将空闲容量借给共享池,并在所属团队需要时回收的系统。为何选择 Kueue

Kueue 是一个 Kubernetes SIG 项目

kubernetes-sigs/kueue。它遵循 Kubernetes API 规范,作为准入控制器运行,而非替代调度器。这一点很重要:它在现有 Kubernetes 原语之上分层运行,而不是引入自己的调度二进制文件。其功能集涵盖了多租户 GPU 集群所需的一切:组调度、配额管理、抢占、工作负载优先级以及基于队列组的借用机制。

我们考虑过 Volcano 等替代方案,它们拥有更多功能。但 Kueue 凭借其简洁性和集成能力胜出:它与 kube-scheduler 协同工作,而非引入第二个调度器二进制文件。针对我们的使用场景(配额和准入控制,而非自定义放置算法),这个权衡是正确的选择。

Kueue 正在积极开发的两个领域对大规模训练尤为重要:拓扑感知调度(自 v0.14 起为 Beta 功能)。对于多节点训练任务,跨机架/区块/可用区的放置会影响吞吐量。弹性工作负载。在不暂停或重新排队的情况下动态扩缩已接纳任务(仍在完善中)。调度前接纳。

Kueue 位于任务提交和 Pod 创建之间。它决定一个工作负载是否应该启动。Kubernetes 的 kube-scheduler 决定已接纳的 Pod 运行在哪里。

当你提交一个任务时,Kueue 会在 Pod 被创建之前拦截它,并检查集群配额。如果配额可用,Kueue 会接纳该工作负载(将其标记为活跃状态),然后 kube-scheduler 会放置 Pod。如果配额不可用,Kueue 会将其保留在队列中。

当这两种视图一致时,系统运行得非常完美。当它们出现分歧时(而且它们一定会),你就会遇到你职业生涯中最令人困惑的调试过程。预留队列与默认池。

Kueue 的核心抽象是 ClusterQueue:一个带有资源配额以及关于如何使用该配额的规则的命名桶。

以下是我们如何在 Runway 构建队列的:

预留 ClusterQueue 专用于团队或项目。每个队列都有一个

nominalQuota(它拥有的 GPU 数量)。预留队列的 borrowingLimit 为 0:它们不从其他队列借用,但可以回收任何当前正被借用的自身配额。默认 ClusterQueue 是共享的、机会主义的池。它自身有一个较小的 nominalQuota,但可以从预留队列借用未使用的配额。当预留队列空闲或利用率不足时,默认队列会用可中断的工作来填补缺口。

思维模型:一个带有预留许可证的停车场。预留队列就是预留车位:许可证持有者保证有一个车位。默认队列是溢出停车:你可以停在任何一个空的预留车位上,但如果许可证持有者来了,你的车就会被拖走(被抢占),并且你得稍后再回来。

除了预留队列和默认队列,我们还保留了一些特殊用途的队列(例如,本地开发,以便工程师可以在真实的 GPU 上进行迭代,而无需与训练任务竞争;以及用于特征流水线和数据集准备的数据预处理)。出借空闲 GPU。

所有 ClusterQueue 都属于同一个队列组(一组可以共享资源的队列)。在队列组内,Kueue 会追踪每个队列的

名义配额和当前使用量;两者之差即为可借用的资源。示例:三个预留队列加上默认队列。

A 团队预留了 80 块 GPU,但只用了 64 块。B 团队预留了 40 块,但只用了 24 块。C 团队预留了 32 块,但一块都没用。默认队列可以借用这 64 块空闲 GPU,用于运行批量评估、实验和其他可被抢占的工作负载。

从外部看,默认队列的分配量可能很小,但实际的 GPU 使用量却很大。在底层,每一块被借用的 GPU 都归属于某个特定的预留队列,从而实现了资源回收路径。回收资源

当某个预留队列需要默认队列正在借用的容量时:

  1. Kueue 检测到该预留队列的配额不足。
  2. Kueue 会选择默认队列中的工作负载进行抢占(优先选择 Kueue 工作负载优先级最低的;若优先级相同,则选择运行时间最短的)。
  3. Kueue 会挂起被选中的工作负载(终止 Pod)。
  4. 一旦释放出足够的配额,Kueue 就会接纳该预留队列的工作负载。

这就是让这套系统运转起来的约定:团队获得保障,因为他们总能收回自己的配额;默认队列获得高利用率,因为它能接受中断。如果你将任务提交到默认队列,你的作业必须能够容忍被抢占。抢占并非瞬间完成

在实践中,从“发起抢占”到“预留作业开始运行”之间可能存在 20 到 30 分钟的间隔,原因包括:Pod 终止宽限期、由 Operator 驱动的拆除流程(例如 Ray)和排空序列,以及当默认队列大量借用资源时可能发生的级联抢占。

我们通过两种方式来缓解这个问题:Kubernetes 级别的抢占:我们给默认队列的工作负载分配一个负的 Pod 优先级类(例如 -500),这样当更高优先级的 Pod 处于待处理状态时,kube-scheduler 会主动驱逐它们。应用级别的容错:频繁的检查点、从检查点重启的逻辑以及优雅关闭处理器。两套优先级系统,两个层面

Kueue 和 Kubernetes 各自拥有一套优先级系统;它们是独立的,控制着工作负载生命周期的不同部分。

系统 控制内容 作用范围 示例
Kueue 工作负载优先级 准入排序以及队列内部/队列之间的 Kueue 级别抢占 Kueue 准入控制器 训练任务(优先级 1000)与常规评估任务(优先级 500)
Pod 优先级类别 kube-scheduler 抢占机制:节点回收的激进程度 kube-scheduler 默认 Pod(-500)会被快速驱逐;预留 Pod(0)则不会

在实践中,我们通常希望:默认队列:低 Pod 优先级(快速被驱逐)和不同的 Kueue 优先级(控制哪些任务存活最久)。预留队列:正常 Pod 优先级(0)和反映内部重要性的 Kueue 优先级(例如大型预训练任务)。当配额与现实脱节时

Kueue 基于配额而非物理节点进行决策。关键不变条件是:已分配的配额不得超过集群容量。

在我们的设置中,两个配置源必须保持同步:

  1. Kueue 预留配置(ClusterQueue 的 nominalQuota)。
  2. 节点池配置(物理容量)。

我们通过一个 CI 门禁来强制执行这一点,如果总预留量超过总静态容量,则阻止部署。

当这个不变条件被破坏时,症状会非常令人困惑:Kueue 接纳了一个工作负载(配额显示有空余),但 kube-scheduler 无法放置这些 Pod(实际上没有可用节点)。该工作负载在 Kueue 中显示为“已接纳”,但在 Kubernetes 中显示为“待处理”。抽象层断裂之处:已接纳但处于待处理状态

工作负载被 Kueue 接纳,但 Pod 始终无法调度。常见原因:配额与节点容量不一致。Kueue 未统计的 GPU 消费者(DaemonSet、调试 Pod、系统组件)。节点选择器不匹配(工作负载指向不存在或不可用的节点)。抢占速度缓慢

即使 Kueue 挂起了默认工作负载,拆除延迟也可能延迟预留任务的启动。瓶颈通常在于操作算子和关闭顺序。配额变更不会重新调度正在运行的任务

减少

nominalQuota 不会立即抢占正在运行的工作负载。Kueue 通常避免干扰已接纳的工作负载;协调操作仅在提交新任务需要时才会发生。幽灵接纳

Kueue 可能在配额在纸面上有空余时接纳一个工作负载,但物理资源尚未就绪(记账与节点现实之间存在时间差)。完整的接纳路径

分两遍阅读:正常路径:提交 → Kueue 准入(配额)→ kube-scheduler 调度(节点)→ 运行。争用路径:预留任务到达 → 默认策略是借用 → Kueue 抢占默认任务 → 准入预留任务。

反馈循环是关键:默认任务在借用的时间片内运行,当预留工作负载需要容量时便让出资源。我们学到的经验

准入与调度是清晰的边界划分,但你必须对两个层面都进行调试。大多数运维痛点源于 Kueue 的资源核算与集群物理状态之间的不匹配。能够并排展示两种视图的工具是操作体验方面最大的成功。

默认任务作为借用者的模式行之有效。为关键工作负载设置预留队列,其他一切使用默认队列并自动借用,这样无需人工管理即可保持高利用率。实践中我们的利用率约为行业标准的 2 倍。

对抢占的容忍度是文化问题。推广过程不仅仅是配置变更;它需要检查点机制、重启基础设施,以及明确告知默认任务可能被中断的预期。

保持配置同步,否则将自食其果。配额与容量之间的一致性是我们运行中最重要的约束条件。我们的 CI 门禁防止配置漂移,其避免的事故数量超过其他任何单一检查手段。

在此规模下进行 GPU 调度、分布式训练基础设施和集群编排,处于系统工程与机器学习的交叉领域。如果这些问题让你感兴趣,欢迎加入我们。这里有大量激动人心的工作等待完成。

产品 探索 示例 角色 GWM-1 通用世界模型 机器人 SDK Gen-4.5 Aleph Act-Two API

倡议 AI 峰会 2026 ↗ 工作室 AI 嘉年华 ↗ Gen:48 学院 ↗ 资源 创意合作伙伴计划 Runway Builders

公司 我们的研究 出版物 职业 关于我们 客户故事 新闻 人才网络 ↗ 安全

开始使用 面向企业 面向教育 登录 定价 帮助中心 ↗ 数据安全 更新日志

联系 媒体 合作伙伴关系 品牌指南 聚会 ↗ Twitter ↗ Instagram ↗ YouTube ↗ Discord ↗

来源:Runway:News(网页)· runwayml.com