LinuxでのWatchdogデーモンの設定:システムフリーズの自動検知と高可用性のための自動再起動

Linux tutorial - IT technology blog
Linux tutorial - IT technology blog

クイックスタート(5分)

リモートのLinuxサーバーが完全にフリーズした場合、通常はIPMIコンソールへのログインやクラウドアカウントのハイパーバイザーへのアクセス、あるいは物理的なリセットボタンの押下が必要になります。Linuxのwatchdogデーモンを使えば、そうした手動対応の手間を回避できます。OSの健全性を継続的に監視し、カーネルのハングや重要リソースの枯渇を検知すると即座に再起動を実行します。

DebianやUbuntuでは、softdogカーネルモジュールと標準のwatchdogパッケージを利用して、5分足らずで基本的なソフトウェアWatchdogをセットアップできます。

まず、カーネルモジュールをロードし、再起動後も永続化されるよう設定します。

sudo modprobe softdog
echo "softdog" | sudo tee -a /etc/modules-load.d/watchdog.conf
ls -l /dev/watchdog

キャラクターデバイス /dev/watchdog が存在することを確認します。次に、ユーザースペースデーモンをインストールします。

sudo apt update
sudo apt install -y watchdog

お好みのエディタで /etc/watchdog.conf を開きます。

sudo nano /etc/watchdog.conf

以下の基本パラメータのコメントアウトを解除、または追記して、ハートビート間隔とCPUロードアベレージの閾値を設定します。

watchdog-device = /dev/watchdog
watchdog-timeout = 60
interval = 10
max-load-1 = 24

ファイルを保存し、サービスを有効化して起動します。

sudo systemctl enable --now watchdog
sudo systemctl status watchdog

これでWatchdogが有効になりました。カーネルがフリーズしたり、ロードアベレージが設定した閾値(例: 16コアサーバーで24)を超えたりした場合、Watchdogタイマーがタイムアウトし、60秒後に強制再起動が実行されます。

詳細解説:Linux Watchdogデーモンの仕組み

カーネルレベルのタイマーとユーザースペースデーモンの連携動作を理解しておくことで、誤った再起動や設定ミスを防ぐことができます。

ハートビートのメカニズム

Watchdogの核となるのは、ハードウェアまたはカーネルのカウントダウンタイマーです。初期化されると、タイマーは設定された時間(例: 60秒)からゼロに向かってカウントダウンを開始します。通常運用中、ユーザースペースデーモンは /dev/watchdog に定期的にキープアライブバイトを書き込みます。システム管理者の間では、このタイマーのリセット処理を「犬を蹴る(kicking the dog)」または「ハートビート送信」と呼びます。

もしOSが応答不能になったらどうなるでしょうか?OOM(メモリ不足)によるハングアップでスケジューラが停止したり、ドライバの不具合でカーネルパニックが発生したりすると、デーモンはチェックインできなくなります。その結果、タイマーがゼロに達し、下位のWatchdogハードウェアが即座にシステムリセットを強制実行します。

ハードウェアWatchdog vs ソフトウェアWatchdog

ハードウェア構成と求められる信頼性要件に応じて、適切なWatchdogドライバを選択してください。

  • ソフトウェアWatchdog(softdog): 純粋なカーネルタイマーモジュールです。特別なハードウェアパススルーなしで、KVM、Proxmox、AWS EC2インスタンスなどの仮想環境内で動作します。ただし、カーネルのタイマー割り込みに依存しているため、致命的なCPUロックアップやハイパーバイザー自体の停止が発生した場合は、softdogによるリセットが発火しない可能性があります。
  • ハードウェアWatchdog(IPMI / iTCO_wdt / bcm2835_wdt): 物理サーバー(iDRAC搭載のDell PowerEdgeやiLO搭載のHPE ProLiantなど)やRaspberry Pi 4のようなシングルボードコンピュータのマザーボードには、専用のタイマーマイクロコントローラが組み込まれています。このクロックはホストCPUやOSから独立して動作するため、カーネルが完全に停止した場合でも確実にハードウェアリセットを実行できます。

サーバーのマザーボードがハードウェアWatchdogに対応しているか確認するには、次のコマンドを実行します。

dmesg | grep -i watchdog

iTCO_wdt(Intelチップセット)や ipmi_watchdog などのドライバが表示された場合は、softdog をロードする代わりに、/etc/watchdog.conf の参照先をそのデバイスノードに直接設定してください。

「Magic Close」機能

メンテナンスのためにサービスを停止した際、意図しない再起動を防ぐ仕組みはどうなっているのでしょうか?デーモンには「Magic Close」と呼ばれる安全プロトコルが実装されています。systemctl stop watchdog で正常に停止される際、デーモンはファイルハンドルをクローズする直前に /dev/watchdog へASCII文字の V を書き込みます。カーネルドライバはこの意図的なシャットダウンコードを検知し、安全にカウントダウンタイマーを解除します。

高度な活用法:カスタムヘルスチェックとネットワークPing

