まずは「本当に OS 側の再起動なのか、それともハードウェアの電源周りの問題なのか」を切り分けるため、前回ブート直前のログを確認することにした。
AlmaLinux(RHEL 系)では journalctl -b -1 を叩くことで「ひとつ前の起動分」のログをまとめて確認できるため、このコマンドを起点に、カーネルメッセージや systemd のログをざっと洗った。
watchdog.service はいないのに、dmesg に NMI watchdog がいた
頻繁な再起動と聞くと、真っ先に思い浮かぶのが「watchdog」だ。
ソフトウェアの watchdog デーモンが誤検知して再起動をかけているのではないかと疑い、まずは systemd のサービス有無を確認した。
sudo systemctl status watchdogしかし、返ってきたのは次のメッセージだった。
Unit watchdog.service could not be found.この結果から、少なくとも「watchdog.service というユーザーランドのデーモン」は存在していないことが分かった。
次に、カーネルレベルで何か watchdog 関連の機構が動いていないか確認するため、dmesg を検索した。
sudo dmesg | grep watchdogすると、ブート初期化のログに以下のような行が見つかった。
NMI watchdog: Enabled. Permanently consumes one hw-PMU counter.ここで初めて、「このマシンではソフトウェア watchdog ではなく、カーネル内の NMI watchdog(ハードロックアップ検出機構)が有効化されている」ということに気付いた。
再起動の直接のトリガーが NMI watchdog かどうかはまだ分からないものの、原因候補として調査対象に含める価値は十分あると判断した。
NMI watchdog が何をしていて、なぜ切ることにしたのか
Linux カーネルには、CPU やシステムが固まった(ロックアップした)状態を検出するための「lockup watchdog」が用意されている。
このうち、NMI を使って CPU のハードロックアップを検出する仕組みが、いわゆる「NMI watchdog」であり、nmi_watchdog カーネルパラメータや /proc/sys/kernel/nmi_watchdog で制御される。
NMI watchdog は、本来は「CPU が完全に応答しなくなるような異常状態」を検出し、panic やログ出力のきっかけを作ってくれる有用な機能だ。
しかし、特定のハードウェアや仮想化環境との相性、または CPU のパフォーマンスカウンタ周りの挙動によっては、誤検知や意図しない挙動を引き起こし、結果として頻繁な再起動やカーネルパニックの原因になることがある。
今回の環境では、ソフトウェア watchdog も他の明らかな再起動要因も見当たらず、「NMI watchdog を一度無効化して様子を見る」価値があると判断した。
ハング検出機構を弱めることになるため、無効化はあくまで段階的に行い、挙動を観察しながら進める方針にした。
nmi_watchdog を安全に無効化する実践手順
まずは一時的に無効化して挙動を確認
いきなりカーネルパラメータを書き換えて再起動してしまうと、もし副作用があった場合に切り戻しが面倒になる。
そこで、まずは sysctl を使って「今動いているカーネル上で一時的に NMI watchdog を無効化する」手順から試した。
# 一時的に無効化
sudo sysctl kernel.nmi_watchdog=0
# 状態確認
cat /proc/sys/kernel/nmi_watchdog
# → 0 になっていれば無効化されているこの設定は再起動すると元に戻るため、「OS を落とさずに動作を変えて、しばらく様子を見る」用途にちょうど良い。
実際、この状態である程度の時間運用してみたところ、これまで発生していたような謎の再起動は発生しなくなり、他の機能やパフォーマンスへの悪影響も特に見られなかった。
この観察結果から、「少なくともこの環境では NMI watchdog を無効化しても実運用上問題なく、むしろ安定性が改善する」と判断し、恒久的に OFF にする方針に切り替えた。
GRUB のカーネルパラメータで恒久的に無効化
恒久化の方法としては、AlmaLinux(RHEL 系)らしく GRUB のカーネルパラメータに nmi_watchdog=0 を追加するのがもっとも確実だ。
具体的には、/etc/default/grub を編集して GRUB_CMDLINE_LINUX にパラメータを追加する。
GRUB_CMDLINE_LINUX="rhgb quiet nmi_watchdog=0"編集後に GRUB 設定を再生成する。BIOS/UEFI で出力先が異なるので、環境に合わせたパスを指定する必要がある。
sudo grub2-mkconfig -o /boot/grub2/grub.cfg # BIOS の例
# UEFI 環境なら /boot/efi/EFI/almalinux/grub.cfg などに合わせる再起動後、以下のコマンドで NMI watchdog が無効になっていることを確認する。
cat /proc/sys/kernel/nmi_watchdog
# → 0 であればカーネルパラメータが効いている必要であれば、/etc/sysctl.d/disable_nmi_watchdog.conf のようなファイルを作成し、kernel.nmi_watchdog = 0 を書いておくことで、sysctl 側でも同じ設定を維持できる。
ただし、カーネルパラメータ側で既に 0 にしている場合、sysctl は補強的な意味合いになる。
まとめ:再起動は止まったが、監視設計は別途考える
NMI watchdog を無効化してからしばらく運用した結果、これまで悩まされていた原因不明の再起動は発生しなくなった。
ログにも NMI 関連のメッセージは出なくなり、アプリケーション側の挙動も安定しているため、この環境では NMI watchdog が不安定要因のひとつだったと判断している。
一方で、NMI watchdog は本来「致命的なハングを検出してくれるセーフティネット」であり、単純に切ればいい機能というわけでもない。
ベアメタルのサーバであれば、IPMI や外部監視システムによる死活監視を併用する、仮想環境であればハイパーバイザ側の監視機構に任せる、など別のレイヤでの監視設計を組み合わせるのが望ましい。
今回の例では、「謎の再起動に悩んでいる場合、watchdog.service だけでなく、dmesg | grep watchdog で NMI watchdog を含むカーネルレベルの watchdog も疑うべき」という学びがあった。
同じように AlmaLinux / RHEL 系で頻繁な再起動に直面している人の参考になれば幸いだ。