Skip to main content

角色

只有两种。 管理员专属接口对 operator 的 token 返回 403 而不是 401——token 没问题,权限有问题。 新账号默认是 operator;启用单点登录时,FORGE_OIDC_DEFAULT_ROLE 决定首次登录的人拿到什么角色。

配额的几个维度

配额按用户设置,五项互相独立:
int
默认值:"8"
这个用户同时最多能占多少张卡,跨他所有运行中的作业统计。精确——准入在下发前就核算。
int
默认值:"4"
同时能跑多少个作业,不看大小。防止一个人用小作业把队列占满。
int
默认值:"0"
每日 GPU-时。0 表示不限。天的边界按服务时区计算。
int
默认值:"0"
这个用户的 run 目录最多能占多少。0 表示不限。是测量而不是预留,所以最终一致。
逗号分隔
默认值:"全部"
这个用户可以申请哪些硬件 profile。留空表示全部。
另外还有 priority,在 priority-fifo 策略下决定队列顺序; 以及一份按卡型的映射——{卡型: {max_concurrent_gpus, daily_gpu_hours}}—— 用于异构集群上一个全局数字不够用的情况。

团队配额

多个部门共用一套集群时,个人配额不够用:八个人各占四张卡,每个人都在自己额度内, 合起来是一个部门三十二张卡。团队配额管的是后者。 一次运行的预算由它所属项目的团队决定,不由提交人决定。 这条是整个模型的关键: 一个人可以同时属于多个团队,只有「项目」能唯一回答「这笔算力算谁的」。作业提交时 就把团队记在作业行上,之后把项目转到别的团队也不会改写已经跑过的账——和 gpu_seconds 在终态冻结是同一条规则。 在控制台 管理 → 团队 建团队、配额度、管成员;项目的归属在项目设置里改(仅管理员)。 两条与个人配额相反的语义,值得单独记住:
  • 团队没配配额 = 不限,不是禁止。个人配额是反过来的(没配 = 不许提交), 那是刻意的 deny-by-default;照搬到团队上,就会变成「建一个团队立刻把里面所有人卡死」。
  • 管理员不豁免团队配额。 个人配额豁免的含义是「这个人可以信任」;跳过团队预算 花的是别的部门的钱,管理员身份不构成对它的主张。
被团队配额拦下的作业排队而不是被拒:这是同事的作业跑完就会解除的共享状况, 拒了等于逼人手动重提一次平台自己就能等的事。

计费

平台一直精确地计量 GPU 卡时,并把它归到项目、人和团队上。计费在这之上只多一个单价 它不重新计量任何东西:卡时来自和用量页同一份台账,归期规则也和 cost_breakdown 一致—— 按作业结束的时间段计入。跨月的长作业整段算在它结束的那个月;仍在跑的作业按已跑部分 计入当期并单独标出。一份和用量页对不上的账单,比没有账单更糟:它是一场谁也说不清的争论, 而用量页是大家已经信的那个数。 在控制台 管理 → 计费 看账单,可按团队 / 项目 / 用户三个维度归集,导出 Excel。

价目表

单价按卡型配,带生效时间。规则两条:
  • 某卡型的第一条价格覆盖全部历史——此前没有任何账单存在,没有可被重写的已结账期。 刚开启计费的部署因此可以给已经跑过的季度定价,那是所有人问的第一件事。
  • 之后的价格不能往回改,那会重写已经给人看过、并且已经被据以行动的账。调价 = 加一条 生效时间更晚的新记录;价目只增不改。
产生了卡时但没有生效单价的卡型会被点名unpriced_series),那部分按 0 计。 一个悄悄漏掉某个卡型的确定数字,比一个说清自己漏了什么的数字糟得多。 金额全程用整数微单位(百万分之一货币单位)计算,只在渲染时取整——浮点不是用来加钱的, 每次运行漂一分钱,最后就是一个谁也对不上的总额。

月度预算

团队可以设一个按自然月的金额预算(服务时区的月界)。超了之后新作业排队而不是被拒—— 月初自己就恢复了,而被告知”十一天后再提一次”的人不会真的去提。 预算读的是已花,不是预测:没人知道一个还没跑的作业会花多少。所以越线的那个作业总是被 允许跑完——超出的部分是它跑出来的,不是它被放行时就注定的。与日卡时预算是同一个形状, 只是上了一层、并且以钱计。

借用与回收(抢占)

静态配额会把集群切碎,然后让它闲置——这是所有共享集群最后都会有的抱怨,也是 Kueue(reclaimWithinCohort)、Volcano(deserved + reclaim)、YARN(guaranteed vs maximum capacity)、Slurm(QOS 抢占)不约而同长出借用的原因。 开启 FORGE_SCHED_PREEMPTION 后,团队的并发 GPU 配额从「上限」变成「保底」:
  • 集群有空时,团队可以超出保底额度运行(容量本身仍由 capacity_gate 按物理卡数兜住)
  • 低于自己保底额度的团队在排队且被容量拦下时,超出部分被回收
