Slurmでジョブの投入制限を設定する

## やりたいこと
現在Slurmで管理しているクラスタへのジョブ同時投入数、同時実行数を制限する。
今回はパーティション単位の制限とユーザ単位の制限の2パターンを設定し、リソース制限の階層構造についても理解する。

## 前提環境
- Unixアカウント（LDAP）
- Slurmクラスタ（SlurmDBDがインストール済）

**※注意事項：必ずUnixユーザ名(UID)≠Unixグループ名(GID)**にする必要があります。
詳細は[Slurm account synchronization　with　UNIX　groups and users](https://slurm.schedmd.com/SLUG19/DTU_Slurm_Account_Sync.pdf)を参照してください。

## UnixアカウントとSlurmアカウントをSyncさせる

#### Slurmアカウント、ユーザの作成
UnixユーザとSlurmユーザを同期させるためには、Slurm側で以下2点を作成する必要があります。

- ①`Unixグループと同名のSlurmアカウント`
- ②`Unixユーザと同名Slurmユーザ`

　詳細は[Slurm account synchronization　with　UNIX　groups and users | P6](https://slurm.schedmd.com/SLUG19/DTU_Slurm_Account_Sync.pdf)を参照してください。

**Unixアカウントの確認**

```bash:Command
id handson
```

```bash:出力例
uid=132400015 gid=132400013(handson-group) groups=132400013(handson-group) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
```

**Slurmアカウントの作成**
ユーザの所属するGroupをslurmのaccountに指定します。

```bash:Command
sacctmgr add account handson-group
```

確認コマンド

```bash:
sacctmgr list account
```
```bash:出力例
   Account                Descr                  Org 
---------- -------------------- -------------------- 
handson-+        handson-group        handson-group 
      root default root account                 root 
```

**Slurmユーザの作成**

```bash:Command
sacctmgr add user handson account=handson-group
```

確認コマンド

```bash:Command
sacctmgr list user 
```

```bash:出力例
      User   Def Acct     Admin 
---------- ---------- --------- 
  handson  handson-+      None 
      root       root Administ+ 
```


## ジョブの投入制限、実行制限の設定

#### Slurmにおけるリソースの制限について
Slurmにおけるリソースの制限については、以下7つの階層(方法)で各種制限を設定することができ、各制限については上位の制限が優先されます。

また、設定付与の形式については`association`という設定を個別に指定して付与する形と`QOS`という複数の設定をひとまとめにしたものを付与する形があります。

**Slurmにおけるリソース制限の階層**

``` 
1. Partition QOS limit  
2. Job QOS limit
3. User association 
4. Account※ association 
5. Root/Cluster association
6. Partition limit
7. None
```
※SlurmにおけるアカウントはUnixにおけるユーザグループとマッピングされます。

今回の設定したい項目であるジョブの実行数、投入数の制限に関する設定項目を[公式サイト](https://slurm.schedmd.com/resource_limits.html)で確認し抜粋してみました。

**ジョブ数制限関連の設定**
associationとして指定できるもの、QOSとして指定できるものをそれぞれの列に記載しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/161999/d49fff4a-6b62-7bdb-089c-fd943974aa88.png)

#### リソース制限を有効にする
ｓlurmのコンフィグファイル`slurm.conf`に以下設定を追記します。

```bash:Command
echo "AccountingStorageEnforce=limits"  >> /PATH/TO/slurm.conｆ
```

注意：　上記設定を有効にするとユーザのassociationがDBにないとジョブが実行できなくなります。
(= slurmユーザではないUnixアカウントはジョブを実行できなくなる。)

各Head、Computeノードの`slurm.conf`を上書きし設定反映、ヘッドノードの `ｓlurmctld` /コンピュートノードの `ｓlurmd` を `stop/start` します。

```bash:例
sudo systemctl stop slurmctld
sudo pdsh -w ${NODE} "systemctl stop slurmd"
sudo systemctl start slurmctld
sudo pdsh -w ${NODE} "systemctl start slurmd"
sudo systemctl status slurmctld
sudo pdsh -w ${NODE} "systemctl status slurmd"
```

#### ユーザに対してassociationを設定する

`slurm.conf` で指定したSlurmUserにスイッチします。
※ここではrootにスイッチしてます。

```
sudo su -
```

最大ジョブ実行のassociationを設定します。

```bash:Command
sacctmgr modify user handson account=handson-group set MaxJobs=1 
```

設定を確認します。
`format=`に確認したい設定の値を指定することで出力をフィルターできます。

```bash:Command
 sacctmgr show Association format=Cluster,Account,User,MaxJobs,MaxSubmit
```

```bash:出力例
   Cluster    Account       User MaxJobs MaxSubmit 
---------- ---------- ---------- ------- --------- 
  20211012       root                              
  20211012       root       root                   
  20211012 handson-g+                              
  20211012 handson-g+    handson       1           
       
```

ジョブを実行してみます。

```bash:Command
su - handson
```

```bash:Command
sbatch run.sh
sbatch run.sh
sbatch run.sh
```

ジョブの実行状況を確認します。
フェデレーションされている環境では`--federation`オプションを指定します。

```bash:Command
squeue --federation
```

指定した `MaxJobs＝１`　の数を超えるジョブはPendingされていることが見て取れます。

```bash:出力例
             JOBID PARTITION     NAME     USER ST       TIME  NODES NODELIST(REASON)
          67109182    vkix01  handson  handson PD       0:00      1 (AssocMaxJobsLimit)
          67109183    vkix01  handson  handson PD       0:00      1 (AssocMaxJobsLimit)
          67109180    vkix01  handson  handson  R       0:09      1 computenode01
```

#### パーティションにQOSを設定する

SlurmUserにスイッチします。

```bash:Command
exit
sudo su -
```

QOSを作成します。

```bash:Command
sacctmgr add qos handsonqos
```
QOSの設定を変更します。
今回は　最大ジョブ実行数：`MaxJobs=0`、最大ジョブ投入数：`MaxSubmitJobsPerUser=0`を設定しジョブを投入できない状態に設定してみます。

※QOS設定可能な設定値詳細については[ResourceLimit](https://slurm.schedmd.com/resource_limits.html)をご参照ください。

```bash:Command
sacctmgr modify qos handsonqos set MaxJobs=0 MaxSubmitJobsPerUser=0
```

QOSの設定を確認します。
`format=`に確認したい設定の値を指定することで出力をフィルターできます。　<br>※QOSでは`MaxSubmit=MaxSubmitJobsPerUser`です。

```bash:Command
sacctmgr show qos format="Name,MaxWall,MaxTRESPerUser%30,MaxJob,MaxSubmit,Priority,Preempt"
```

```bash:Command
      Name     MaxWall                      MaxTRESPU MaxJobs MaxSubmit   Priority    Preempt 
---------- ----------- ------------------------------ ------- --------- ---------- ---------- 
    normal                                                                       0            
handsonqo+                                                 0         0           0       
```

`slurm.conf`でQOSを設定したいパーティションにQOS設定を追加

```bash:slurm.conf
--抜粋--

PartitionName=debug Nodes=loginnode Default=No MaxTime=INFINITE State=UP
PartitionName=vkix01 Nodes=computenode0[1-2] Default=Yes MaxTime=1:00:00 State=UP QOS=handsonqos
```

各Head、Computeノードの`slurm.conf`を上書きし設定反映、ヘッドノードの `ｓlurmctld` /コンピュートノードの `ｓlurmd` を `stop/start` します。

```bash:例
sudo systemctl stop slurmctld
sudo pdsh -w ${NODE} "systemctl stop slurmd"
sudo systemctl start slurmctld
sudo pdsh -w ${NODE} "systemctl start slurmd"
sudo systemctl status slurmctld
sudo pdsh -w ${NODE} "systemctl status slurmd"
```

```

```bash:update.sh
#!/bin/bash

sudo cp -p /scratch/slurm.conf.tmp /usr/local/etc/slurm.conf

sudo systemctl stop slurmctld
sudo systemctl start slurmctld
sudo systemctl status slurmctld

sudo systemctl stop slurmd
sudo systemctl start slurmd
sudo systemctl status slurmd
```

パーティションの設定を確認します。

```bash:Command
scontrol show partition
```

```bash:出力例
PartitionName=vkix02
   AllowGroups=ALL AllowAccounts=ALL AllowQos=ALL
   AllocNodes=ALL Default=YES QoS=handsonqos
   DefaultTime=NONE DisableRootJobs=NO ExclusiveUser=NO GraceTime=0 Hidden=NO
   MaxNodes=UNLIMITED MaxTime=UNLIMITED MinNodes=0 LLN=NO MaxCPUsPerNode=UNLIMITED
   Nodes=computenode0[3-4]
   PriorityJobFactor=1 PriorityTier=1 RootOnly=NO ReqResv=NO OverSubscribe=NO
   OverTimeLimit=NONE PreemptMode=OFF
   State=UP TotalCPUs=2 TotalNodes=2 SelectTypeParameters=NONE
   JobDefaults=(null)
   DefMemPerNode=UNLIMITED MaxMemPerNode=UNLIMITED
```

他のQOS設定やassociationの設定状況を確認します。

```bash:Command
sacctmgr show Association format=Cluster,User,Priority,MaxJobs,MaxSubmit,QOS
```

```bash:出力例
   Cluster       User   Priority MaxJobs MaxSubmit                  QOS 
---------- ---------- ---------- ------- --------- -------------------- 
  20211012                                                       normal 
  20211012       root                                            normal 
  20211012                                                       normal 
  20211012    handson                  1                         normal 
  20211012                                                       normal 
  20211012   nakamura                  1                         normal 
  20211012                                                       normal 
```

ジョブを実行してみます。

```bash:Command
su - handson
```

```bash:Command
sbatch run.sh
```

パーティションQOSの設定が優先されジョブが実行できないことが確認できました。

```bash:出力例
sbatch: error: QOSMaxSubmitJobPerUserLimit
sbatch: error: Batch job submission failed: Job violates accounting/QOS policy (job submit limit, user's size and/or time limits)
```