Supermicro SYS-4028GR-TXRT がシャットダウン後に復活するので、ipmitool で電源を切るようにした
自宅ラボ環境の GPU サーバーが、シャットダウンしても止まらなくなりました。
GPU Console(GPU サーバーの環境を管理するために自作した Web UI)で Graceful Shutdown を押すと、電源はいったん落ちます。
ところが、数秒後には再び起動します。
SSH から systemctl poweroff を実行しても同じでした。
先に結論を書くと、OS の終了処理を済ませたあとに ipmitool で BMC へ電源断を指示するようにしたところ、電源 OFF のまま止まるようになりました。
自動で起動してしまう原因そのものは、まだ特定できていません。
電源はいったん切れている
対象は Supermicro の SYS-4028GR-TXRT で、マザーボードは X10DGO-T です。
調査した時点の BIOS は 2.0a、BMC ファームウェアは 2.03、通常起動の Linux カーネルは 7.0.0-34-generic でした。
GPU Console の Graceful Shutdown は、内部で次の IPMI コマンドを送っています。
ipmitool chassis power soft
soft は ACPI 経由で OS に終了を求める操作で、off は OS の終了処理を待たずに電源を切る操作です。
この違いは ipmitool の公式マニュアル に書かれています。
最初は GPU Console 側の不具合を疑いました。
そこで、外部ホストから BMC の電源状態を監視しながら、GPU Console と同じコマンドと OS の systemctl poweroff の両方で電源を切ってみました。
| 操作 | OFF を検出 | 再び ON を検出 | OFF だった時間 |
|---|---|---|---|
GPU Console と同じ chassis power soft |
03:48:24.208 | 03:48:28.629 | 約 4.4 秒 |
OS の systemctl poweroff |
03:51:04.781 | 03:51:08.811 | 約 4.0 秒 |
時刻は調査日の UTC です。
どちらの試験でも電源を切るコマンドは 1 回だけ送り、最初の試験の間は GPU Console の画面にある電源ボタンにも触れていません。
どちらの経路でも、電源は一度 OFF になってから 4 秒ほどで ON に戻っていました。
起動のきっかけになりそうな設定を確かめる
まず、自動起動のきっかけになりそうな設定を確認しました。
- 接続中の NIC の Wake-on-LAN は無効
- BMC の Power Restore Policy は
always-off - BIOS の Restore on AC Power Loss は
Stay Off - BMC と systemd の watchdog は無効
- RTC に起動予約はない
未接続の NIC だけは WOL が有効だったので、ACPI、PCIe、USB の wake とまとめて一時的に無効にしました。
それでも結果は変わりません。
ほかにも条件を変えて試した結果が次の表です。
| 試した条件 | 結果 |
|---|---|
| ACPI、PCIe、USB の wake と、両 NIC の WOL を無効化 | 約 4.0 秒後に自動起動 |
| BMC を cold reset してから poweroff | 約 4.1 秒後に自動起動 |
旧カーネル 7.0.0-29-generic で poweroff |
約 4.1 秒後に自動起動 |
| NVIDIA 関連サービスを止め、ドライバをすべてアンロード | 約 4.1 秒後に自動起動 |
旧カーネルでも、NVIDIA 関連のサービスとドライバを止めた状態でも、約 4 秒後に起動しました。
新しいカーネルだけで起きる症状ではなく、稼働中の NVIDIA ドライバが引き起こしている可能性も低そうです。
試験のために変えた wake の設定と起動カーネルは、あとで元に戻しました。
OS のログを見ると、poweroff.target までは到達しています。
journal が止まったあとの出力もシリアルコンソールで採取したところ、最後の行は次のとおりでした。
Powering off.
[131.033911] reboot: Power down
接頭辞は reboot: ですが、メッセージは Power down なので、カーネルは電源断を選んでいます。
BIOS、BMC、基板のどこで起動がかかっているのかは、このログからは分かりません。
halt してから BMC で切ると止まる
次に、OS の停止と電源断を別々に行ってみました。
まず SSH から OS を停止します。
sudo systemctl halt
停止が終わったのを確かめてから、別の管理ホストから BMC に電源断を指示します。
接続先とユーザー名は例です。
ipmitool -I lanplus -H <BMCのアドレス> -U <管理ユーザー> -a chassis power off
halt の完了後に BMC へ off を送ると、観測した 60 秒間は OFF のままでした。
その後はこちらから Power On して試験を終えました。
このときは halt から 45 秒待ってから off を送りましたが、停止にかかる時間は動いている処理によって変わります。
off は OS を正常に終了させるコマンドではないので、手で送るなら秒数を決め打ちせず、KVM やシリアルコンソールで停止の完了を確かめてからにします。
毎回これを手で行う代わりに、通常の poweroff の最後で、OS 自身から BMC へ off を送らせることにしました。
systemd の最終フックから ipmitool を呼ぶ
使ったのは systemd のシャットダウンフックです。
次の場所に実行可能なスクリプトを置きました。
/usr/lib/systemd/system-shutdown/bmc-poweroff
このディレクトリにある実行ファイルは、サービスが止まったあと、電源を切る直前に呼ばれます。
引数には poweroff、halt、reboot などの操作名が渡され、複数のフックは並列に実行されます(systemd の公式ドキュメント)。
今回のフックは poweroff のときだけ動き、次の順に処理します。
- 既存の fwupd と mdadm の終了処理が終わるのを待つ
- 永続ストレージに書き込み可能なマウントが残っていないこと、swap が止まっていることを確かめる
syncを完了させる- ローカルの IPMI インターフェースを復旧する
- BMC に電源断を 1 回だけ送る
最後に送るのは次のコマンドです。
ipmitool -I open chassis power off
-I open はローカルの IPMI デバイスを使う指定なので、ネットワーク越しの認証情報は要りません(ipmitool の公式マニュアル)。
終了処理の待機やストレージの確認に失敗したときは、BMC への off は送らず、通常の poweroff の経路に戻します。
フックの全体は bmc-poweroff.sh に置きました。
使うときは拡張子を外して /usr/lib/systemd/system-shutdown/bmc-poweroff に置き、実行権限を付けます。
ログはコンソールとシリアルポートの /dev/ttyS1 に書き出しているので、シリアルポートの番号は機体に合わせて変えてください。
この形に落ち着くまでに、試験で 2 回つまずきました。
終わったはずのフックを待っていた
最初の試験では、fwupd の処理がまだ残っていると判定して通常の poweroff に戻り、元どおり自動起動しました。
待っていたプロセスを調べると、実行中ではなく、終了済みのゾンビプロセスになっていました。
並列に動くフックは systemd が回収するまでプロセス情報が残るので、プロセス名だけで判定すると、終了処理がまだ続いているように見えます。
プロセスの状態も見るようにして、終了済みの Z と X は待つ対象から外しました。
シャットダウン中に /dev/ipmi0 が消えていた
次の試験では、ルートファイルシステムが読み取り専用になり、swap も止まったところまでは確認できました。
ところが、最後の ipmitool が失敗しました。
この環境の openipmi.service は、停止するときに ipmi_devintf をアンロードします。
そのため、普段は存在する /dev/ipmi0 が、最終フックの時点ではなくなっていました。
フックの中で ipmi_si と ipmi_devintf を読み込み直し、必要なら /proc/devices から取ったメジャー番号で /dev/ipmi0 を作り直すようにしました。
普段のシャットダウンで止まるようになった
直したあと、普段どおりの操作で試しました。
sudo systemctl poweroff
コンソールには、ipmitool の次の応答が出ました。
Chassis Power Control: Down/Off
外部からの監視では、05:04:52.813 から 05:05:53.964 までの約 61 秒間、OFF のままでした。
GPU Console と同じ chassis power soft でも、最終フックから off が送られ、60 秒以上 OFF のままになることを確かめました。
どちらの試験も、最後はこちらから起動しています。
今の電源断の流れは次のとおりです。
Graceful Shutdown / systemctl poweroff
→ OS のサービス停止・ストレージ終了処理
→ 最終フックでローカル IPMI を復旧
→ BMC に chassis power off
→ 電源 OFF を維持
フックで電源を切ったあとに起動し直しても、停止前に動いていた 7 個のコンテナと、Open WebUI、ComfyUI、llama-server は元どおり復帰しました。
フックを止めたいときは、実行権限を外します。
sudo chmod -x /usr/lib/systemd/system-shutdown/bmc-poweroff
ただし、そうすると通常の poweroff に戻るので、この機体では自動起動が再発する可能性があります。
原因はまだ分かっていない
通常の poweroff と、OS を止めてから BMC へ off を送る場合とで、結果が分かれることまでは確認できました。
ただし、この違いが BIOS、BMC、基板のどこで生じているかは特定できていません。
観測も 60 秒程度なので、長く止めておいた場合や、繰り返し実行した場合の挙動もまだ確かめていません。
現在は、GPU Console の Graceful Shutdown からこのフックを経由して電源を切っています。