はんドンクラブ 運営ブログ

Mastodonインスタンス「handon.club」の運営ブログです。コラムなど,Mastodonに関する一般的な記事も投稿予定です。

【Prometheus+Grafana】Mastodonサーバの外形監視(HTTPレスポンスタイム等)

こんばんは。

Mastodonインスタンスの1つである「handon.club」では,昨日より外形監視を始めました。構成は,Prometheus+Grafanaのオンプレ構成です。

今日は,今回構築した「handon.club」における外形監視の例を使って,Mastodonサーバの外形監視方法についてご紹介したいと思います。なお,日本語で設定方法を解説している記事が見つからなかったため,具体的な設定の方法についても触れたいと思います。

外形監視

本投稿でいう外形監視とは,「HTTPレスポンス」に関する統計情報(メトリクス)を指します。一般に外形監視とは,サーバのCPU利用率やディスクI/Oといった内部の情報ではなく,サーバの外部から見える範囲での情報を使った監視のことです。よくあるping監視もそのうちの1つと考えますが,今回はHTTPレスポンスに限った話をします。

Mastodonインスタンスのhandon.clubにおける外形監視についてですが,特に2つのフロントエンドサーバについて,以下の観点の監視が必要だと考えています。

そこで,以下に示すような監視システムを構築することで,要件を満たす外形監視を実現しました。

全体の構成

本章では,今回構築した監視システムの全体概要を説明します。

f:id:highemerly:20190128233137p:plain
Prometheus+Grafanaによる監視システム構成

まずはじめに,監視方式として,makarelやdatadogといったクラウドサービスを使うか,それとも自分で監視サーバを構築するかという2択を選択しなくてはなりません。しかし,前者のクラウドサービスを使う場合,当然ながら無料で使える範囲には限りがあります。残念ながら私の要件を満たすためには,有料プランの契約が必要となるようでした。どうせお金を払うならば,ということで,今回は自分で構築する道を選びました。

今回,監視サーバの基幹には,Prometheusというサーバ監視ツールを使いましたGoogleにおけるサーバ監視のノウハウが生かされているとの噂で,最近人気上昇中のOSS監視ツールです。pull型(監視対象に定期的にメトリクスを取得にいく方式)が採用されている点が最大の特徴です。

このPrometheusは,監視サーバそのものに加え,監視対象サーバ側で動作させる「exporter」と呼ばれるプログラムから構成されています。pull型の監視ソリューションであるPrometheusは,監視サーバそのものがこのexporterに対してメトリクスを要求することで,必要な情報を集めるしくみになっています。exporterは非常に多くの種類が用意されており,監視したい項目に応じて自由に選ぶことできます。今回はそのexporterの中でも,外形監視を実現するために用意されている「blackbox-exporter」を使って,外形監視を行いました。

一方Grafanaは,様々な情報をグラフィカルに表示する可視化ツールです。有名なので詳細は割愛します。

事前準備

以下の作業は行われているものとします。

  • Mastodonサーバを構築済みであること
  • Prometheus,Grafanaを構築済みで,それらの連携設定が完了していること

実際にMastodonサーバで外形監視を行おうとしている方で,もし上記の作業を実施していない方がいらっしゃいましたら,他の方の書かれた記事を参照してみてください。ググるとたくさん出てきます。

また,今回のサーバ環境は以下の通りです。

  • Host OS: CentOS 7
  • Prometheus: 2.6.1
  • Grafama: 5.4.3

blackbox-exporterの導入

blackbox-exporterは,ICMPおよびHTTPによる外形監視を実現することのできるPrometheus用exporterです。通常のexporterは監視対象サーバで動作させますが,外形監視の性質から考えて,このexporterは監視サーバ本体で動作させるのが一般的です。動作のイメージを以下に示します。この図では,先ほどの図に比べて,exporter名を正確に記載しています。

f:id:highemerly:20190201003535p:plain
システム概略図(exporter名入り)

では,導入手順を説明します。まずはじめに,以下のようにexporterを適当な場所に配置する必要があります。exporterはバイナリが配布されていますので,導入はとっても簡単ですね。

$ cd /usr/local/src/exporter/
$ sudo wget https://github.com/prometheus/blackbox_exporter/releases/download/v0.13.0/blackbox_exporter-0.13.0.linux-amd64.tar.gz
$ sudo tar -zxvf blackbox_exporter-0.13.0.linux-amd64.tar.gz
$ sudo ln -s blackbox_exporter-0.13.0.linux-amd64.tar.gz/ blackbox_exporter

