3. 集群资源管理与调度器架构
在仿真计算集群中,调度器并不是一个孤立的“排队程序”,而是位于用户作业与物理资源之间的中枢系统。它向上接收用户提交的作业描述,向下管理计算节点的 CPU、内存、GPU、许可证等资源,并在中间通过队列、分区、账户等策略层完成资源分配与优先级裁决。理解调度器的组件与工作流程,是后续编写作业脚本、排查排队异常、优化资源利用率的基础。
一、调度器在集群中的位置与职责
从系统层次看,集群可分为四层:用户接入层(登录节点、Web 门户、API)、调度管理层(资源管理器与调度器)、计算执行层(计算节点与守护进程)、存储与网络层(共享文件系统、InfiniBand 等)。调度器位于第二层,其核心职责包括:
- 资源发现与状态维护:持续收集各计算节点的 CPU 核数、内存容量、GPU 数量、当前负载、健康状态。
- 作业接收与排队:接收用户提交的作业,解析资源请求、时限、队列、账户等属性,放入待调度队列。
- 调度决策:按优先级、公平共享、回填、预留等策略,从队列中选择作业并匹配可用资源。
- 作业启动与监控:在选定节点上启动作业进程,跟踪运行状态,处理超时、失败与资源回收。
- 策略与配额管理:通过分区、队列、账户、QOS 等机制限制资源使用,保障公平性与优先级。
调度器不直接执行仿真程序,而是通过节点守护进程(如 Slurm 的 slurmd、PBS 的 pbs_mom、LSF 的 LIM 与 RES)在计算节点上拉起任务。因此,调度器是“决策者”,守护进程是“执行者”。
二、核心组件与对象模型
以 Slurm 为例,其架构包含以下关键组件:
- slurmctld(中央管理守护进程):运行在控制节点,负责资源管理、作业调度、状态持久化。它是整个集群的“大脑”。
- slurmd(节点守护进程):运行在每个计算节点,负责接收并执行来自 slurmctld 的任务,上报节点状态与资源使用。
- slurmdbd(数据库守护进程):可选组件,用于将作业记录、账户信息写入数据库,支持 sacct 查询与公平共享策略。
- 计算节点(Node):实际执行作业的服务器,具有名称、CPU 核数、内存、GPU、特性(Feature)等属性。
- 分区(Partition):节点的逻辑分组,类似“资源池”。一个节点可属于多个分区。分区可设置默认时限、最大节点数、优先级、允许的账户等。
- 队列(Queue):在 PBS/LSF 中常称队列,在 Slurm 中与分区概念高度重合。队列通常绑定特定资源集合与策略。
- 作业(Job):用户提交的计算任务,包含资源请求、脚本、环境变量、依赖关系等。
- 账户(Account)与 QOS:用于资源配额与优先级管理,常与项目经费、课题组绑定。
PBS 与 LSF 的组件命名不同,但角色对应:PBS 的 pbs_server 对应 slurmctld,pbs_mom 对应 slurmd,pbs_sched 对应调度策略模块;LSF 的 mbatchd 负责作业管理,mbschd 负责调度决策,LIM 负责节点资源监控。理解这些对应关系,有助于跨集群迁移作业脚本。
三、作业从提交到运行的工作流程
下面以 Slurm 为例,描述一个典型作业的完整生命周期:
- 提交:用户在登录节点执行
sbatch job.sh,slurmctld 接收作业并解析脚本中的#SBATCH指令,如--partition=compute、--nodes=2、--ntasks-per-node=32、--time=04:00:00。 - 排队:作业进入指定分区的待调度队列,状态为 PENDING。调度器根据优先级、资源可用性、回填策略决定何时启动。
- 资源选择:调度器从空闲节点中筛选满足请求的节点集合,考虑节点特性、拓扑、许可证等约束。
- 启动:slurmctld 向选中节点的 slurmd 发送启动指令,slurmd 创建作业步骤(job step),执行用户脚本。
- 运行与监控:作业状态变为 RUNNING,slurmctld 持续跟踪资源使用;用户可用
squeue查看状态,scontrol show job查看详情。 - 完成与回收:作业结束后,slurmd 回收进程与资源,slurmctld 更新状态为 COMPLETED,并记录到 slurmdbd(若启用)。
在 PBS 中,流程类似:qsub 提交 → pbs_server 接收 → pbs_sched 调度 → pbs_mom 执行 → qstat 查看。LSF 则使用 bsub、bjobs、bkill 等命令。
四、队列与分区的策略设计
分区与队列是调度器实现资源隔离与优先级控制的主要手段。一个合理的分区设计通常考虑以下维度:
- 硬件差异:将 GPU 节点、大内存节点、普通 CPU 节点分入不同分区,避免小作业占用稀缺资源。
- 作业时限:debug 分区限制 30 分钟,适合调试;long 分区允许 7 天,适合长时仿真。
- 优先级与配额:高优先级分区面向紧急任务,但限制最大节点数;普通分区通过账户配额保障公平。
- 访问控制:通过 AllowAccounts、AllowGroups 限制特定分区仅对某些课题组开放。
例如,一个典型的 Slurm 分区配置片段如下:
# slurm.conf 片段
PartitionName=debug Nodes=node[01-03] Default=YES MaxTime=00:30:00 State=UP
PartitionName=compute Nodes=node[01-10] MaxTime=24:00:00 State=UP
PartitionName=gpu Nodes=node[11-14] MaxTime=72:00:00 State=UP
PartitionName=long Nodes=node[01-10] MaxTime=7-00:00:00 State=UP
用户提交时通过 --partition=gpu 指定分区。若未指定,则使用默认分区。调度器在分区内按优先级排序,同时考虑回填:小作业可利用大作业预留的空隙提前运行,但不得延迟任何已排队作业的预计开始时间。
五、调度器职责的边界与常见误区
调度器负责“分配资源”,但不负责“优化用户程序”。常见误区包括:
- 认为提交后就会立即运行:实际取决于资源可用性与优先级,PENDING 是正常状态。
- 忽略资源请求的准确性:申请 64 核但实际只用 8 核,会浪费资源并降低自身后续作业优先级。
- 混淆分区与物理节点:一个节点可属于多个分区,分区是逻辑视图,不是物理隔离。
- 忽视账户与 QOS 限制:超出配额会导致作业被拒绝或降级,需提前确认项目账户余额与 QOS 上限。
squeue -j <jobid> -o "%.18i %.9P %.8j %.8u %.2t %.10M %.6D %R" 查看排队原因;sinfo -p <partition> 查看分区节点状态;scontrol show job <jobid> 查看详细约束;sacctmgr show assoc user=$USER 确认账户配额。常见原因包括:资源请求超过分区上限、账户配额耗尽、QOS 限制、节点被预留或下线。
理解调度器的组件与工作流程后,下一步是掌握作业脚本的编写与资源请求的精确表达。调度器只根据你声明的资源需求做决策,声明越准确,排队与运行效率越高。