Ubuntu Weekly Recipe

第506回 HealthcheckでCronジョブの失敗を監視する

この記事を読むのに必要な時間:およそ 6.5 分

毎日のバックアップやログの集計などをはじめ,サーバーでは定期的に様々な処理が実行されていますよね。

当然ですが,管理者はこうした処理が失敗したことに気づけなければなりません。スクリプトの中でエラーをハンドリングしたり,あるいはスクリプトの戻り値を見てメールを送信したりSlackに発言したり……といった処理を仕込んでいるのではないでしょうか。

Cronでスクリプトの失敗時にメールを送信するありがちな例

0 0 * * * root /usr/local/bin/hogehoge.sh || echo "エラーメッセージ" | mail -s "エラーですよ" admin@example.com

しかしこのアプローチには問題があります。サーバーに意図しない問題が起きている状態では,エラーメールの送信にも失敗してしまう可能性があります。その場合管理者は,正常に終了したからアラートが来ないのか,アラートの送信にすら失敗しているのか判断がつかず,問題を見逃してしまうでしょう。その結果「毎日正常に動いていたと思っていたバックアップ処理が,実は半年前から失敗し続けていることをディスク故障後に知る」といった悲劇に見舞われることになります。

そこで逆に「ジョブの成功時に監視サーバーにPingを打ち,一定期間Pingがなかったジョブを失敗したと見なす」という考え方で作られた監視システムが,今回紹介するHealthchecksです※1)⁠

※1
つまるところ,一般的な死活監視システムと同じ考えを,プログラムの成否判定の監視に適用したものです。

実はHealthchecksはSaaSとして運営されておりここにサインアップするだけで監視機能を利用できます。ですがせっかくですので,今回はこれと同じ監視サーバーを自前で構築する手順から紹介します※2)⁠

※2
こういったマネージドなサービスは非常に便利なのですが,色々なしがらみからすべて自社内で用意せざるをえないことが多々あるのは,読者の皆様でしたらご理解いただけるのではないでしょうか。

依存パッケージのインストール

まずは必要なパッケージをインストールします※3)⁠

※3
本記事ではUbuntu 16.04 LTS上でPython3を使うことを前提とします。

HealthchecksはPython製のソフトウェアで,依存ライブラリのインストールにpipを利用するため,python3-pipパッケージが必要です。バックエンドのデータベースにはSQLite(デフォルト)のほかに,MySQL,PostgreSQLが選べます。筆者はMySQLを選択したので,データベース本体であるmysql-serverと,Python3のインターフェイスであるpython3-mysqldbをインストールします。また後述するアラートをメールで送信するため,postfixも必要です。

Healthchecksの依存パッケージのインストール

$ sudo apt install python3-pip python3-mysqldb mysql-server postfix

インストール中にPostfixの構成タイプとメールサーバー名を訊かれます。⁠Internet Site」を選択し,サーバーのFQDNを入力してください。

図1 Postfixの設定。Internet Siteを選択する

画像

同様に,MySQLのrootユーザーのパスワードを訊かれるので,パスワードを設定してください。

図2 MySQLのrootパスワードの設定

画像

Postfixの設定

今回Postfixはアラートの送信にしか使用せず,外部からのSMTP送信やメール受信でのPingは受け取らないため,⁠inet_interfaces」「localhost」を指定し,外部に対して25番ポートを晒さないようにします。また25番でのsasl_authを禁止しておきます。postconfで設定を行ったら,postfixを再起動します。

Postfixの設定と再起動

$ sudo postconf -e 'inet_interfaces = localhost'
$ sudo postconf -e 'smtpd_relay_restrictions = permit_mynetworks defer_unauth_destination'
$ sudo systemctl restart postfix.service

MySQLユーザーとデータベースの作成

MySQLに,Healthchecks用のMySQLユーザーとデータベースを作成します。ここではユーザー名,データベース名ともに「healthchecks」としていますが,お好みで変えても構いません。

MySQLのユーザーとデータベースの作成

$ mysql -uroot -p
Enter password:
mysql> GRANT ALL ON healthchecks.* TO healthchecks@'localhost' IDENTIFIED BY 'パスワード';
mysql> CREATE DATABASE healthchecks DEFAULT CHARACTER SET utf8;

Healthchecks用ユーザーの作成

Healthchecks用のユーザーを作成します。Healthchecksはこのユーザーのホームディレクトリ以下にインストールし※4)⁠後述するアラート通知用サービスも,このユーザーの権限で起動させます。以後の作業はhealthchecksユーザーで行うため,sudoを実行可能にしておきます※5)⁠

※4
「/opt以下にインストールしたい」というような方は,以後のパスを適宜読み替えてください。
※5
本記事ではわかりやすさを優先するため「専用ユーザーを作ってsudoを許可する」という形にしましたが,sudoが必要なコマンドだけを別のユーザーで実行したり,あるいはvirtualenv環境を使うなどすれば,このユーザーにsudo権限は不要です。また,そもそもHealthchecks用のユーザーを作らず,Ubuntuインストール時に作成したユーザーですべての作業を行ってしまうという手もあります。このあたりはお好みで調整してください。

healthcheckユーザーの作成と,sudo権限の付与

$ sudo useradd -m -s /bin/bash healthchecks
$ sudo passwd healthchecks
$ sudo gpasswd -a healthchecks sudo

ソースコードの取得と依存ライブラリのインストール

healthchecksユーザーにスイッチしたら,Healthchecksのソースコードをcloneします。

ソースコードのclone

$ sudo -i -u healthchecks
$ git clone https://github.com/healthchecks/healthchecks.git

「/home/healthcecks/healthchecks」ディレクトリが作成され,コードがcloneされました。この中にある「requirements.txt」には,依存しているPythonのライブラリが列挙されています。pip3コマンドの「-r」オプションにこのファイルを渡して,依存ライブラリをインストールしてください※6)⁠

※6
ここでもわかりやすさを優先するため,root権限で/usr/local以下にライブラリをインストールしています。これが気になる方は,virtualenv環境を使うのもよい考えでしょう。しかし最近では,この手のアプリは専用のコンテナに閉じ込めることが多いので,コンテナ内でシステムワイドにインストールしてしまうのが楽でいいのではないか,というのが筆者の考えです。実際に筆者は本記事の手順でインストールしたHealthchecksを,LXCコンテナ内で運用しています。

依存ライブラリのインストール

$ cd healthchecks/
$ sudo pip3 install -r requirements.txt

著者プロフィール

水野源(みずのはじめ)

Ubuntu Japanese Teamメンバー。理想のフリーデスクトップ環境を求めて東へ西へ……のはずが,気がついたら北の大地で就職していたインフラ寄りのエンジニア。最近レンズ沼にハマる。

コメント

コメントの記入