Watchdogデーモンは、CPUスケジューラの応答確認だけでなく、空きメモリ、ネットワークゲートウェイ、重要なデーモンのPID、カスタムアプリケーションのエンドポイントの監視にも対応しています。

リソースおよびネットワーク閾値の設定

以下は、インターネットに接続されたノード向けに実績のある /etc/watchdog.conf の設定例です。

# Watchdogデバイスとハートビート間隔
watchdog-device = /dev/watchdog
interval = 5
watchdog-timeout = 30

# 空きRAMが128MBを下回った場合に再起動
min-memory = 128M

# 1分間のロードアベレージが30を超えた場合に再起動
max-load-1 = 30

# ネットワーク疎通確認のためローカルゲートウェイへPing
ping = 192.168.1.1
interface = eth0

# WebサーバープロセスのPID生存確認
pidfile = /var/run/nginx.pid

ローカルゲートウェイが長期間ICMPパケットに応答しなくなったり、メモリリークにより利用可能RAMが128MB未満に低下したりした場合、Watchdogが異常を検知してホストを再起動します。

カスタムテストスクリプトの作成

事前定義された設定項目だけでは、あらゆるエッジケースをカバーできない場合があります。幸いにも、/etc/watchdog.d/ 配下に独自のシェルスクリプトを配置することで柔軟に対応できます。デーモンはハートビートサイクルごとにこのディレクトリ内のすべてのスクリプトを実行し、終了ステータスが1〜244の場合はチェック失敗とみなします。

例えば、ポート8080で動作する内部マイクロサービスが3秒以内にHTTP 200を返すか検証するには次のように設定します。

sudo mkdir -p /etc/watchdog.d
sudo nano /etc/watchdog.d/check_api.sh

以下のスクリプトを貼り付けます。

#!/usr/bin/env bash

# 3秒のタイムアウトで内部APIの健全性を確認
HTTP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" --max-time 3 http://127.0.0.1:8080/health)

if [ "$HTTP_STATUS" -eq 200 ]; then
    exit 0
fi

exit 1

スクリプトに実行権限を付与します。

sudo chmod +x /etc/watchdog.d/check_api.sh

次に、/etc/watchdog.conf 内でテストディレクトリのポーリングを有効にします。

test-directory = /etc/watchdog.d
test-timeout = 10

サービスを再起動してヘルスチェックスクリプトを反映させます。

sudo systemctl restart watchdog

本番環境運用の実践的なヒント

Watchdogの設定を過度に厳格にすると、サーバーが無限再起動ループに陥る恐れがあります。復旧の自動化を安全に運用するために、以下の実践的なガイドラインに従ってください。

適切なインターバル調整と軽量なスクリプト設計

ヘルスチェックスクリプトは常にシンプルかつ短時間で終わるように設計してください。DNSクエリやデータベースのロック待ちでプローブが停滞すると、Watchdog自体のループ処理時間を圧迫してしまいます。/etc/watchdog.d/ 内で複雑なDBクエリを実行したり、多重サブシェルを呼び出したりすることは避けてください。

watchdog-timeout は必ず interval の2〜3倍以上に設定してください。ハートビート間隔が10秒であれば、Watchdogタイムアウトは30秒または60秒に設定します。このバッファを設けることで、一時的な高I/O負荷が発生した際にも、短時間の遅延を致命的なフリーズと誤判定するのを防ぐことができます。

検証のためのシステムロックアップ擬似再現

本番フリートへ導入する前に、必ずステージング環境で設定をテストしてください。Linux Magic SysRqキーを使用すれば、復旧不能なカーネルパニックを安全にシミュレートできます。まず、カーネルでSysRqトリガーが有効になっていることを確認します。

sudo sysctl -w kernel.sysrq=1

サーバーのシリアルコンソールまたはアウトオブバンド(OOB)コンソールに接続し、意図的にカーネルクラッシュを発生させます。

echo c | sudo tee /proc/sysrq-trigger

SSHセッションが即座に応答しなくなります。アウトオブバンド管理コンソールを確認すると、設定された watchdog-timeout の時間が経過した直後にハードウェアタイマーが発火し、電源が再投入されてクリーンなログインプロンプトへ復帰します。

ブートループとファイルシステム破損の防止

Watchdogによるリセットは、通常の shutdown -r now による安全なシャットダウンではなく、不意のハードウェアリセットである点に注意が必要です。PostgreSQL、Redis、MySQLなどのデータベースは、起動時のクラッシュリカバリに数分かかることがあります。起動直後に短いタイムアウト設定でMySQLを監視すると、データベースがWALログをリプレイしている最中に再びリセットがかかってしまう危険があります。

ブートループを防止するには、systemdの依存関係(After=network.target など)を活用し、重要なアプリケーションユニットに適切な起動タイムアウトを設定してください。十分なバッファを確保することで、Watchdogの監視対象となる前にサービスがクラッシュリカバリを完了できるようになります。

Share: