Slurm 节能指南

目录

概述

Slurm 提供了一种集成机制,可以根据需要或请求将节点挂起(关闭电源,进入节能模式)和恢复(开机,从节能模式恢复)。在 IDLE 状态下保持SuspendTime 的节点将被 SuspendProgram 挂起,并且在 SuspendTimeout 内将无法进行调度。节点将通过 ResumeProgram 自动恢复以完成分配给它们的工作。在 ResumeTimeout 内未能注册的节点将变为 DOWN,并且其分配的作业将被重新排队。可以通过 scontrol update nodename=<nodename> state=power_<down|up> 手动请求节点节能。节点恢复或挂起的速率可以通过 ResumeRate 和 SuspendRate 控制。

Slurm 可以通过其 API 配置为在任何云提供商(例如 亚马逊网络服务、谷歌云平台、微软 Azure)中实现节能,通过管理计算资源。这些资源可以与现有集群结合使用以处理超出工作负载(云突发),或者可以作为独立的自包含集群运行。

要在 Slurm 中启用节能操作,必须配置以下内容:

  • ResumeProgram 和 SuspendProgram 必须定义。它们的值必须是程序的有效路径。
  • ResumeTimeout 和 SuspendTimeout 必须定义,或者全局定义,或者至少在一个分区上定义。
  • SuspendTime 必须定义,或者全局定义,或者至少在一个分区上定义,并且不能是 INFINITE 或 -1。
  • ResumeRate 和 SuspendRate 必须大于或等于 0。

Slurm 控制守护进程 slurmctld 必须重新启动以初始启用节能操作。配置参数(例如 SuspendTime)的更改将在修改 slurm.conf 配置文件并执行 scontrol reconfigure 后生效。

配置

以下感兴趣的配置参数包括:

DebugFlags

定义应提供更详细事件日志记录的特定子系统。感兴趣的选项包括:

Power

电源管理插件和节能(挂起/恢复程序)详细信息。

ReconfigFlags

控制在发出 scontrol reconfigure 命令时可能采取的各种操作的标志。感兴趣的选项包括:

KeepPowerSaveSettings

如果设置,则 scontrol reconfigure 命令将保留 SuspendExcNodes、SuspendExcParts 和 SuspendExcStates 的当前状态。

ResumeFailProgram

当节点未能在 ResumeTimeout 内恢复时要执行的程序。程序的参数将是失败节点的名称(使用 Slurm 的主机列表表达式格式)。

ResumeProgram

用于从节能模式恢复节点的程序。该程序以 SlurmUser 身份执行(如在 slurm.conf 中配置)。程序的参数将是要从节能模式恢复的节点名称(使用 Slurm 的主机列表表达式格式)。

如果 slurmd 守护进程未能在配置的 ResumeTimeout 值内以更新的 BootTime 响应,则该节点将被置于 DOWN 状态,请求该节点的作业将被重新排队。如果节点实际上没有重启(例如,当配置了多个 slurmd 时),可以使用 "-b" 选项启动 slurmd,以将节点启动时间报告为现在。

通过读取由 SLURM_RESUME_FILE 环境变量指定的临时文件,可以获得作业到节点的映射,文件应在 ResumeProgram 开始时使用 - 有关更多详细信息,请参见 容错 部分。该程序可以使用 scontrol show nodename 命令来确保节点已启动并且 slurmd 守护进程已启动。

SLURM_RESUME_FILE=/proc/1647372/fd/7:
{
  "all_nodes_resume" : "cloud[1-3,7-8]",
  "jobs" : [
    {
      "extra" : "来自 --extra 的任意字符串",
      "features" : "c1,c2",
      "job_id" : 140814,
      "nodes_alloc" : "cloud[1-4]",
      "nodes_resume" : "cloud[1-3]",
      "oversubscribe" : "OK",
      "partition" : "cloud",
      "reservation" : "resv_1234"
    },
    {
      "extra" : null,
      "features" : "c1,c2",
      "job_id" : 140815,
      "nodes_alloc" : "cloud[1-2]",
      "nodes_resume" : "cloud[1-2]",
      "oversubscribe" : "OK",
      "partition" : "cloud",
      "reservation" : null
    },
    {
      "extra" : null,
      "features" : null,
      "job_id" : 140816,
      "nodes_alloc" : "cloud[7-8]",
      "nodes_resume" : "cloud[7-8]",
      "oversubscribe" : "NO",
      "partition" : "cloud_exclusive",
      "reservation" : null
    }
  ]
}

