

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# Slurm 多队列模式指南
<a name="multiple-queue-mode-slurm-user-guide-v3"></a>

在这里，您可以了解如何 AWS ParallelCluster Slurm和管理队列（分区）节点，以及如何监控队列和节点状态。

## 概述
<a name="multiple-queue-mode-slurm-user-guide-v3-overview"></a>

扩展架构基于 Slurm 的[云调度指南](https://slurm.schedmd.com/elastic_computing.html)和节能插件。有关节能插件的更多信息，请参阅 [Slurm Power Saving Guide](https://slurm.schedmd.com/power_save.html)。在该架构中，可能可供集群使用的资源通常在 Slurm 配置中预定义为云节点。

## 云节点生命周期
<a name="multiple-queue-mode-slurm-user-guide-v3-cloud-node-lifecycle"></a>

在整个生命周期中，云节点会进入以下几种（如果不是全部）状态：`POWER_SAVING`、`POWER_UP` (`pow_up`)、`ALLOCATED` (`alloc`) 和 `POWER_DOWN` (`pow_dn`)。在某些情况下，云节点可能会进入 `OFFLINE` 状态。下面的列表详细介绍了云节点生命周期中这些状态的几个方面。
+ **处于 `POWER_SAVING` 状态的节点**在 `sinfo` 中显示 `~` 后缀（例如 `idle~`） 在这种状态下，没有支持该节点的 EC2 实例。但 Slurm 仍然可以向该节点分配作业。
+ **正在过渡到 `POWER_UP` 状态的节点**将在 `sinfo` 中显示 `#` 后缀（例如 `idle#`）。当 Slurm 向处于 `POWER_SAVING` 状态的节点分配作业时，该节点会自动转变为 `POWER_UP` 状态。

  或者，您可以以 `su` 根用户身份使用以下命令将节点手动转变为 `POWER_UP` 状态：

  ```
  $ scontrol update nodename={{nodename}} state=power_up
  ```

  在此阶段，将调用 `ResumeProgram`，启动并配置 EC2 实例，并且节点会过渡到 `POWER_UP` 状态。
+ **当前可供使用的节点**在 `sinfo` 中不显示后缀（例如 `idle`）。节点设置完毕并加入集群后，即可用于运行作业。在此阶段，节点已正确配置并可供使用。

  一般而言，我们建议 Amazon EC2 实例的数量与可用节点的数量相同。在大多数情况下，在创建集群后，静态节点即可用。
+ **正在过渡到 `POWER_DOWN` 状态的节点**在 `sinfo` 中显示 `%` 后缀（例如 `idle%`）。经过 [`ScaledownIdletime`](Scheduling-v3.md#yaml-Scheduling-SlurmSettings-ScaledownIdletime) 之后，动态节点会自动进入 `POWER_DOWN` 状态。相比之下，静态节点在大多数情况下不会关闭。但您可以以 `su` 根用户身份使用以下命令将节点手动置于 `POWER_DOWN` 状态：

  ```
  $ scontrol update nodename={{nodename}} state=down reason="manual draining"
  ```

  在此状态下，与节点关联的实例将会终止，节点将设置回 `POWER_SAVING` 状态并在经过 [`ScaledownIdletime`](Scheduling-v3.md#yaml-Scheduling-SlurmSettings-ScaledownIdletime) 之后可供使用。

  [`ScaledownIdletime`](Scheduling-v3.md#yaml-Scheduling-SlurmSettings-ScaledownIdletime) 设置保存到 Slurm 配置中的 `SuspendTimeout` 设置。
+ **离线的节点**将在 `sinfo` 中显示 `*` 后缀（例如 `down*`）。如果 Slurm 控制器无法联系某个节点，或者静态节点被禁用并且支持实例被终止，则该节点将会离线。

请考虑以下 `sinfo` 示例中所示的节点状态。

```
$ sinfo
  PARTITION AVAIL  TIMELIMIT  NODES  STATE NODELIST
  efa          up   infinite      4  idle~ efa-dy-efacompute1-[1-4]
  efa          up   infinite      1   idle efa-st-efacompute1-1
  gpu          up   infinite      1  idle% gpu-dy-gpucompute1-1
  gpu          up   infinite      9  idle~ gpu-dy-gpucompute1-[2-10]
  ondemand     up   infinite      2   mix# ondemand-dy-ondemandcompute1-[1-2]
  ondemand     up   infinite     18  idle~ ondemand-dy-ondemandcompute1-[3-10],ondemand-dy-ondemandcompute2-[1-10]
  spot*        up   infinite     13  idle~ spot-dy-spotcompute1-[1-10],spot-dy-spotcompute2-[1-3]
  spot*        up   infinite      2   idle spot-st-spotcompute2-[1-2]
```

`spot-st-spotcompute2-[1-2]` 和 `efa-st-efacompute1-1` 节点已经设置了支持实例，并且可供使用。`ondemand-dy-ondemandcompute1-[1-2]` 节点处于 `POWER_UP` 状态，应会在几分钟内可用。`gpu-dy-gpucompute1-1` 节点处于 `POWER_DOWN` 状态，它将在 [`ScaledownIdletime`](Scheduling-v3.md#yaml-Scheduling-SlurmSettings-ScaledownIdletime)（默认为 10 分钟）之后过渡到 `POWER_SAVING` 状态。

所有其他节点都处于 `POWER_SAVING` 状态，没有支持它们的 EC2 实例。

## 使用可用节点
<a name="multiple-queue-mode-slurm-user-guide-v3-working-with-available-nodes"></a>

可用节点由 Amazon EC2 实例提供支持。默认情况下，可以使用节点名称直接通过 SSH 加入到实例中（例如 `ssh efa-st-efacompute1-1`）。可以使用以下命令来检索实例的私有 IP 地址：

```
$ scontrol show nodes {{nodename}}
```

在返回的 `NodeAddr` 字段中检查 IP 地址。

对于不可用的节点，`NodeAddr` 字段不应指向正在运行的 Amazon EC2 实例，而是应与节点名称相同。

## 作业状态和提交
<a name="multiple-queue-mode-slurm-user-guide-v3-job-states"></a>

在大多数情况下，提交的作业会立即分配给系统中的节点，或者如果所有节点都已分配，则将其置于待处理状态。

如果为作业分配的节点包括任何处于 `POWER_SAVING` 状态的节点，则该作业将以 `CF` 或 `CONFIGURING` 状态开始。此时，该作业将会等待处于 `POWER_SAVING` 状态的节点过渡到 `POWER_UP` 状态并变为可用。

为作业分配的所有节点都可用后，该作业将进入 `RUNNING` (`R`) 状态。

默认情况下，所有作业都提交到默认队列（在 Slurm 中称为分区）。此队列由队列名称后面的后缀 `*` 表示。您可以使用 `-p` 作业提交选项选择队列。

所有节点都配置了以下特征，这些特征可以在作业提交命令中使用：
+ 实例类型（例如 `c5.xlarge`）。
+ 节点类型（`dynamic` 或 `static`。）

您可以使用以下命令查看特定节点的特征：

```
$ scontrol show nodes {{nodename}}
```

在返回的结果中，查看 `AvailableFeatures` 列表。

考虑集群的初始状态，可以通过运行 `sinfo` 命令来查看该状态。

```
$ sinfo
  PARTITION AVAIL  TIMELIMIT  NODES  STATE NODELIST
  efa          up   infinite      4  idle~ efa-dy-efacompute1-[1-4]
  efa          up   infinite      1   idle efa-st-efacompute1-1
  gpu          up   infinite     10  idle~ gpu-dy-gpucompute1-[1-10]
  ondemand     up   infinite     20  idle~ ondemand-dy-ondemandcompute1-[1-10],ondemand-dy-ondemandcompute2-[1-10]
  spot*        up   infinite     13  idle~ spot-dy-spotcompute1-[1-10],spot-dy-spotcompute2-[1-3]
  spot*        up   infinite      2   idle spot-st-spotcompute2-[1-2]
```

请注意，`spot` 是默认队列。它由 `*` 后缀表示。

向默认队列 (`spot`) 中的一个静态节点提交作业。

```
$ sbatch --wrap {{"sleep 300"}} -N {{1}} -C {{static}}
```

向 `EFA` 队列中的一个动态节点提交作业。

```
$ sbatch --wrap {{"sleep 300"}} -p {{efa}} -C {{dynamic}}
```

向 `ondemand` 队列中的八 (8) 个 `c5.2xlarge` 节点和两 (2) 个 `t2.xlarge` 节点提交作业。

```
$ sbatch --wrap {{"sleep 300"}} -p {{ondemand}} -N {{10}} -C "[{{c5.2xlarge*8&t2.xlarge*2}}]"
```

向 `gpu` 队列中的一个 GPU 节点提交作业。

```
$ sbatch --wrap {{"sleep 300"}} -p {{gpu}} -G {{1}}
```

考虑使用 `squeue` 命令的作业状态。

```
$ squeue
 JOBID PARTITION    NAME   USER   ST       TIME  NODES NODELIST(REASON)
  12   ondemand     wrap   ubuntu CF       0:36     10 ondemand-dy-ondemandcompute1-[1-8],ondemand-dy-ondemandcompute2-[1-2]
  13        gpu     wrap   ubuntu CF       0:05      1 gpu-dy-gpucompute1-1
   7       spot     wrap   ubuntu  R       2:48      1 spot-st-spotcompute2-1
   8        efa     wrap   ubuntu  R       0:39      1 efa-dy-efacompute1-1
```

作业 7 和 8（在 `spot` 和 `efa` 队列中）已经在运行 (`R`)。作业 12 和 13 仍在配置 (`CF`)，可能正在等待实例变为可用。

```
# Nodes states corresponds to state of running jobs
$ sinfo
 PARTITION AVAIL  TIMELIMIT  NODES  STATE NODELIST
 efa          up   infinite      3  idle~ efa-dy-efacompute1-[2-4]
 efa          up   infinite      1    mix efa-dy-efacompute1-1
 efa          up   infinite      1   idle efa-st-efacompute1-1
 gpu          up   infinite      1   mix~ gpu-dy-gpucompute1-1
 gpu          up   infinite      9  idle~ gpu-dy-gpucompute1-[2-10]
 ondemand     up   infinite     10   mix# ondemand-dy-ondemandcompute1-[1-8],ondemand-dy-ondemandcompute2-[1-2]
 ondemand     up   infinite     10  idle~ ondemand-dy-ondemandcompute1-[9-10],ondemand-dy-ondemandcompute2-[3-10]
 spot*        up   infinite     13  idle~ spot-dy-spotcompute1-[1-10],spot-dy-spotcompute2-[1-3]
 spot*        up   infinite      1    mix spot-st-spotcompute2-1
 spot*        up   infinite      1   idle spot-st-spotcompute2-2
```

## 节点状态和特征
<a name="multiple-queue-mode-slurm-user-guide-v3-node-state-features"></a>

在大多数情况下，节点状态完全由 AWS ParallelCluster 根据本主题前面所述的云节点生命周期中的特定流程进行管理。

但是， AWS ParallelCluster 还会替换或终止处于不健康`DRAINED`状态的节点`DOWN`和具有不健康后备实例的节点。有关更多信息，请参阅 [`clustermgtd`](processes-v3.md#clustermgtd-v3)。

## 分区状态
<a name="multiple-queue-mode-slurm-user-guide-v3-partition-states"></a>

AWS ParallelCluster 支持以下分区状态。Slurm 分区就是 AWS ParallelCluster中的队列。
+ `UP`：表示该分区处于活动状态。这是分区的默认状态。在此状态下，该分区中的所有节点都处于活动状态并且可供使用。
+ `INACTIVE`：表示该分区处于非活动状态。在此状态下，将会终止支持非活动分区的节点的所有实例。不会为非活动分区中的节点启动新实例。

## 集群 update-compute-fleet
<a name="multiple-queue-mode-slurm-user-guide-v3-pcluster-update-compute-fleet"></a>
+ **停止计算队列**-执行以下命令时，所有分区都将`INACTIVE`转换为状态， AWS ParallelCluster 进程将分区保持`INACTIVE`状态。

  ```
  $ pcluster update-compute-fleet --cluster-name {{testSlurm}} \
     --region {{eu-west-1}} --status STOP_REQUESTED
  ```
+ **启动计算实例集** - 执行以下命令时，所有分区最初都将转变为 `UP` 状态。但是， AWS ParallelCluster 进程不会使分区保持`UP`状态。您需要手动更改分区状态。所有静态节点将在几分钟后变为可用。请注意，将分区设置为 `UP` 不会增加任何动态容量。

  ```
  $ pcluster update-compute-fleet --cluster-name {{testSlurm}} \
     --region {{eu-west-1}} --status START_REQUESTED
  ```

当运行 `update-compute-fleet` 时，您可以通过运行 `pcluster describe-compute-fleet` 命令并检查 `Status` 来查看集群的状态。下面列出了可能的状态：
+ `STOP_REQUESTED`：停止计算实例集请求已发送到集群。
+ `STOPPING`：`pcluster` 进程当前正在停止计算实例集。
+ `STOPPED`：`pcluster` 进程已完成停止进程，所有分区都处于 `INACTIVE` 状态，并且所有计算实例都已终止。
+ `START_REQUESTED`：启动计算实例集请求已发送到集群。
+ `STARTING`：`pcluster` 进程当前正在启动集群。
+ `RUNNING`：`pcluster` 进程已完成启动过程，所有分区都处于 `UP` 状态，静态节点将在几分钟后可用。
+  `PROTECTED`：此状态表示某些分区持续出现引导故障。受影响的分区处于非活动状态。请调查问题，然后运行 `update-compute-fleet` 以重新启用该实例集。

## 队列的手动控制
<a name="multiple-queue-mode-slurm-user-guide-v3-manual-control-queue"></a>

在某些情况下，您可能需要对集群中的节点或队列（在 Slurm 中称为分区）进行一些手动控制。您可以使用 `scontrol` 命令通过以下常用过程管理集群中的节点。
+ **启动处于 `POWER_SAVING` 状态的动态节点**

  `su`以根用户身份运行以下命令：

  ```
  $ scontrol update nodename={{nodename}} state=power_up
  ```

  您也可以提交占位符 `sleep 1` 作业，请求一定数量的节点，然后依赖于 Slurm 来启动所需数量的节点。
+ **在 [`ScaledownIdletime`](Scheduling-v3.md#yaml-Scheduling-SlurmSettings-ScaledownIdletime) 之前关闭动态节点**

  我们建议您以 `su` 根用户身份使用以下命令将动态节点设置为 `DOWN`：

  ```
  $ scontrol update nodename={{nodename}} state=down reason="manually draining"
  ```

  AWS ParallelCluster 自动终止并重置已关闭的动态节点。

  通常，我们不建议直接使用 `scontrol update nodename={{nodename}} state=power_down` 命令将节点设置为 `POWER_DOWN`。这是因为 AWS ParallelCluster 会自动处理关闭过程，
+ **禁用队列（分区）或停止特定分区中的所有静态节点**

  以 `su` 根用户身份使用以下命令将特定队列设置为 `INACTIVE`：

  ```
  $ scontrol update partition={{queuename}} state=inactive
  ```

  此操作会终止支持该分区中节点的所有实例。
+ **启用队列（分区）**

  以 `su` 根用户身份使用以下命令将特定队列设置为 `UP`：

  ```
  $ scontrol update partition={{queuename}} state=up
  ```

## 扩展行为和调整
<a name="multiple-queue-mode-slurm-user-guide-v3-scaling-behavior"></a>

**下面是正常扩展工作流程的示例：**
+ 调度器收到需要两个节点的作业。
+ 调度器将两个节点转换为 `POWER_UP` 状态，并使用节点名称（例如 `queue1-dy-spotcompute1-[1-2]`）调用 `ResumeProgram`。
+ `ResumeProgram` 启动两个 Amazon EC2 实例并分配 `queue1-dy-spotcompute1-[1-2]` 的私有 IP 地址和主机名，等待 `ResumeTimeout`（默认时段为 30 分钟），然后重置节点。
+ 实例配置完成并加入集群。作业开始在实例上运行。
+ 作业完成并停止运行。
+ 经过配置的 `SuspendTime`（设置为 [`ScaledownIdletime`](Scheduling-v3.md#yaml-Scheduling-SlurmSettings-ScaledownIdletime)）后，调度器将实例设置为 `POWER_SAVING` 状态。然后，调度器将 `queue1-dy-spotcompute1-[1-2]` 设置为 `POWER_DOWN` 状态并使用节点名称调用 `SuspendProgram`。
+ 为两个节点调用 `SuspendProgram`。节点保持在 `POWER_DOWN` 状态，例如通过保持 `idle%` 状态持续 `SuspendTimeout`（默认时段为 120 秒（2 分钟））。在 `clustermgtd` 检测到节点正在关闭后，它会终止支持实例。然后，它将 `queue1-dy-spotcompute1-[1-2]` 转变到空闲状态并重置私有 IP 地址和主机名，使其能够启动以供将来的作业使用。

**如果出现问题，特定节点的某个实例由于某种原因无法启动，则会发生以下情况：**
+ 调度器收到需要两个节点的作业。
+ 调度器将两个云爆发节点转变为 `POWER_UP` 状态，并使用节点名称（例如 `queue1-dy-spotcompute1-[1-2]`）调用 `ResumeProgram`。
+ `ResumeProgram` 仅启动一（1）个 Amazon EC2 实例并配置 `queue1-dy-spotcompute1-1`，另一（1）个实例 `queue1-dy-spotcompute1-2` 未能启动。
+ `queue1-dy-spotcompute1-1` 未受影响，并在进入 `POWER_UP` 状态后上线。
+ `queue1-dy-spotcompute1-2` 转变为 `POWER_DOWN` 状态，并且由于 Slurm 检测到节点故障，自动将作业重新排队。
+ 经过 `SuspendTimeout`（默认为 120 秒（2 分钟））之后 `queue1-dy-spotcompute1-2` 变为可用。在此期间，作业将重新排队，并可以开始在另一个节点上运行。
+ 上述过程将会重复，直到作业可以在可用节点上运行而不发生故障。

**有两个定时参数可以根据需要进行调整：**
+ **`ResumeTimeout`（默认为 30 分钟）：**`ResumeTimeout` 控制 Slurm 将节点转变为关闭状态之前等待的时间。
  + `ResumeTimeout`如果您的 pre/post 安装过程花费了将近那么长的时间，那么扩展可能会很有用。
  + `ResumeTimeout` 也是在出现问题的情况下 AWS ParallelCluster 在替换或重置节点之前等待的最长时间。如果在启动或设置过程中发生任何错误，则计算节点会自行终止。 AWS ParallelCluster 检测到已终止的实例后，进程会替换节点。
+ **`SuspendTimeout`（默认为 120 秒（2 分钟））**：`SuspendTimeout` 控制将节点放回系统并准备好再次使用的速率。
  + `SuspendTimeout` 越短，节点重置就会越快，并且 Slurm 能够更频繁地尝试启动实例。
  + `SuspendTimeout` 越长，故障节点的重置就会越慢。在此期间，Slurm 会尝试使用其他节点。如果 `SuspendTimeout` 超过几分钟，则 Slurm 将会循环尝试系统中的所有节点。对于大型系统（超过 1000 个节点），较长的 `SuspendTimeout` 可能有利于减轻 Slurm 上因频繁尝试对失败作业重新排队而产生的压力。
  + 请注意，`SuspendTimeout`这并不是指 AWS ParallelCluster 等待终止节点的后备实例的时间。`POWER_DOWN` 节点的支持实例将会立即终止。终止过程通常在几分钟内完成。但在此期间，节点仍处于 `POWER_DOWN` 状态，无法供调度器使用。

## 架构的日志
<a name="multiple-queue-mode-slurm-user-guide-v3-logs"></a>

以下列表包含关键日志。与 Amazon Logs 一起使用的 CloudWatch 日志流名称的格式{{logIdentifier}}为`{{{hostname}}}.{{{instance_id}}}.{{{logIdentifier}}}`，后面是日志名称。
+ `ResumeProgram`: `/var/log/parallelcluster/slurm_resume.log` (`slurm_resume`)
+ `SuspendProgram`: `/var/log/parallelcluster/slurm_suspend.log` (`slurm_suspend`)
+ `clustermgtd`: `/var/log/parallelcluster/clustermgtd.log` (`clustermgtd`)
+ `computemgtd`: `/var/log/parallelcluster/computemgtd.log` (`computemgtd`)
+ `slurmctld`: `/var/log/slurmctld.log` (`slurmctld`)
+ `slurmd`: `/var/log/slurmd.log` (`slurmd`)

## 常见问题以及调试方法：
<a name="multiple-queue-mode-slurm-user-guide-v3-common-issues"></a>

**无法启动、加电或加入集群的节点**
+ 动态节点：
  + 检查 `ResumeProgram` 日志，查看是否对该节点调用过 `ResumeProgram`。如果没有，请检查 `slurmctld` 日志以确定 Slurm 是否尝试过对该节点调用 `ResumeProgram`。请注意，`ResumeProgram` 上不正确的权限可能会导致它静默失败。
  + 如果调用了 `ResumeProgram`，请查看是否为该节点启动了实例。如果未启动实例，则应有明确的错误消息，说明实例启动失败的原因。
  + 如果启动了实例，则可能在引导过程中出现了问题。从`ResumeProgram`日志中找到相应的私有 IP 地址和实例 ID，然后在 Logs 中查看特定实例的相应引导 CloudWatch 日志。
+ 静态节点：
  + 检查 `clustermgtd` 日志，查看是否为该节点启动了实例。如果实例未启动，则应有明确的错误说明实例启动失败的原因。
  + 如果启动了实例，则引导过程出现了问题。从`clustermgtd`日志中找到相应的私有 IP 和实例 ID，然后在 Logs 中查看特定实例的相应引导 CloudWatch 日志。

**节点意外替换或终止和节点故障**
+ 节点 replaced/terminated 出乎意料：
  + 在大多数情况下，`clustermgtd` 会处理所有节点维护操作。要检查 `clustermgtd` 是否替换或终止了节点，请查看 `clustermgtd` 日志。
  + 如果 `clustermgtd` 替换或终止了节点，则应显示一条消息，说明该操作的原因。如果原因与调度器有关（例如，节点处于 `DOWN` 状态），请查看 `slurmctld` 日志以获取更多详细信息。如果原因与亚马逊 EC2 有关，请使用诸如亚马逊 CloudWatch 或亚马逊 EC2 控制台、CLI 或软件开发工具包之类的工具来检查该实例的状态或日志。例如，您可以检查该实例是否有已安排的事件或失败的 Amazon EC2 运行状况检查。
  + 如果 `clustermgtd` 没有终止该节点，请检查 `computemgtd` 是否终止了该节点，或者 EC2 是否终止了该实例以回收竞价型实例。
+ 节点故障：
  + 在大多数情况下，如果节点出现故障，作业会自动重新排队。在 `slurmctld` 日志中查看作业或节点失败的原因，并在其中评测具体情况。

**替换或终止实例时出现故障、关闭节点时出现故障**
+ 通常，`clustermgtd` 会处理所有预期的实例终止操作。在 `clustermgtd` 日志中查看其无法替换或终止节点的原因。
+ 对于 [`ScaledownIdletime`](Scheduling-v3.md#yaml-Scheduling-SlurmSettings-ScaledownIdletime) 失败的动态节点，请在 `SuspendProgram` 日志中查看 `slurmctld` 进程是否以特定节点作为参数进行了调用。请注意，`SuspendProgram` 实际上并不执行任何特定的操作，它只是记录被调用时的时间。所有实例终止和 `NodeAddr` 重置均由 `clustermgtd` 完成。Slurm 会在 `SuspendTimeout` 后将节点转变为 `IDLE` 状态。

**其它问题：**
+ AWS ParallelCluster 不会做出工作分配或扩大规模的决策。它只是尝试按照 Slurm 的指示启动、终止和维护资源。

  对于与作业分配、节点分配和扩展决策有关的问题，请查看 `slurmctld` 日志中是否存在错误。