毎日のバックアップやログの集計などをはじめ、サーバーでは定期的に様々な処理が実行されていますよね。
当然ですが、管理者はこうした処理が失敗したことに気づけなければなりません。スクリプトの中でエラーをハンドリングしたり、あるいはスクリプトの戻り値を見てメールを送信したりSlackに発言したり……といった処理を仕込んでいるのではないでしょうか。
しかしこのアプローチには問題があります。サーバーに意図しない問題が起きている状態では、エラーメールの送信にも失敗してしまう可能性があります。その場合管理者は、正常に終了したからアラートが来ないのか、アラートの送信にすら失敗しているのか判断がつかず、問題を見逃してしまうでしょう。その結果「毎日正常に動いていたと思っていたバックアップ処理が、実は半年前から失敗し続けていることをディスク故障後に知る」といった悲劇に見舞われることになります。
そこで逆に「ジョブの成功時に監視サーバーにPingを打ち、一定期間Pingがなかったジョブを失敗したと見なす」という考え方で作られた監視システムが、今回紹介するHealthchecksです[1]。
実はHealthchecksはSaaSとして運営されており、ここにサインアップするだけで監視機能を利用できます。ですがせっかくですので、今回はこれと同じ監視サーバーを自前で構築する手順から紹介します[2]。
依存パッケージのインストール
まずは必要なパッケージをインストールします[3]。
HealthchecksはPython製のソフトウェアで、依存ライブラリのインストールにpipを利用するため、python3-pipパッケージが必要です。バックエンドのデータベースにはSQLite(デフォルト)のほかに、MySQL、PostgreSQLが選べます。筆者はMySQLを選択したので、データベース本体であるmysql-serverと、Python3のインターフェイスであるpython3-mysqldbをインストールします。また後述するアラートをメールで送信するため、postfixも必要です。
インストール中にPostfixの構成タイプとメールサーバー名を訊かれます。「Internet Site」を選択し、サーバーのFQDNを入力してください。
同様に、MySQLのrootユーザーのパスワードを訊かれるので、パスワードを設定してください。
Postfixの設定
今回Postfixはアラートの送信にしか使用せず、外部からのSMTP送信やメール受信でのPingは受け取らないため、「inet_interfaces」に「localhost」を指定し、外部に対して25番ポートを晒さないようにします。また25番でのsasl_authを禁止しておきます。postconfで設定を行ったら、postfixを再起動します。
MySQLユーザーとデータベースの作成
MySQLに、Healthchecks用のMySQLユーザーとデータベースを作成します。ここではユーザー名、データベース名ともに「healthchecks」としていますが、お好みで変えても構いません。
Healthchecks用ユーザーの作成
Healthchecks用のユーザーを作成します。Healthchecksはこのユーザーのホームディレクトリ以下にインストールし[4]、後述するアラート通知用サービスも、このユーザーの権限で起動させます。以後の作業はhealthchecksユーザーで行うため、sudoを実行可能にしておきます[5]。
ソースコードの取得と依存ライブラリのインストール
healthchecksユーザーにスイッチしたら、Healthchecksのソースコードをcloneします。
「/home/healthcecks/healthchecks」ディレクトリが作成され、コードがcloneされました。この中にある「requirements.txt」には、依存しているPythonのライブラリが列挙されています。pip3コマンドの「-r」オプションにこのファイルを渡して、依存ライブラリをインストールしてください[6]。
Healthchecksの設定
Healthchecksの設定ファイルは、hcディレクトリ内の「settings.py」と「local_settings.py」です。settings.pyにはデフォルトの設定が書かれています。local_settings.pyに設定を記述すると、settings.pyの設定を上書きできます。ですのでsettings.pyを直接編集することはせず、サイト固有の設定はlocal_settings.pyで行いましょう。
local_settings.pyは初期状態では存在しないため、サンプルの「local_settings.py.example」をコピーして雛形を作ります。
テキストエディタでlocal_settings.pyを開いてください。冒頭に以下の3行がコメントアウトされています。コメントを解除して、適切な値を設定してください。
SITE_ROOTはHealthchecksのFQDNです。メール通知などの中に埋め込まれるので、ブラウザーでアクセスできる正しいURLを記述してください。 SITE_NAMEはその名の通り、テンプレート全体で利用されるサイトの名前です。特に変更しなくても動作に支障はありませんが、自社のプロジェクト名などにしておくとわかりやすいでしょう。 DEFAULT_FROM_EMAILは、Healthchecksが送信するメールのFromです。スパムと判定されないためにも、自分のドメイン名にしておきましょう。
その下に、以下の行を追記してください。
HOSTに設定した値は、メールでPingを送る際の(受信アドレスの)ドメイン名になります。この機能は本記事では紹介しないのですが、Web UI上での表記がデフォルトのlocalhostのままなのもかっこ悪いので、このサーバーのFQDNを設定しておきます。
PING_ENDPOINTはPingを送る際のURLになります。先ほど設定したSITE_ROOTの値を元にしています。
ALLOWED_HOSTSは、サービスにアクセスを許可するホストです。デフォルトではlocalhostのみになっているため、アクセスを許可したいIPアドレスを列挙してください。ここにはWeb UIにアクセスするホストと、Pingを送信するサーバーのすべてが含まれている必要があります。上記の例ではすべてのホストを許可しています。
REGISTRATION_OPENは、Web UIからのサインアップを許可するかどうかです。クローズドな環境下で、限られたメンバーだけで運用するのであれば、不特定多数のサインアップを許可する必要はないため、Falseに設定しておくとよいでしょう。もちろん、誰でも自由に使ってよいというポリシーであれば、この行は省略して構いません。
その下にはデータベースの設定を記述します。最初からコメントアウトされた状態で各設定の例が記述されていますので、下記のようにMySQLのセクションのコメントを解除し、NAME、USER、PASSWORDに先ほどデータベースを作成した時の値を指定してください。
データベースの設定のさらに下に、メール送信の設定がコメントアウトされた状態で記述されています。今回はローカルにあるPostfixからメールを送信するため、設定を書き換える必要はありません。外部のSMTPサーバーを利用する場合は、適宜設定を書き換えてください。
マイグレーションとスーパーユーザーの作成
アプリケーションの設定が完了したら、マイグレーションとスーパーユーザーの作成を行います。Healthchecksをcloneしたディレクトリにある「manage.py migrate」と「manage.py createsuperuser」を実行してください。
この際、インタプリタとしてpython3を明示的に指定して実行しています。というのも、manage.pyのshebangには「#!/usr/bin/env python」が指定されているのですが、最近のUbuntuサーバーではPython2がインストールされていないため、以下のようにスクリプトを実行するとエラーになってしまうためです。
テストサーバーの起動と動作確認
ここまでの作業が完了したら、Healthchecksを動かせます。以下のコマンドを実行し、manage.pyでテスト用Webサーバーを起動してください[7]。
Webブラウザーからサーバーの8080番ポートに接続してください。Healthchecksのトップページが表示されていれば成功です。
Ctrl+Cでテストサーバーを終了できます。
WSGIで動作させる
runserverはあくまでテスト用のサーバーですので、本番での利用は推奨されません。そこでアプリケーションが動作することが確認できたら、Apacheでアプリケーションをホストするようにしましょう。ApacheとWSGIモジュールをインストールします。
「/etc/apache2/sites-enabled/000-default.conf」を、以下の内容に置き換えます。もしもインストールしているパスが異なる場合は、適宜変更してください。
Apacheを再起動します。
今度はWebブラウザーから、サーバーの80番ポートに接続してください。先ほどと同じトップページが表示されていれば成功です。
Healthchecksの使い方
それでは実際にHealthchecksを使ってみましょう。
先ほどcreatesuperuserで作成したユーザーでログインします。まずページ右上の「Log In」をクリックしてください。スーパーユーザー作成時に登録したメールアドレスを入力して「Log In」ボタンをクリックすると、そのアドレスにログイン用のURLが送信されます。リンクをクリックしてログインしてください。
なお「I want to use a password」にチェックを入れると、パスワード入力欄が表示されます。メール経由でなく、パスワードでログインしたい場合はこちらを使います。
「Add Check」ボタンをクリックすると、Pingを送信するユニークなURLが生成されます。これが「チェック」です。
「Name」の部分をクリックすると、チェックに名前とタグをつけられます。わかりやすい名前をつけておきましょう。タグはWeb UI上でチェックのフィルタリングに使います。スペースで区切ることで複数のタグをつけられるので、「web」「mail」「backup」等々、整理しやすいタグをつけておくと便利かもしれません。
生成されたばかりでPingを受信していないチェックは、ステータスが「New」となっています。ためしにこのチェックに対してPingを送信してみましょう。チェックの右端にある歯車のアイコンから「Usage Examples」をクリックすると、各種ツールや言語でPingを送信する例が表示されます。ここの「Bash」のタブにはcurlコマンドやwgetコマンドを使った例がありますので、これをコピペするのが楽でしょう。正常にPingが送信できると、チェックのステータスが「Up」になり、アイコンが緑色に変化します。
「Period」「Grace」は、ステータスが変化してアラートが発生するまでの時間です。「Period」にはPingが送信されるインターバルを指定します。1日1回、決まった時間に実行されるジョブが対象であれば「1 day」に設定します。前回のPing送信からPeriodに設定した時間が経過すると、チェックのステータスが「Up」から「Late」になり、アイコンが黄色くなります。
「Grace」には、ステータスが「Late」になってから実際にアラートが送信されるまでの猶予時間を設定します。たとえば日によって処理にかかる時間が異なるジョブの場合、単純に「24時間以上経過したらアラート」という設定だと、処理は正常に行われているのにアラートが鳴る日と鳴らない日が出てきてしまうからです。Periodを「1 day」、Graceを「3 hours」に設定した場合、前回Pingを受け取ってから27時間経過した時点でステータスが「Late」から「Down」になり、このタイミングでアラートが送信されます。
インテグレーションの設定
アラートが送信される条件は前述の通りなのですが、チェックを設定しただけでは実際にアラートは飛びません。まずアラートの送信先を登録し、チェックと関連づける必要があります。このアラートの送信先をインテグレーションと呼び、インテグレーションにはメールのほか、SlackやWebhook、HipChatなどが用意されています。ここではよく使うであろう、メールのインテグレーションの設定を例に紹介します。
「INTEGRATIONS」ページにある、Emailの「Add Integration」ボタンをクリックします。
アラートを送信するメールアドレスを入力して「Save Integration」ボタンをクリックします。
インテグレーションが追加されますが、この状態ではまだ(unconfirmed)になっています。不正なメール送信を防止するため、メールインテグレーションでは受信者の同意が必要なためです。
設定したメールアドレス宛てに確認のメールが送信されていますので、その中に記載されているURLを開いてください。「Email Address Verified」のページが表示されれば確認は完了です。以後、このアドレス宛てにアラートの送信ができます。
各インテグレーションの「Assigned Checks」をクリックすると、そのインテグレーションをどのチェックと関連づけるかを選択できます。チェックごとに送信先を変えたい場合に便利です。
さて、実はこれだけではまだアラートは送信されません。アラートの送信は別プロセスによって行われるため、このプロセスをバックグラウンド起動しておかないと、インテグレーションを設定してもアラートは送信されないのです。インテグレーションを設定したら以下のコマンドを実行して、アラートが送信されることを確認してください。テストのためにはチェックのPeriodとGraceを極端に短くした上で、curlでPingを送ってみるとよいでしょう。
sendalertsをsystemdのサービスとして動作させる
sendalertsを毎回手で起動するのは面倒ですので、正常にアラートが飛ぶことが確認できたら、systemdのサービスとして起動させましょう。 「/etc/systemd/system/sendalerts.service」というファイルを、下記の内容で作成してください(例によってインストールしたパスが違う場合は適宜読み替えてください)。
サービスを起動します。
いかがでしょうか。Cronモニタリングシステムと名乗っているHealthchecksですが、一定時間内に応答があったかどうかを見張るという仕組みは、他にも色々と応用できそうです。インストールも簡単ですので、お手軽なプロセス監視システムがほしい方は導入を検討してみてもいいかもしれませんね。