有关 oversubscribe 的可能值,请参见 squeue 手册页。

注意:SLURM_RESUME_FILE 仅在 Slurm 使用 JSON-C 序列化库编译时存在并可用。

ResumeRate

每分钟从节能模式中移除的最大节点数。值为零表示不施加限制。默认值为 300。使用此值可以防止电力消耗快速增加。

ResumeTimeout

发出节点恢复请求和节点实际可用之间允许的最大时间(以秒为单位)。在此时间范围内未能响应的节点将被标记为 DOWN,调度在该节点上的作业将被重新排队。此时间范围后重启的节点将被标记为 DOWN,原因是“节点意外重启”。默认值为 60 秒。

SchedulerParameters

此参数的解释因 SchedulerType 而异。多个选项可以用逗号分隔。感兴趣的选项包括:

salloc_wait_nodes

如果定义,salloc 命令将在所有分配的节点准备好使用(即启动)之前等待。默认情况下,salloc 在资源分配完成后立即返回。salloc 命令可以使用 --wait-all-nodes 选项来覆盖此配置参数。

sbatch_wait_nodes

如果定义,sbatch 脚本将在所有分配的节点准备好使用(即启动)之前等待。在默认情况下,sbatch 脚本将在作业分配中的第一个节点准备好后立即启动。sbatch 命令可以使用 --wait-all-nodes 选项来覆盖此配置参数。

SlurmctldParameters

以逗号分隔的选项,标识 slurmctld 选项。感兴趣的选项包括:

cloud_dns

默认情况下,Slurm 期望云节点的网络地址在节点创建之前未知,并且 Slurm 会在注册时通知节点的地址。由于 Slurm 通信依赖于 slurm.conf 中找到的节点配置,Slurm 会在等待所有节点启动后,告诉客户端命令每个节点的 IP 地址。然而,在节点在 DNS 中的环境中,可以通过配置此选项来避免此步骤。

idle_on_node_suspend

在使用 SuspendProgram 挂起节点时,无论当前状态如何,将节点标记为闲置,以便节点在稍后可以恢复。

node_reg_mem_percent=#

节点允许注册的内存百分比,而不被标记为低内存。默认值为 100。对于 State=CLOUD 节点,默认值为 90。

power_save_interval=#

power_save 线程检查恢复和挂起节点的频率。power_save 线程将在节点状态发生变化时更早执行工作。默认值为 10 秒。

power_save_min_interval=#

power_save 线程至少检查恢复和挂起节点的频率。默认值为 0。

SuspendExcNodes

不受挂起/恢复逻辑约束的节点。这可以用于避免挂起和恢复不在云中的节点。或者,挂起/恢复程序可以将本地节点与从云中提供的节点区分对待。使用 Slurm 的主机列表表达式来识别节点,使用可选的 ":" 分隔符和要从前面的范围中排除的节点计数。例如 nid[10-20]:4 将防止在 nid[10-20] 集合中 4 个可用节点(即 IDLE 且不 DOWN、DRAINING 或已关闭电源)被关闭。可以在逗号分隔的列表中指定多个节点集合,带或不带计数(例如 nid[10-20]:4,nid[80-90]:2)。默认情况下,不排除任何节点。此值可以使用 scontrol 更新。有关设置持久性的详细信息,请参见 ReconfigFlags=KeepPowerSaveSettings。

SuspendExcParts