借用和回收是同一个开关。 只借不收,会让一个团队无限期占住集群、而别的团队在自己的 配额之内干等——那比它取代的硬上限更糟。

什么可以被回收,尽可能窄地说

五个条件全部成立才算候选,每一条都对应一种「没有它就会让人有理由生气」的情况: 最年轻的,因为那是丢掉最少的活。刻意不用优先级:优先级排的是「接下来轮到谁」, 拿它来选受害者会让一个高优先级的长作业安全、而一分钟前刚起的高优先级作业被拿掉—— 两个问题用了同一个数字。

回收做的事就是暂停

平台早就有这条路,而且语义正好:PAUSED(auto_resume)系统侧暂停(维护排空和 时段执法用的就是它),计量在暂停那一刻就停止计费,工作目录保留,队列 worker 会自动从最近 checkpoint 续跑。被回收的人不需要做任何事,也会收到站内通知说明原因。 代价是诚实且有界的:最近一次 checkpoint 之后的进度。NeMo-RL 默认每 save_period 步落盘, 所以是分钟级。

切分 GPU(MIG / 时分)

只需要在硬件注册表里加一行。 NVIDIA GPU Operator 会把 MIG 切片作为独立的扩展资源上报 (nvidia.com/mig-3g.40gb),时分切片报成 nvidia.com/gpu.shared。在管理 → 平台设置 → 硬件里把它注册成一个卡型,并填上 k8s_resource,它就自动获得独立的容量、配额、计量和 时段窗口——因为这四样本来就是按卡型 id 组织的。 调度器一行都不用改。 切卡是硬件注册表的一条记录,不是一个调度特性。 仅 kuberay 后端读取这个字段:localnode 后端的分配器按索引发整卡,不认识切片, 在那里声明一个切片等于宣告一份放不下去的容量。

审批:一条升级路径,不是流程引擎

团队在 3 号就花光当月预算,作业会排 28 天。排队是对的默认——条件会自己消失,拒了等于 让人三周后再提一次——但总得有办法说”这个真的等不了”,并且留下是谁说的。 它不接在准入里。 显而易见的做法是给 _SUBMIT_DISPOSITION 加第三个动词:超预算就转审批。 那是错的,而且理由可以推广:团队配额往往几分钟内就随同事作业结束而解除,把每一次这样的拒绝 都送给人,只会得到一队还没被读就自己有答案的请求,以及一个学会无视这个列表的审批人。 所以升级是主动发起的:作业照常排队,提交人在确实等不了时去作业详情页申请一次例外。 一次批准只放行一个作业。 不是这个团队,不是这个月,也不是”直到有人想起来撤销”。 一个活得比它的理由更久的授权,就是预算不再是预算的开始;而一个范围很窄的授权,才是审批人 在他会花的那十秒里真的能想清楚的东西。 审批人是拥有那笔预算的团队的负责人(管理员兜底——总得有人能答,当团队没有负责人、 或唯一的负责人正是申请人时)。没有人能批准自己的申请;驳回自己的可以,撤回不需要第二个人。 配额变更申请一律由管理员批:团队负责人批准自己的加额,那不叫额度。

刻意不做的

一级审批,加一个有效期。没有会签、加签、转办、代理。那些属于组织已经在用的 OA 系统—— 在这里重造一遍只会得到一个更差的副本,而且没有哪个合规部门会认。平台欠那套系统的是 一条记录和一个回调,不是一套流程引擎。 没人回应的请求会在有效期后自动过期。一个只增不减的待办列表没有人会读,而真正要紧的那条 就埋在里面。

从单点登录同步团队

配置 FORGE_OIDC_GROUP_CLAIM 后,每次登录用目录里的组覆盖此人的团队成员关系—— 加也删:在 IdP 里离开了某个部门,这里也就离开了。留空(默认)表示平台完全不碰 成员关系,手工维护团队的部署必须留空,否则下次登录会把所有人清出去。 目录里有、平台上没有的组会被跳过,不会自动建团队:一个 IdP 组不构成「创建一个预算 承担方」的授权。FORGE_OIDC_GROUP_PREFIX 用来去掉目录下发的路径前缀。

默认是软的

FORGE_QUOTA_ENFORCE=false 只记录用量,不拒绝任何东西。 在你还在摸索这些数字该设多少时它很有用,摸索完还开着就很危险。 即使打开了执法,裸金属 Ray 也没有 cgroup 或 GPU 硬隔离,所以准入是作业启动之前的一道闸。 运行时看门狗是第二层:它把集群实际用量与台账对账, 并且可以停掉能可靠归因的超额作业。硬配额需要 Kubernetes 或 Kueue 一类的基础设施。

读懂一次拒绝

最后一行是重要的区分:在队列里排队不是配额失败。排队的作业是已经被准入的。

审计

创建用户、设置角色、启用或禁用账号、设置配额,全都会连同操作的管理员一起记进 审计日志。每一次因配额被拒的提交也会记—— 这就是为什么错误信息滚走之后,「我的作业为什么没跑」仍然回答得出来。