tl;dr
最近, Healthchecks.io という Web サービスを教えていただきました. SaaSだけではなく, 仕組み自体は OSS で提供されていて Docker でサクッと試すことが出来ます.
Healthchecks.io とは
シンプル
Django で書かれた Cron ジョブをモニタリングするツールです. どのようにモニタリングするかと言うと, サイトにも掲載されているように Cron ジョブが終了したら, Healthchecks.io から払い出される HTTP エンドポイントに対してリクエストを投げることで Cron ジョブが正常に終了することをモニタリングします.
以下は, サイトのトップページに掲載されている Cron 定義です.
# m h dom mon dow command 8 6 * * * /home/user/backup.sh && curl -fsS --retry 3 https://hc-ping.com/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx > /dev/null
backup.sh が正常に終了しなかった場合, curl -fsS --retry 3 https://hc-ping.com/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx > /dev/null
が実行されないことになります.
ドキュメントの中でこの URL は Ping URL と呼ばれています.
Healthchecks.io は Ping URL にリクエストを送信する度に, そのリクエストを記録し, 監視対象 (この例で言うと backup.sh) の Ping の値を更新します. 最後に受信した Ping から設定した時間 (期間) が経過すると, その監視対象は遅延しているとみなされ, Healthchecks.io は「猶予期間」を待ってから Ping がない場合にはアラートを送信します. 以下, 期間と猶予期間を設定する Web ユーザーインターフェースです.
上記の設定例だと, Ping は 30 分毎に送信され, 猶予期間は 30 分となり, 30 分 + 30 分 = 60 分間 Ping の送信が無い場合にはアラート送信されます. この設定は監視対象毎に設定が可能となりますので, 1 つの Cron ジョブ毎に設定が可能ということになります.
尚, 以下のように Ping URL に /fail
を追加することで, 監視対象の障害発生を通知することが出来ます. 以下はドキュメントより引用した Python コードです.
import requests URL = "https://hc-ping.com/your-uuid-here" def do_work(): # Do your number crunching, backup dumping, newsletter sending work here. # Return a truthy value on success. # Return a falsy value or throw an exception on failure. return True success = False try: success = do_work() finally: # On success, requests https://hc-ping.com/your-uuid-here # On failure, requests https://hc-ping.com/your-uuid-here/fail requests.get(URL if success else URL + "/fail")
Healthchecks.io の主な機能はこれだけ (良い意味で!) となり, 実にシンプルで理解しやすいツールになっていると思います.
インテグレーション
以下のような外部サービスと連携が可能なようです.
- Slack
- Webhook
- PagerTree
- HipChat
- VictorOps
- OpsGenie
おなじみの Slack をはじめ, いにしへのプロトコルになりつつある電子メールや Webhook 等, 通知系のサービスとの連携がデフォルトで行えるようになっています.
料金プラン
Healthchecks.io は無償枠以外に以下のような料金プランが用意されています.
無料枠でも 20 Checks で各 Check 毎に 100 ログエントリとあるので, 通常の利用範囲 (ちょっとした Web サービス) であれば無料枠でも十分なのでは思います.
その他
REST API も提供されていますので, 監視対象の追加や削除, 監視の一時停止等を API で操作することが出来ますし, 幾つかの言語で API をラップしたクライアントライブラリが有志の方々によってリリースされています.
尚, API を利用する為には, [Account Settings] → [Account] → [API Access] にて API キーを払い出す必要があります.
チュートリアル
Docker にて
以下の docker-compose.yml を利用して, ローカル環境に Healthchecks.io を起動します.
起動すると, Healthchecks.io 以外に MariaDB と MailHog というテスト用のシンプルな SMTP サーバーが起動します. 尚, 今回の検証環境は以下の通りとなっています.
$ docker version Client: Docker Engine - Community Version: 18.09.0 API version: 1.39 Go version: go1.10.4 Git commit: 4d60db4 Built: Wed Nov 7 00:47:43 2018 OS/Arch: darwin/amd64 Experimental: false Server: Docker Engine - Community Engine: Version: 18.09.0 API version: 1.39 (minimum version 1.12) Go version: go1.10.4 Git commit: 4d60db4 Built: Wed Nov 7 00:55:00 2018 OS/Arch: linux/amd64 Experimental: true $ docker-compose --version docker-compose version 1.23.2, build 1110ad01
起動
docker-compose up -d
を実行すると, 以下のようなコンテナが起動します.
$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 822062af97fc docker-healthchecks_hc "/entrypoint.sh /sta…" 27 hours ago Up 27 hours 0.0.0.0:9090->9090/tcp docker-healthchecks_hc_1 d5684cbb2484 mariadb "docker-entrypoint.s…" 27 hours ago Up 27 hours 3306/tcp docker-healthchecks_db_1 0a2910fbde7d mailhog/mailhog "MailHog" 27 hours ago Up 27 hours 1025/tcp, 0.0.0.0:8025->8025/tcp docker-healthchecks_mailhog_1
コンテナが起動したら, 以下を実行して管理者権限を持つユーザーを作成します.
$ docker-compose exec hc ./manage.py createsuperuser Username: admin Email address: admin@example.com Password: Password (again): Superuser created successfully.
作成したユーザー (実際には Email address) を使って, Docker で起動している Healthchecks.io にブラウザで http://localhost:9090 にアクセスしてログインします.
チェック (監視対象) の追加
以下のように実行して API を利用して監視対象の追加を行います.
$ export API_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx $ curl http://localhost:9090/api/v1/checks/ \ --header "X-Api-Key: ${API_KEY}" \ --data '{"name": "my-first-check", "tags": "my-test", "timeout": 3600, "grace": 60}'
各パラメータは以下のような内容になっています.
name
: 監視対象の名前tags
: 監視対象をグループ化する際に便利なタグを付与することが出来ますtimeout
:Period
(期間)grace
: 猶予期間
以下のように出力されます.
{ "ping_url": "http://localhost:9090/ping/4111b763-2319-4bdd-8c0c-70ce621c2b4b", "timeout": 3600, "tags": "my-test", "update_url": "http://localhost:9090/api/v1/checks/4111b763-2319-4bdd-8c0c-70ce621c2b4b", "pause_url": "http://localhost:9090/api/v1/checks/4111b763-2319-4bdd-8c0c-70ce621c2b4b/pause", "last_ping": null, "channels": "", "next_ping": null, "name": "my-first-check", "grace": 60, "n_pings": 0, "status": "new" }
ping_url
が払い出されていることが判ります.
監視
以下のように ping_url
に対して curl でアクセスしてみます.
curl http://localhost:9090/ping/4111b763-2319-4bdd-8c0c-70ce621c2b4b -w "\n"
以下のように出力されます.
$ curl http://localhost:9090/ping/4111b763-2319-4bdd-8c0c-70ce621c2b4b -w "\n" OK
監視対象の状態を確認してみます.
curl -s http://localhost:9090/api/v1/checks/?tag=my-test --header "X-Api-Key: ${API_KEY}" | jq .
以下のように出力されます.
$ curl -s http://localhost:9090/api/v1/checks/?tag=my-test --header "X-Api-Key: ${API_KEY}" | jq . { "checks": [ { "ping_url": "http://localhost:9090/ping/4111b763-2319-4bdd-8c0c-70ce621c2b4b", "timeout": 3600, "tags": "my-test", "update_url": "http://localhost:9090/api/v1/checks/4111b763-2319-4bdd-8c0c-70ce621c2b4b", "pause_url": "http://localhost:9090/api/v1/checks/4111b763-2319-4bdd-8c0c-70ce621c2b4b/pause", "last_ping": "2018-12-19T23:10:46+00:00", "channels": "", "next_ping": "2018-12-20T00:10:46+00:00", "name": "my-first-check", "grace": 60, "n_pings": 2, "status": "up" } ] }
ブラウザでは以下のように出力されます. Log の部分に Ping URL へのアクセスが記録されていることが判ります.
監視の一時停止
メンテナンス等で, Cron バッチ等を一時的に停止する必要がある場合, 以下のように Ping URL のパスに pause
を付与してリクエストを送信することで, 監視を一時停止することが出来ます.
curl -XPOST http://localhost:9090/api/v1/checks/4111b763-2319-4bdd-8c0c-70ce621c2b4b/pause --header "X-Api-Key: ${API_KEY}"
以下のように出力されます.
{ "timeout": 3600, "pause_url": "http://localhost:9090/api/v1/checks/4111b763-2319-4bdd-8c0c-70ce621c2b4b/pause", "last_ping": "2018-12-19T23:48:49+00:00", "name": "my-first-check", "grace": 60, "ping_url": "http://localhost:9090/ping/4111b763-2319-4bdd-8c0c-70ce621c2b4b", "n_pings": 2, "status": "paused", "tags": "my-test", "channels": "", "next_ping": "2018-12-20T00:48:49+00:00", "update_url": "http://localhost:9090/api/v1/checks/4111b763-2319-4bdd-8c0c-70ce621c2b4b" }
監視の再開は, Ping URL にアクセスすることで再開されます.
期間や猶予期間の変更
監視対象を登録した際に設定した期間や猶予期間は以下のように変更します. 期間を 3600 秒から 60 秒に変更してみます.
curl http://localhost:9090/api/v1/checks/4111b763-2319-4bdd-8c0c-70ce621c2b4b \ --header "X-Api-Key: ${API_KEY}" \ --data '{"name": "my-first-check", "tags": "my-test", "timeout": 60, "grace": 60}'
以下のように出力されます.
{ "timeout": 60, "pause_url": "http://localhost:9090/api/v1/checks/4111b763-2319-4bdd-8c0c-70ce621c2b4b/pause", "last_ping": "2018-12-19T23:50:16+00:00", "name": "my-first-check", "grace": 60, "ping_url": "http://localhost:9090/ping/4111b763-2319-4bdd-8c0c-70ce621c2b4b", "n_pings": 3, "status": "down", "tags": "my-test", "channels": "", "next_ping": "2018-12-19T23:51:16+00:00", "update_url": "http://localhost:9090/api/v1/checks/4111b763-2319-4bdd-8c0c-70ce621c2b4b" }
監視対象との疎通が取れなくなった場合
Cron ジョブ等が正常に実行されなかった場合等, 設定した期間と猶予期間の時間を超えるとステータスが Down
に変わります. 期間だけを超える場合には Late
というステータスになります. 以下は, API を利用して監視対象の状態を取得している実行例です.
$ curl -s http://localhost:9090/api/v1/checks/?tag=my-test --header "X-Api-Key: ${API_KEY}" | jq . { "checks": [ { "timeout": 60, "pause_url": "http://localhost:9090/api/v1/checks/4111b763-2319-4bdd-8c0c-70ce621c2b4b/pause", "last_ping": "2018-12-19T23:50:16+00:00", "name": "my-first-check", "grace": 60, "ping_url": "http://localhost:9090/ping/4111b763-2319-4bdd-8c0c-70ce621c2b4b", "n_pings": 3, "status": "down", "tags": "my-test", "channels": "", "next_ping": "2018-12-19T23:51:16+00:00", "update_url": "http://localhost:9090/api/v1/checks/4111b763-2319-4bdd-8c0c-70ce621c2b4b" } ] }
status
が down
になっていることが判ります. ブラウザで確認すると以下のように Current Status
が down となっていることが判ります.
以上
Cron ジョブの稼働監視を一覧化するにあたって, 以前に Jenkins を使うことを検討したことが有りました.
Jenkins の「外部ジョブの監視」を利用することで, Cron の実行結果の一覧を Jenkins で確認することは出来ることを確認しましたが, Healthchecks.io のように期間や猶予期間を指定するということは出来なかったと記憶しています (現在は可能かもしれませんが). 期間や猶予期間を指定出来ることで, Cron ジョブの監視以外にも定期的に実行される (それが Cron で実行されているのであれば, Cron ジョブ監視になってしまいますが...) バックエンドのサービス等の死活監視にも利用可能なのではと考えています.
今回は Docker を使って, 超簡単に Healthchecks.io をチュートリアルしてみました. 本当にシンプルで特に難しいこともなく基本的な機能を触ることが出来ました. Slack への通知等も簡単に行えるようなので, 時間を見つけて試してみたいと思います. また, サードパーティ製のライブラリをアプリケーションに組み込みんでみて, 実運用のアプリケーションでどのように使えるかも検証してみたいと考えています.