来源:SchedMD Slurm 官方文档《Licenses Guide》。本文于 2026 年 10 月 5 日依完整源文译编,原页无个人作者署名。本文中的终端输出均为原文案例或从其数字整理的表格,不是本次执行结果。
商业软件许可数量有限时,Slurm 可以把可用许可作为调度资源分配给作业。资源不足,作业继续等待;资源可用,作业才有机会进入运行。这里的许可不是绑定某台计算节点的资源,而是与整个集群关联的共享资源。
对于两个甚至更多集群,关键问题是:总许可池有多少,每个集群可以使用多少,调度器看到的数量是否与真实许可服务器保持一致。Slurm 的本地许可配置与远程许可资源分别解决不同范围的问题。本文以两个集群共享 Nastran 与 Matlab 许可为主线,覆盖创建、查看、调整、删除关联,以及动态计数的边界。

本地许可与远程许可
本地许可写在当前集群的 slurm.conf 中,使用 Licenses 选项:
Licenses=fluent:30,ansys:100
用 scontrol show lic 查看时,原文案例里 ansys 的 Total=100、Used=0、Free=100,fluent 则为 30、0、30,二者均显示 Remote=no。提交时通过 -L 或 --licenses 申请:
sbatch -L ansys:2 script.sh
scontrol show lic
在原文展示的作业已获得两份许可的状态下,ansys 变为 Used=2、Free=98。仅提交命令成功并不意味着此时已经获得许可;作业仍可能排队,实际应以集群状态为准。
也可以使用 --tres-per-task 申请许可,但相应许可还必须写入 AccountingStorageTRES:
Licenses=fluent:30
AccountingStorageTRES=license/fluent
sbatch --tres-per-task=license/fluent:4 script.sh
原文的这一案例随后显示 Total=30 Used=4 Free=26 Reserved=0 Remote=no。这是按任务请求资源的接口,规划多任务作业时应按实际任务数量和版本语义核对,不能直接把单个案例的总消耗搬到其他作业上。
远程许可由数据库保存,通过 sacctmgr 配置;变更后,slurmdbd 会把更新发送给分配了该资源的集群。
远程许可不会自行连接 FlexNet、Reprise 等第三方许可管理器。创建资源时的 Server 和 ServerType 仅是信息字段,不意味着自动集成已经发生。管理员仍需控制真实许可的领取路径,并实现必要的计数同步。否则,Slurm 可能认为许可足够,而应用实际启动后拿不到许可。
案例:两个许可池、两个集群
假设一个 FlexNet 服务器提供 100 份 Nastran 许可,另一台 Reprise License Management 服务器提供 50 份 Matlab 许可。两个计算集群名为 fluid 和 pdf。管理员希望 Nastran 对半分配;Matlab 的 70% 分配给 pdf,30% 分配给 fluid。
前提是两个集群已经在 SlurmDBD 中正确配置。先进行只读核验:
sacctmgr show clusters format=cluster,controlhost
原文输出列出 fluid 与 pdf 各自的控制主机。本文不把原文展示的主机 IP 作为部署目标;实际操作必须以自己管理的集群记录为准。后续命令会修改调度数据库,不能作为普通本地演示随意运行。
一次创建 Nastran,分步分配 Matlab
Nastran 两个集群的份额相同,可一次完成资源创建和分配:
sacctmgr add resource name=nastran cluster=fluid,pdf \
count=100 allowed=50 server=flex_host servertype=flexlm type=license
这会创建 nastran@flex_host,总量 Count=100,两个集群各自 Allowed=50。在本节没有启用 Absolute 标志,因此 Allowed 表示百分比:每个集群得到总池的 50%,也就是 50 份。
Matlab 的份额不同,可以先建资源,再分别添加集群关联:
sacctmgr add resource name=matlab count=50 server=rlm_host \
servertype=rlm type=license
sacctmgr add resource name=matlab server=rlm_host \
cluster=pdf allowed=70
sacctmgr add resource name=matlab server=rlm_host \
cluster=fluid allowed=30
资源的完整标识为 matlab@rlm_host。这里的 flex_host、rlm_host 是原文的示例标识,不能仅因填入了它们,就认为 Slurm 已经联系上真实服务器。
分两层核验:数据库分配与集群可见额度
sacctmgr show resource
sacctmgr show resource withclusters
第一条查看许可池总量,第二条展开每个集群的关联。原文创建完成后,两个资源的 Allocated 都是 100;在百分比模式下,这是分配比例总和 100%,不是把 Matlab 的 50 份许可变成了 100 份。
| 资源 | Count | 集群 | Allowed | 应分得的数量 |
|---|---|---|---|---|
nastran@flex_host |
100 | fluid | 50% | 50 |
nastran@flex_host |
100 | 50% | 50 | |
matlab@rlm_host |
50 | fluid | 30% | 15 |
matlab@rlm_host |
50 | 70% | 35 |
再分别在两个集群查看控制器看到的许可:
scontrol show lic
原文中,pdf 上的 Matlab 是 Total=35 Used=0 Free=35,Nastran 是 Total=50 Used=0 Free=50;fluid 上的 Matlab 为 15、0、15,Nastran 为 50、0、50。四条均显示 Remote=yes,并带有 Reserved、LastConsumed、LastDeficit 和 LastUpdate 字段。源文输出中的 2023 年时间戳是历史示例,不是当前同步状态的证据。
申请远程许可时,默认必须同时写资源名称与服务器:
sbatch -L nastran@flex_host script.sh
默认只支持小写资源名。Slurm 26.05 起,可在 slurmdbd.conf 中设置 Parameters=PreserveCaseResource 允许大写;同样从 26.05 起,slurm.conf 的 LicenseParameters=RemoteFuzzyMatch 可以允许申请时省略服务器。本文保留完整标识,避免把新版的可选行为误当作所有集群都具备的默认行为。
调整总量与分配比例
如果 Matlab 总池增加到 200 份,先修改资源总量,再把 pdf 的比例从 70% 改为 60%:
sacctmgr modify resource name=matlab server=rlm_host set count=200
sacctmgr modify resource name=matlab server=rlm_host \
cluster=pdf set allowed=60
sacctmgr show resource withclusters
fluid 仍保留 30%,因此两者的总分配比例变为 90%。按案例数字,fluid 的额度为 60,pdf 为 120,剩余 20 份没有通过这两个关联分配出去。这里的数量是从文档输入计算得到的,真实控制器是否已接收变更仍须用 scontrol 核验。
删除某个关联,还是删除整个资源
下面两种操作影响范围不同。第一条仅删除 Matlab 与 fluid 的关联;第二条删除整个 Nastran 资源及其集群关联。它们是原文的管理示例,会修改数据库,本次未执行。
# 删除一个集群关联
sacctmgr delete resource where name=matlab server=rlm_host cluster=fluid
# 删除整个资源及其所有集群关联
sacctmgr delete resource where name=nastran server=flex_host
sacctmgr show resource withclusters
按原文顺序完成后,展开列表只剩 Matlab 与 pdf 的关联,Count=200、Allocated=60、Allowed=60。删除前应确认目标资源、服务器和集群谓词,并保存现有分配记录以便恢复;省略 cluster 不是无关紧要的缩写。
Absolute:让 Allowed 直接表示份数
Slurm 23.02 引入 Absolute 标志。启用后,集群的 Allowed 表示绝对许可份数,不再是百分比。原文用一个总池 150 份、两个集群各分 70 份的 deluxe 资源说明这一点。
下面是对原文命令的明确改写:去掉自动确认的 -i,补上 type=license,并在更新时写出 name、server 和 cluster,使目标更清楚。原文创建输出一度显示 Type=Unknown,随后查询显示 License;本文不把这处展示不一致当作需要依赖的行为。
sacctmgr add resource name=deluxe cluster=fluid,pdf count=150 allowed=70 \
server=flex_host servertype=flexlm type=license flags=absolute
sacctmgr show resource withclusters
sacctmgr modify resource where name=deluxe server=flex_host cluster=fluid \
set allowed=25
sacctmgr show resource withclusters
初始合计分出 140 份;把 fluid 改成 25 份后,pdf 仍为 70 份,合计 95 份。注意此时 Allocated=95 的单位也是份数。若希望所有新建资源默认使用此模式,原文给出的选项是 slurmdbd.conf 中的 AllResourcesAbsolute=yes,修改后需重启 SlurmDBD 才生效;本文没有实施这一服务变更。
SharedPool:共享全池不是避免争抢的保证
Slurm 26.05 新增 SharedPool,允许每个集群访问完整许可池,不再要求预先分配部分份额。代价是每个集群都可能调度到 Count 的规模,一个集群耗尽许可后,另一个集群的作业可能卡在真实许可领取环节。
这种模式要求每个集群的 Allowed 为 0 或完整的 Count/100%,不支持部分份额,因为部分分配会与跨集群应用 LastConsumed 的方式冲突。原文强烈建议配合动态许可,让真实服务器的当前使用情况进入调度判断。旧版集群不能假定认识此标志。
动态许可:同步 LastConsumed,而不是虚构自动集成
从 Slurm 23.02 起,远程许可的 LastConsumed 用于定期接收真实许可服务器报告的使用量。更新此字段后,SlurmDBD 会把变更推送到控制器;控制器据此计算 LastDeficit,表示从集群视角“去向不明”、需要临时扣留的许可数量。
原文为 FlexLM 的 lmstat 提供了下面的简短脚本。它仅是集成思路示例,不是已经适配任意许可服务器的生产方案;下列内容原样保留供静态审查,没有运行。
#!/bin/bash
set -euxo pipefail
LMSTAT=/opt/foobar/bin/lmstat
LICENSE=foobar
consumed=$(${LMSTAT} | grep "Users of ${LICENSE}"|sed "s/.*Total of \([0-9]\+\) licenses in use)/\1/")
sacctmgr -i update resource ${LICENSE} set lastconsumed=${consumed}
这里有几处实际风险:解析依赖特定输出文字和正则格式;多条匹配或格式变化可能令结果不是一个整数;变量展开缺少引号会产生分词和通配符展开;更新只按资源名定位,未明确服务器;-i 跳过确认,而 set -x 会把命令及展开内容记入跟踪日志。这个固定示例没有秘密,也没有 eval,不能夸大成已证明的任意 shell 代码执行;但如果直接接入外部输出,它缺少必要的数据和目标验证。
下面给出一个静态改写的只读预览器。它读取一份已经保存的 lmstat 文本,要求恰好找到一条对应功能的使用记录,只打印待核对的更新命令。与原文不同,它不调用许可服务器、不执行 sacctmgr、不自动把解析失败当作 0,也不绕过确认。该解析器本身同样未执行测试,真实输出格式仍需管理员核验。
#!/usr/bin/env bash
set -euo pipefail
LICENSE=foobar
SERVER=slurmdb
[[ $# -eq 1 ]] || { printf '用法: preview.sh lmstat-report.txt\n' >&2; exit 2; }
consumed=$(awk -v feature="$LICENSE" '
$1 == "Users" && $2 == "of" && $3 == feature ":" {
if (match($0, /Total of [0-9]+ licenses in use/)) {
value = substr($0, RSTART, RLENGTH)
gsub(/[^0-9]/, "", value)
count++
}
}
END {
if (count != 1) exit 1
print value
}
' -- "$1") || { printf '记录缺失、多义或格式不符;停止。\n' >&2; exit 1; }
[[ "$consumed" =~ ^[0-9]+$ ]] || { printf '使用量不是非负整数。\n' >&2; exit 1; }
printf '预览(未执行):sacctmgr modify resource where name=%q server=%q set lastconsumed=%q\n' \
"$LICENSE" "$SERVER" "$consumed"
预览通过后,仍需核对服务器、资源名、时间戳、总量和采集权限,再设计正式同步。旧值或失败的采集不应伪装为最新的零使用量。计数更新也不是分布式许可领取的原子锁,不能替代商业许可服务器自身的授权控制。
用数字理解 LastDeficit
原文最后的案例总池为 100 份,blackhole 集群按绝对数量分得 80 份。初始该集群未使用许可:
sacctmgr add resource foobar count=100 flags=absolute cluster=blackhole allowed=80
scontrol show license
示例资源默认显示为 foobar@slurmdb,控制器初始为 Total=80 Used=0 Free=80。若真实服务器报告总使用量为 30,则集群原本知道池外最多可用 20 份,额外的 10 份便形成缺口。源文更新后的输出是:
LicenseName=foobar@slurmdb
Total=80 Used=0 Free=70 Reserved=0 Remote=yes
LastConsumed=30 LastDeficit=10
当 LastConsumed 降到 20 时,这 20 份可以完全由集群以外的预留份额解释,缺口归零,该集群又可使用 80 份:
LicenseName=foobar@slurmdb
Total=80 Used=0 Free=80 Reserved=0 Remote=yes
LastConsumed=20 LastDeficit=0
原文勘误:这一段英文说明写成“降到 10”,紧随其后的命令却是 lastconsumed=20,输出同样为 20。本文采用命令与输出一致的 20,并在此保留差异;若降到 10,在这个特定数字案例中同样不会出现缺口,但那不是原文展示的命令。
静态审查结论与版本范围
本文完整核对了本地许可、远程资源、百分比与绝对份数、SharedPool、动态使用量及删除范围,没有连接 SlurmDBD、提交作业、运行脚本或执行任何删除操作。修改命令的风险在于错误集群、错误资源以及立即影响调度;第三方许可输出和跨集群并发行为没有通过实机验证。没有发现固定示例中含秘密不等于此类集成没有漏洞。
基础示例与新增功能不能混为同一版本承诺:Absolute、LastConsumed 的动态用途起于 23.02;SharedPool、保留资源名大小写和远程模糊匹配起于 26.05。部署前应对照自己安装版本的 sacctmgr 手册、slurm.conf 与 slurmdbd.conf,并按正常变更流程核验实际调度状态。
原文:SchedMD · Licenses Guide。版权与原文归属保留给 SchedMD 及相关权利人;未从软件的开源许可推断网页具有另行未声明的转载许可。编辑改动包括中文整理、示例结果表格化、删除自动确认的改写示例、添加只读解析预览器,以及记录原文数值和类型展示的不一致。












暂无评论内容