複数台の計算ノードが四六時中計算しているわけでもなく、夜間や連休時にはアイドリングの時もある
そのような時に計算機自体を停止できれば余分な電気代が浮く.
slurmにはそのような一定時間、ジョブが来なければ計算ノードを停止する機能がある
そしてジョブが発行されたらその時に起動して、ジョブを受ける.
ここではその機能を使ってみる
計算機を止めるのは簡単。相手先にsshで入って「shutdown -h now」を発行するだけ.
でも起動には?
ここでは検証環境として proxmox v9.1.1 を使っている.
この場合、proxmoxホストに飛んでくるMACアドレスを含むマジックパケットをキャッチしてvmを起動させるデーモンを用意するか
ipmi方式ならproxmoxに VirtualBMC を仕込んで各vmにBMCを持たせるようにする.
ここでは簡単に「Wake-on-LAN」方式を採用してみます.
まず起動させたいvmのIDとMACアドレスは下記とします
vm101 bc:24:11:7b:4a:d4
vm102 bc:24:11:9b:9d:dbそして proxmoxホスト内に下記内容の「/usr/local/bin/vm-wol.sh」を用意します
- ! - | - - | | ! ! | - - | | ! ! | ! | |
これを起動させておきます. serviceにさせるまでもなく、単にずっと動かしていればいい. proxmoxホストに入って、下記を実行する
root@f:~# bash /usr/local/bin/vm-wol.sh
停止はCtrl-C で止まります
他のマシンや、同じproxmox内の別のvmに「net-tools」パッケージをインストールして「ether-wake」コマンドで対象マシンを起動させます
「-b」はブロードキャスト、「-i」は使用するインターフェースを指定します
dnf install net-tools
ether-wake -b -i enp6s18 bc:24:11:7b:4a:d4これでproxmox内のvmを起動できます
っで肝心のslurm.confの設定です. 「/opt/slurm/etc/slurm.conf」に追記します
[root@slurm ~]# vi /opt/slurm/etc/slurm.conf
:
SlurmUser=slurm
:
SuspendProgram=/opt/slurm/sbin/slurm_suspend.sh # idle状態のまま SuspendTime(秒) 経過後に計算ノードに放たれる スクリプト. SlurmUser によって実行されます
ResumeProgram=/opt/slurm/sbin/slurm_resume.sh # ジョブが発行されてターゲットの計算ノードに向けて放たれる スクリプト
SuspendTime=600 # idle状態でこの時間(秒)が過ぎたら SuspendProgram が動きます
SuspendTimeout=120 # SuspendProgramが実行後、このSuspendTimeout(秒)が経っても生きていたら「正常に停止できなかった異常ノード」として記録される
SuspendRate=10 # 一度に全部の計算ノードに SuspendProgram を放つのではなく、1分ごとにSuspendRate 台数分ずつ SuspendProgram を放つ.
ResumeTimeout=300 # ResumeProgram が実行されてResumeTimeout(秒) 後もまだ起きていないならDOWNと定義される
ResumeRate=10 # 一度に立ち上がる計算ノードの数を制限. 1分ごとに ResumeRate 台数分ずつ ResumeProgram を放つ. 電源設備の保護目的
#SuspendExcNodes = r9-[3-5] # 絶対落とさせない計算ノードを指定します
#SuspendExcParts # 絶対落とさせない計算queue. このqueueに含まれる計算ノードに suspendprogram は送らないです.
[root@slurm ~]#このように定義して「scontrol reconfig」で読み込ませる.
スクリプトの実行者はslurm.confで定義される「SlurmUser=slurm」です.
なのでそのユーザにはプログラムを実行できるように loginshell を「/bin/bash」へとかあとホームディレクトリを用意したりが必要かも. slurmctldホストのみ. slurmdはそのまま/bin/false、ホームディレクトリなしでも構わない.
SuspendProgramには引数として 対象となる計算ノード名が "node[001-004]" として渡ります.
これを for do で展開させ1つ1つの計算ノード名にして停止スクリプトを実行させる.
例えば「/opt/slurm/sbin/slurm_suspend.sh」として
#!/bin/bash
LOG=/tmp/slurm-suspend.log
SCONTROL=/opt/slurm/bin/scontrol
BMC_USER=ADMIN
BMC_PASSWORD=ADMIN
{
echo "==== $(date) ===="
echo "raw argument: $1"
for node in $($SCONTROL show hostnames "$1"); do
echo "suspend target: $node"
# ssh経由の場合
ssh -l root $node /usr/sbin/shutdown -h now # ユーザslurmで動かすなら公開鍵を作って各計算ノードの/root/.ssh/authorized_keys に追記
# ipmi経由の場合. 計算ノードのipmiポートのホスト名が ${host}-ipmi (r9-1-ipmi) なら
#ipmitool -H ${node}-ipmi -U "${BMC_USER}" -P "${BMC_PASSWORD}" chassis power off
done
} >> "$LOG" 2>&1
exit 0な感じで. ipmitoolを使う場合は、計算ノードのホスト名とは違って、ipmi向けホスト名があると思うので、host名が「r9-1」なら「r9-1-ipmi」とhost名から連携できると嬉しいかも.
同じく実行者は「SlurmUser=」のユーザになります.
立ち上げは Wake-on-LAN か ipmi のいずれかの方法で
Wake-on-LANの場合はスクリプト内にホスト名とMACアドレスの対応表を持っておく必要があるので、ipmi形式が楽かなぁ
あとWake-on-LANの場合、実行者の「SlurmUser=」が管理者権限で ether-wake を実行させる必要があるので sudo に入れて NOPASSWD で実行できるようにします
「/opt/slurm/sbin/slurm_resume.sh」として
#!/bin/bash
LOG=/tmp/slurm-resume.log
SCONTROL=/opt/slurm/bin/scontrol
{
echo "==== $(date) ===="
echo "raw argument: $1"
for node in $($SCONTROL show hostnames "$1"); do
echo "resume target: $node"
# Wake-on-LAN の場合
if [ "$node" == "r9-1" ]; then
sudo /usr/sbin/ether-wake -b -i enp6s18 bc:24:11:7b:4a:d4
elif [ "$node" == "r9-2" ]; then
sudo /usr/sbin/ether-wake -b -i enp6s18 bc:24:11:9b:9d:db
fi
# ipmi経由の場合. 計算ノードのipmiポートのホスト名が ${host}-ipmi (r9-1-ipmi) なら
#ipmitool -H ${node}-ipmi -U "${BMC_USER}" -P "${BMC_PASSWORD}" chassis power on
done
} >> "$LOG" 2>&1
exit 0とします
Wake-on-LANは台数分のMACアドレスの登録が必要になるのでかなり面倒かなぁ.
いちおう検証環境の proxmox 内では動いた.
実環境でしかもipmitoolでも試してみたいが、あてがない.
あと、「計算機をいちいち止めると故障になるかも」との懸念はあり得る。でも「HDDなどの回転装置がないなら半導体だけなので故障しないのでは?」とも思う。
研究室にたくさんの計算機があって暑い。毎月の電気代が高い。とかなら試してもいいような感じでしょうか。