ただし,バージョン,ディストリビューション,プラットフォームは環境等に合わせて設定してください。

Releases · prometheus/blackbox_exporter · GitHub

さて,一度起動してみましょう。

$ cd /usr/local/src/exporter/blackbox_exporter
$ ./blackbox_exporter

level=info ts=2019-01-28T15:03:15.017239345Z caller=main.go:215 msg="Starting blackbox_exporter" version="(version=0.13.0, branch=HEAD, revision=1cfb7512daa7e100abb32037996c8f805990d813)"
level=info ts=2019-01-28T15:03:15.019513325Z caller=main.go:228 msg="Loaded config file"
level=info ts=2019-01-28T15:03:15.019660332Z caller=main.go:332 msg="Listening on address" address=:9115

正常に起動しているっぽいですね。また,9115ポートで待ち受けていることも分かります。

さて,コマンドで起動することが確認出来たら,Linuxにサービスとして登録し,常時動かせるようにしましょう。

$ sudoedit /usr/lib/systemd/system/prometheus-blackbox-exporter.service 

[Unit]
Description=Prometheus's client - blackbox exporter
Documentation=https://github.com/prometheus/blackbox_exporter

[Service]
Type=simple
ExecStart=/usr/local/src/exporter/blackbox_exporter/blackbox_exporter --config.file=/usr/local/src/exporter/blackbox_exporter/blackbox.yml

[Install]
WantedBy=multi-user.target

$ sudo systemctl daemon-reload
$ sudo systemctl enable prometheus-blackbox-exporter
$ sudo systemctl start prometheus-blackbox-exporter
$ sudo systemctl status prometheus-blackbox-exporter -l

● prometheus-blackbox-exporter.service - Prometheus's client - blackbox exporter
   Loaded: loaded (/usr/lib/systemd/system/prometheus-blackbox-exporter.service; disabled; vendor preset: disabled)
   Active: active (running) since 火 2019-01-29 00:03:23 JST; 1min 15s ago
     Docs: https://github.com/prometheus/blackbox_exporter
 Main PID: 31928 (blackbox_export)
   CGroup: /system.slice/prometheus-blackbox-exporter.service
           └─31928 /usr/local/src/exporter/blackbox_exporter/blackbox_exporter --config.file=/usr/local/src/exporter/blackbox_exporter/blackbox.yml

ここで注意点です。.service ファイル中に呪文のように Restart=always と書く方がいらっしゃいます(自分もそうでした)。しかし,このblackbox-exporterについては, Restart=always を設定するとうまく動きません。詳細な原因までは追っていませんが,再起動すると「前回の終了から次の起動までの時間が短すぎる」という旨のエラーメッセージが表示されてうまく起動しないようです。

ちなみに,実行時にblackbox.ymlという設定ファイルを指定してますが,この設定ファイルは私はデフォルトのままいじっていません。

これでblackbox-exporter側の設定は完了です。

Prometheus側の設定変更

実際に外形監視を行うURLなどはPrometheus側の設定にて行います。設定は, blackbox-exporterのドキュメントを参考にしました。具体的には,prometheus.ymlに以下の記述を追加しました。

$ sudoedit /path/to/prometheus.yml

scrape_configs:
  # The job name is added as a label `job=<job_name>` to any timeseries scraped from this config.
  - job_name: 'blackbox'
    scrape_timeout: 10s
    metrics_path: /probe
    params:
      module: [http_2xx]
    static_configs:
      - targets:
        - https://handon.club/                                          # Web Server
        - https://handon.club/api/v1/timelines/public    # REST API Server
        - https://media.handon.club/xxxxxxx                 # Media Server
        labels:
          group: 'response'
    relabel_configs:
      - source_labels: [__address__]
        target_label: __param_target
      - source_labels: [__param_target]
        target_label: instance
      - target_label: __address__
        replacement: 127.0.0.1:9115

targets 配下に監視対象のURLを記載しているところがポイントです。私は以下の3つを監視対象としました。

  1. <Mastodon-host>
  2. <Mastodon-host>/api/v1/timelines/public
  3. <Mastodon-media-host>/<適当な画像のpath>

この監視対象URLをなぜこのように設定したかについて解説したいとおもいます。まず,1つめの2つめの違いについてです。