包含永远不会进入节能模式的节点的分区列表。可以使用逗号分隔符指定多个分区。默认情况下,不排除任何节点。此值可以使用 scontrol 更新。有关设置持久性的详细信息,请参见 ReconfigFlags=KeepPowerSaveSettings。

SuspendExcStates

指定不应自动关闭电源的节点状态。有效状态包括 CLOUD、DOWN、DRAIN、DYNAMIC_FUTURE、DYNAMIC_NORM、FAIL、INVALID_REG、MAINTENANCE、NOT_RESPONDING、PERFCTRS、PLANNED 和 RESERVED。默认情况下,如果处于这些状态中的任何一个且闲置时间超过 SuspendTime,将关闭电源。此值可以使用 scontrol 更新。有关设置持久性的详细信息,请参见 ReconfigFlags=KeepPowerSaveSettings。

SuspendProgram

用于将节点置于节能模式的程序。该程序以 SlurmUser 身份执行(如在 slurm.conf 中配置)。程序的参数将是要置于节能模式的节点名称(使用 Slurm 的主机列表表达式格式)。

SuspendRate

每分钟放入节能模式的最大节点数。值为零表示不施加限制。默认值为 60。使用此值可以防止电力消耗快速下降。

SuspendTime

节点在闲置或关闭此秒数后变为可进入节能模式。负数将禁用节能模式。默认值为 -1(禁用)。

SuspendTimeout

发出节点挂起请求和节点关闭完成之间允许的最大时间(以秒为单位)。在此时,节点必须准备好以便发出恢复请求以满足新工作负载的需要。默认值为 30 秒。

节点配置

感兴趣的节点参数包括:

Feature

节点特性可以与从云中获取的资源相关联,用户作业可以使用 --constraint 选项指定其资源使用偏好。

NodeName

这是 Slurm 识别节点的名称。建议使用包含数字后缀的名称以方便使用。

State

要按需添加的节点应具有 CLOUD 状态。

Weight

每个节点可以配置一个权重,表示使用该资源的优先级。权重较低的节点优先于权重较高的节点。默认值为 1。Slurm 将首先从已开机的节点分配资源,其次是启动的节点,最后是已关闭电源的节点 - 在每个集合中遵循节点权重。

分区配置

感兴趣的分区参数包括:

PowerDownOnIdle

如果设置为 YES 并且该分区启用了节能,则从该分区分配的节点在分配至少一个作业后将请求关闭电源。这些节点在从 COMPLETING 转换为 IDLE 之前不会关闭电源。如果设置为 NO,则节能将按照分区的配置运行。默认值为 NO。

以下将导致从 COMPLETING 转换为 IDLE:

  • 完成所有正在运行的作业,而不分配其他作业。
  • ExclusiveUser=YES,在所有正在运行的作业完成后,但在分配其他用户的作业之前。
  • OverSubscribe=EXCLUSIVE,在运行作业完成后,但在分配其他作业之前。

注意:当 PowerDownOnIdle 设置为 NO 时,节点在闲置时间超过 SuspendTime 时仍然会被关闭电源。

ResumeTimeout

发出节点恢复请求和节点实际可用之间允许的最大时间(以秒为单位)。在此时间范围内未能响应的节点将被标记为 DOWN,调度在该节点上的作业将被重新排队。此时间范围后重启的节点将被标记为 DOWN,原因是“节点意外重启”。默认值为 60 秒。

对于在多个分区中设置此选项的节点,将采用最高时间。如果在任何分区中未设置,则节点将使用整个集群设置的 ResumeTimeout 值。

SuspendTime

在此秒数内保持闲置或关闭的节点将通过 SuspendProgram 进入节能模式。

对于在多个分区中设置此选项的节点,将采用最高时间。如果在任何分区中未设置,则节点将使用整个集群设置的 SuspendTime 值。将 SuspendTime 设置为 INFINITE 将禁用该分区中节点的挂起。

SuspendTimeout

发出节点挂起请求和节点关闭完成之间允许的最大时间(以秒为单位)。在此时,节点必须准备好以便发出恢复请求以满足新工作负载的需要。默认值为 30 秒。

