Sougen Blog

Supermicro SYS-4028GR-TXRT がシャットダウン後に復活するので、ipmitool で電源を切るようにした

linuxsupermicroipmisystemdhomelab

自宅ラボ環境の 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 だけは 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 のときだけ動き、次の順に処理します。

  1. 既存の fwupd と mdadm の終了処理が終わるのを待つ
  2. 永続ストレージに書き込み可能なマウントが残っていないこと、swap が止まっていることを確かめる
  3. sync を完了させる
  4. ローカルの IPMI インターフェースを復旧する
  5. 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 からこのフックを経由して電源を切っています。