意図的に停止したサービスをウォッチドッグが再起動してしまいました
オペレーション
当社のウォッチドッグの1つは、有効になっているのに稼働していないサービスを起動します。10月に2回、意図的に停止したサービスを起動してしまいました。2回目は、あるサイトの訪問者が約45分間エラーに遭遇しました。
そのウォッチドッグが存在する理由
例えば、名前を指定してプロセスをkillされた場合など、SIGTERMを受けて正常に終了したサービスは、systemdから見れば「failed」ではありません。Restart=on-failureでは再起動されず、systemctl --failedにも表示されません。誰かが偶然気づくまで停止したままです。そのため、ウォッチドッグは有効だが稼働していないサービスを探し、起動します。
問題は、手動で停止したサービスがまったく同じ状態に見えることです。
1回目
10月7日、ジョブキューを編集するため、12:47にsystemctl stopを使ってビデオワーカーを停止しました。12:55には再び稼働していました。ウォッチドッグが起動したのです。
2回目
10月21日、当社の2つのサイトも稼働させているマシンのメモリをモデルテスト用に確保する必要がありました。スクリプトでサイトのWebアプリ、同期ジョブ、データベースコンテナを停止しました。これもsystemctl stopを使用しました。約5分後、サイトを監視するタイマーが、そして19:14にウォッチドッグがトンネルとWebアプリを起動しました。
トンネルは再びトラフィックを受け付けましたが、Webアプリは応答できませんでした。テスト中のモデルがマシンのメモリを114 GiB占有していたためです。19:14頃から20:00頃まで、一部の訪問者に502エラーが発生しました。20:00にトンネル、Webアプリ、同期ジョブを無効化し、監視タイマーを停止しました。
現在使用しているルール
- サービスを停止するには無効化します:
sudo systemctl disable --now <unit>。復帰にはsudo systemctl enable --now <unit>を使用します。当社のウォッチドッグは有効なサービスのみを確認するため、無効なサービスには干渉しません。 - 復帰させうるものすべてを停止します: 手前のトンネルや、サービスを監視するタイマーなどです。
- 短時間の停止はレースです。
stopのみを使用する場合、次のチェックまでに作業を終えてください。当社のマシンでは数分以内にチェックが実行されます。
同じ月に遭遇した、systemdに関するその他の落とし穴2つ
systemctl mask --runtimeは、/etc/systemd/systemにあるユニットファイルには何も作用しません。 /etc内のユニットは/run内のランタイムマスクより優先されるため、コマンドは成功してもサービスは起動してしまいます。サービスを停止状態に保つには、ConditionPathExists=!/etc/<name>.holdを含むドロップインを使用します。このファイルが存在する限り、サービスは起動時にも手動起動でも開始されません。systemctl is-activeは、稼働中の oneshot サービスを inactive と判定します。Type=oneshotサービスの実行中は状態が "activating" となるため、is-activeはその旨を表示し、終了コード 3 を返します。夜間ジョブの完了を待つためにwhile systemctl is-active --quiet job.service; do sleep 60; doneのようなループを書いても、即座に抜けてしまいます。代わりに状態を確認してください。active、activating、reloading、deactivating はいずれも稼働中を意味します。
Factory Floorは、有効になっているのに起動していないサービスを検知します。デフォルトでは報告のみを行い、有効に設定した場合のみ起動します。バージョン 1.0.3 以降では、アラートに意図的にサービスを一時停止する方法も記載され、ランブックにも同じ内容が記述されています。