对于在多个分区中设置此选项的节点,将采用最高时间。如果在任何分区中未设置,则节点将使用整个集群设置的 SuspendTimeout 值。

节点生命周期

当 Slurm 配置为节能操作时,节点与之相关的状态集扩展。与节能相关的状态在使用 sinfo 查看节点详细信息时通常会标记符号。

图 1. 节点生命周期
图 1. 节点生命周期

感兴趣的节点状态:

状态 节能符号 描述
POWER_DOWN ! 关闭电源请求。当节点不再运行作业时,运行 SuspendProgram。
POWER_UP   开机请求。当可能时,运行 ResumeProgram。
POWERED_DOWN ~ 节点已关闭电源或处于节能模式。
POWERING_DOWN % 节点正在关闭电源或被置于节能模式,并且在 SuspendTimeout 内无法运行任何作业。
POWERING_UP # 节点正在开机或从节能模式恢复。

手动节能

可以通过使用 scontrol 将节点的状态设置为以下状态来手动开关节点:

scontrol update nodename=<nodename> state=power_<down|down_asap|down_force|up>

scontrol update 命令的操作/状态感兴趣:

POWER_DOWN
将使用配置的 SuspendProgram 程序显式将节点置于节能模式。如果节点已经在关闭电源的过程中,则该命令只会更改节点的状态,但在达到配置的 SuspendTimeout 之前不会产生任何效果。
POWER_DOWN_ASAP
将排空节点并标记为关闭电源。当前正在运行的作业将首先完成,且不会分配其他作业到该节点。
POWER_DOWN_FORCE
将取消节点上的所有作业,关闭电源,并将其状态重置为 IDLE。
POWER_UP
将使用配置的 ResumeProgram 程序显式将节点移出节能模式。如果节点已经在开机的过程中,则该命令只会更改节点的状态,但在达到配置的 ResumeTimeout 之前不会产生任何效果。
RESUME
不是实际的节点状态,但将节点状态从 DRAIN、DRAINING、DOWN 或 REBOOT 更改为 IDLE 和 NoResp。slurmctld 将尝试联系 slurmd 请求节点注册自身。一旦注册,节点状态将移除 NoResp 标志,并恢复正常操作。它还将清除节点的 POWERING_DOWN 状态,使其有资格被分配。

恢复与挂起程序

ResumeProgram 和 SuspendProgram 以 SlurmUser 身份在 slurmctld 守护进程运行的节点上执行(主服务器和备份服务器节点)。可能需要使用 sudo 使 SlurmUser 能够关闭电源和重启节点。如果需要将 Slurm 的主机列表表达式转换为单个节点名称,scontrol show hostnames 命令可能会很有用。用于启动或关闭节点的命令将取决于您的集群管理工具。

ResumeProgram 和 SuspendProgram 不受任何时间限制,但必须具有 容错。它们应执行所需的操作,理想情况下验证该操作(例如,节点启动并启动 slurmd 守护进程,因此节点不再对 slurmctld 无响应)并终止。长时间运行的程序将被 slurmctld 记录,但不会被中止。

示例 ResumeProgram:

#!/bin/bash
# 示例 ResumeProgram
hosts=$(scontrol show hostnames "$1")
logfile=/var/log/power_save.log
echo "$(date) Resume invoked $0 $*" >>$logfile
for host in $hosts
do
        sudo node_startup "$host"
done
exit 0

示例 SuspendProgram:

#!/bin/bash
# 示例 SuspendProgram
hosts=$(scontrol show hostnames "$1")
logfile=/var/log/power_save.log
echo "$(date) Suspend invoked $0 $*" >>$logfile
for host in $hosts
do
        sudo node_shutdown "$host"
done
exit 0

注意:挂起和恢复程序的 stderr 和 stdout 不会被记录。如果需要记录,则应将其添加到脚本中。

容错