1つめはWebページそのものを,2つめはAPIをコールしてTLを取得しています。1つめのMastodonのトップページでは,FederationまたはLocalのTLが表示されているため,1つめと2つめの違いは一見,APIを間接的にコールするか直接コールするかの違いしかないように思えます。しかしながら,1つめのトップページについては,HTTPレスポンス上TL表示がすべて完了する前に「200 OK」を返してしまうのです。つまり,HTTPレスポンスを監視するblackbox-exporterでは,1つめのURLだけを監視すると,TL表示に関するレスポンスは監視出来ていないことなります。例えばTLを格納しているpostgresが落ちている場合も正常と判断してしまうのです。これは問題です。そこで今回は,認証も不要でかつTLを取得出来る,public TLのHTTPレスポンスを監視することにしました。

次に3つめについて,なぜルートではなく,適当な画像のpathを指定しているのか説明します。

handon.clubでは,画像サーバのみ別のサブドメイン(media.handon.club)を使っています。しかし,素直にmedia.handon.clubのルートにアクセスすると,「401 Forbidden」が返ってくる仕様となっており,これでは正常に動作しているかどうか分かりません。そこで,適当な画像のURLを監視対象とすることで,HTTPレスポンスが正常である(=サーバがダウンしていない)ことを監視することにしました。

Grafana側の設定

ここまできたら,あとはGrafanaでかっこいい見た目を設定するだけです。

HTTPレスポンス時間

まずはレスポンス時間(レスポンスタイム)を測定します。メトリクスに以下を入力します。

sum(probe_http_duration_seconds) by (instance)

"sum" について補足します。probe_http_duration_secconds には,実際には以下に示すようないくつかの要素があります(このスクリーンショットは,GrafanaではなくPrometheusの画面です)。

f:id:highemerly:20190129002344p:plain

HTTPレスポンス時間といえば大半はProcessingなのですが,Resolveなどの時間もきちんと記録することが可能で,それぞれ個別に計測されています。すごいですね・・・。しかし,ユーザの体感時間をメトリクスとして記録しておきたかったため,今回の監視対象はProcessingだけではなくResolveも含めた合計値とすることにしました。そのため,"sum"が付いています。

実際の表示例はこんな感じです。

f:id:highemerly:20190129002828p:plain

HTTPステータス

HTTPサーバが落ちていないか(200を返しているか)を監視します。たとえば,成功しているサーバの数を表示するには,メトリクスに以下を入力します。

count(probe_success)

これだけだと芸が無いですね。そこで,今回は3つのサーバを監視していることから,以下の様に設定を変え,Availabilityとして%表示するようにしてみました。

(count(probe_success) / 3.0) * 100

その結果,他の監視項目と併せて,以下の様な良い感じのダッシュボードが出来ました。

f:id:highemerly:20190129003312p:plain
Grafanaダッシュボードの例

完全に余談ですが,Mastodon自体はStatsDに対応しているので,MastodoサーバにStatsDのexporterを入れることで監視できる項目が大幅に増えます。例えば,sidekiqのキュー状態についてもPrometheusで取得できるようになりました。これが結構良くて,以下3つを横並びで監視することができるようになりました。

  • node_exporterによるホストのCPU/MEM状態
  • blackbox-exporterによるHTTPレスポンスタイム
  • statsd_exporterによるsidekiqのキュー状態

分かっていないこと

以下は,監視したいのですが,やり方が分かっておらず監視できていないメトリクスです。引き続き調査したいと思いますが,もし経験のある方がいらっしゃれば是非教えてください・・・。

  • Streamingサーバのレスポンス監視
    • StreamingサーバはTCPコネクションが貼りっぱなしとなるので,レスポンスタイムという概念がない? 何をどうやって監視すべきなのか一度考えたい。
  • Conohaのオブジェクトストレージの残量
    • もはや外形監視関係ない。
    • たぶんexporterを自作してconohaのREST APIを叩けばよい。ただし認証周りの実装がよく分からない。。

おわりに

今日は,PrometheusとGrafanaを使って,MastodonサーバのHTTPレスポンス外形監視を実現する方法をご紹介しました。すでに活用していた他のexporterについても,また時間のあるときに解説記事が書ければいいなと思います。

さて,handon.clubについての話です。このダッシュボードは現在,管理者である私しか見ることができません。しかし今回構築したGrafanaでは,REST APIによるデータ公開が可能ですので,将来はユーザ全員にステータス監視ページを公開できるよう準備をはじめています。イメージはTwitterみたいな感じですかね。レスポンスタイムも公開出来ればいいかなと思っています。

api.twitterstat.us