角色
只有两种。
管理员专属接口对
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 后端读取这个字段:local 和 node 后端的分配器按索引发整卡,不认识切片,
在那里声明一个切片等于宣告一份放不下去的容量。
审批:一条升级路径,不是流程引擎
团队在 3 号就花光当月预算,作业会排 28 天。排队是对的默认——条件会自己消失,拒了等于 让人三周后再提一次——但总得有办法说”这个真的等不了”,并且留下是谁说的。 它不接在准入里。 显而易见的做法是给_SUBMIT_DISPOSITION 加第三个动词:超预算就转审批。
那是错的,而且理由可以推广:团队配额往往几分钟内就随同事作业结束而解除,把每一次这样的拒绝
都送给人,只会得到一队还没被读就自己有答案的请求,以及一个学会无视这个列表的审批人。
所以升级是主动发起的:作业照常排队,提交人在确实等不了时去作业详情页申请一次例外。
一次批准只放行一个作业。 不是这个团队,不是这个月,也不是”直到有人想起来撤销”。
一个活得比它的理由更久的授权,就是预算不再是预算的开始;而一个范围很窄的授权,才是审批人
在他会花的那十秒里真的能想清楚的东西。
审批人是拥有那笔预算的团队的负责人(管理员兜底——总得有人能答,当团队没有负责人、
或唯一的负责人正是申请人时)。没有人能批准自己的申请;驳回自己的可以,撤回不需要第二个人。
配额变更申请一律由管理员批:团队负责人批准自己的加额,那不叫额度。
刻意不做的
一级审批,加一个有效期。没有会签、加签、转办、代理。那些属于组织已经在用的 OA 系统—— 在这里重造一遍只会得到一个更差的副本,而且没有哪个合规部门会认。平台欠那套系统的是 一条记录和一个回调,不是一套流程引擎。 没人回应的请求会在有效期后自动过期。一个只增不减的待办列表没有人会读,而真正要紧的那条 就埋在里面。从单点登录同步团队
配置FORGE_OIDC_GROUP_CLAIM 后,每次登录用目录里的组覆盖此人的团队成员关系——
加也删:在 IdP 里离开了某个部门,这里也就离开了。留空(默认)表示平台完全不碰
成员关系,手工维护团队的部署必须留空,否则下次登录会把所有人清出去。
目录里有、平台上没有的组会被跳过,不会自动建团队:一个 IdP 组不构成「创建一个预算
承担方」的授权。FORGE_OIDC_GROUP_PREFIX 用来去掉目录下发的路径前缀。
默认是软的
FORGE_QUOTA_ENFORCE=false 只记录用量,不拒绝任何东西。
在你还在摸索这些数字该设多少时它很有用,摸索完还开着就很危险。
即使打开了执法,裸金属 Ray 也没有 cgroup 或 GPU 硬隔离,所以准入是作业启动之前的一道闸。
运行时看门狗是第二层:它把集群实际用量与台账对账,
并且可以停掉能可靠归因的超额作业。硬配额需要 Kubernetes 或 Kueue 一类的基础设施。
读懂一次拒绝
最后一行是重要的区分:在队列里排队不是配额失败。排队的作业是已经被准入的。