如果 slurmctld 守护进程正常终止,它将等待最多十秒(或 SuspendTimeout 或 ResumeTimeout 中较小的值)以终止任何生成的 SuspendProgram 或 ResumeProgram,然后再终止守护进程。如果生成的程序在该时间段内未终止,则事件将被记录,slurmctld 将退出,以允许启动另一个 slurmctld 守护进程。任何生成的 SuspendProgram 或 ResumeProgram 将继续运行。

当 slurmctld 守护进程关闭时,任何 SLURM_RESUME_FILE 临时文件将不再可用,即使 slurmctld 重新启动。因此,ResumeProgram 应在启动后十秒内使用 SLURM_RESUME_FILE 以保证它仍然存在。

启动不同的映像

如果您希望 ResumeProgram 根据作业规范启动各种映像,则它需要是一个相当复杂的程序,并执行以下操作:

  1. 确定与要启动的节点相关联的作业。SLURM_RESUME_FILE 将有助于此步骤。
  2. 确定每个作业所需的映像。可以通过 NodeFeaturesPlugins 映射映像。
  3. 为每个节点启动适当的映像。

使用分配

资源分配请求将在选择资源后立即获得批准,可能在所有节点都可用之前。作业步骤的启动将被延迟,直到所需节点恢复服务(它会打印关于等待节点变为可用的警告,并定期重试,直到它们可用)。

在 sbatch 命令的情况下,批处理程序将在分配的节点零准备好使用时启动,并可以根据需要执行预处理,然后使用 srun 启动作业步骤。可以使用 sbatch --wait-all-nodes=<value> 选项在每个作业的基础上覆盖此行为,并可以使用 SchedulerParameters=sbatch_wait_nodes 选项设置系统范围的默认值。

在 salloc 命令的情况下,一旦分配完成,将在登录节点上创建一个新 shell。可以使用 salloc --wait-all-nodes=<value> 选项在每个作业的基础上覆盖此行为,并可以使用 SchedulerParameters=salloc_wait_nodes 选项设置系统范围的默认值。

节点特性

由 NodeFeaturesPlugins 定义的特性,并与 slurm.conf 中的云节点相关联,将在节点关闭电源时可用但不活跃。如果作业请求可用但不活跃的特性,控制器将分配已关闭电源且具有可用特性的节点。在分配时,这些特性将变为活跃。云节点将保持活跃特性,直到节点关闭电源(即节点无法重启以获取其他特性,直到节点关闭电源)。当节点关闭电源时,这些特性变为可用但不活跃。任何未由 NodeFeaturesPlugins 定义的特性始终处于活跃状态。

示例:

slurm.conf:
NodeFeaturesPlugins=node_features/helpers

NodeName=cloud[1-5] ... State=CLOUD Feature=f1,f2,l1
NodeName=cloud[6-10] ... State=CLOUD Feature=f3,f4,l2

helpers.conf:
NodeName=cloud[1-5] Feature=f1,f2 Helper=/bin/true
NodeName=cloud[6-10] Feature=f3,f4 Helper=/bin/true

特性 f1、f2、f3 和 f4 是可变特性,并在 slurm.conf 中的节点行上定义,因为 CLOUD 节点在分配之前不会注册。通过将 Helper 脚本设置为 /bin/true,slurmd 将不会向控制器报告任何活跃特性,控制器将管理所有活跃特性。如果 Helper 设置为报告活跃特性的脚本,控制器将验证报告的活跃特性是节点活跃可变特性的超集。特性 l1 和 l2 将始终处于活跃状态,并可以用作可选择的标签。

混合集群

按需获取的云节点可以放置在其自己的 Slurm 分区中。这种操作模式可以仅在用户请求时使用这些节点。请注意,作业可以提交到多个分区,并将使用允许更快启动的分区的资源。以下是一个示例配置,当工作负载超过可用资源时,从云中添加节点。用户可以通过使用 --constraint 选项显式请求本地资源或云资源。

示例:

# slurm.conf 摘录
SelectType=select/cons_tres
SelectTypeParameters=CR_CORE_Memory

SuspendProgram=/usr/sbin/slurm_suspend
ResumeProgram=/usr/sbin/slurm_resume
SuspendTime=600
SuspendExcNodes=tux[0-127]
TreeWidth=128

NodeName=DEFAULT    Sockets=1 CoresPerSocket=4 ThreadsPerCore=2
NodeName=tux[0-127] Weight=1 Feature=local State=UNKNOWN
NodeName=ec[0-127]  Weight=8 Feature=cloud State=CLOUD
PartitionName=debug MaxTime=1:00:00 Nodes=tux[0-32] Default=YES
PartitionName=batch MaxTime=8:00:00 Nodes=tux[0-127],ec[0-127]

当全局设置 SuspendTime 时,Slurm 尝试挂起所有节点,除非被 SuspendExcNodes 或 SuspendExcParts 排除。记住将本地节点添加到排除选项可能会很棘手。通过将全局 SuspendTime 设置为 INFINITE 并在特定于云的分区上配置 SuspendTime,可以避免必须排除节点。

示例:

# slurm.conf 摘录
SelectType=select/cons_tres
SelectTypeParameters=CR_CORE_Memory

SuspendProgram=/usr/sbin/slurm_suspend
ResumeProgram=/usr/sbin/slurm_resume
TreeWidth=128

NodeName=DEFAULT    Sockets=1 CoresPerSocket=4 ThreadsPerCore=2
NodeName=tux[0-127] Weight=1 Feature=local State=UNKNOWN
NodeName=ec[0-127]  Weight=8 Feature=cloud State=CLOUD
PartitionName=debug MaxTime=1:00:00 Nodes=tux[0-32] Default=YES
PartitionName=batch MaxTime=8:00:00 Nodes=tux[0-127],ec[0-127]
PartitionName=cloud Nodes=ec[0-127] SuspendTime=600

在这里,我们配置了一个仅包含云节点的分区,并在该分区上定义了 SuspendTime。这样可以让我们控制这些节点何时关闭电源,而不影响我们的本地节点,因此在此设置中不需要 SuspendExcNodes 或 SuspendExcParts。

云计费

有关云实例的信息可以存储在数据库中。这可以通过在 slurmd 启动时配置实例 ID/类型或使用 scontrol update 来完成。节点的“额外”字段也将存储在数据库中。

在 slurmd 启动时配置云信息:

$ slurmd --instance-id=12345 --instance-type=m7g.medium --extra="任意字符串" . . .

使用 scontrol update 配置云信息:

$ scontrol update nodename=n1 instanceid=12345 instancetype=m7g.medium extra="任意字符串"

然后可以使用 scontrol show node 在控制器上查看这些数据。过去和当前的数据可以通过 sacctmgr show instance 在数据库中查看,也可以通过 slurmrestd 使用 /instance 和 /instances 端点查看。

使用 scontrol 在控制器上显示云信息:

$ scontrol show nodes n1 | grep "NodeName\|Extra\|Instance"
NodeName=n1 Arch=x86_64 CoresPerSocket=4
   Extra=任意字符串
   InstanceId=12345 InstanceType=m7g.medium

使用 sacctmgr 从数据库中显示云信息:

$ sacctmgr show instance format=nodename,instanceid,instancetype,extra
NodeName                  InstanceId         InstanceType                Extra
--------------- -------------------- -------------------- --------------------
n1                             12345           m7g.medium     任意字符串

使用 slurmrestd 从数据库中显示云信息:

$ curl -k -s \
        --request GET \
        -H X-SLURM-USER-NAME:$(whoami) \
        -H X-SLURM-USER-TOKEN:$SLURM_JWT \
        -H "Content-Type: application/json" \
        --url localhost:8080/slurmdb/v0.0.40/instances \
        | jq ".instances"

[
  {
    "cluster": "c1",
    "extra": "任意字符串",
    "instance_id": "12345",
    "instance_type": "m7g.medium",
    "node_name": "n1",
    "time": {
      "time_end": 0,
      "time_start": 1687213177
    }
  }
]

最后修改于 2025 年 5 月 20 日