まっそのせかい

やった事のメモとか

Prometheusによるサーバ監視について少し紹介する

この記事はCCS Advent Calendar 2020の7日目の記事です。
昨日の記事: おすすめ家電(?) 2020 - 稲枝の押入れ

お疲れ様です。
社畜の階段を登り続けているCCSOBのまっそうめんです。
労働に追われているせいで大したネタが無く低みの見物をしていたのですが、入れろと煽られたカレンダーが空いていたので参戦しようと思います。
ネタについてはかろうじて書けそうなサーバの監視をテーマにし、Prometheusというツールについて少し紹介しようと思います。
ゲーム制作とかだとこういう話はあまり無いと思うので「そういう概念とかツールがあるんだなぁ~」みたいな気持ちで見ていただければ幸いです。
一応補足ですが、基本的にウェブ関係の監視についての話です。
それしか知らないので…すいません…(無知)
また、紹介メインで設定ファイルなどの項目など細かい説明はあまりしない予定です。
実際に試す場合は公式のチュートリアルや他の記事を参照してみて下さい。

なぜ監視が必要か社畜の刃 無限出社編

上司「弊社の(人)柱になれ、まっそうめん!」
ワイ「ウィッス!(カチャカチャカチャ、ッターン!!!)」
※ フィクションです

唐突ですがみなさん、プログラムを書いてバグらせた経験はありますでしょうか?
ゲーム制作とかでありがちな奴だと配列外参照して強制終了したりとか、ああいう感じの奴です。
趣味の範囲であれば特に大した問題はないと思いますが、バグったり落ちたりすると困るプログラムや処理になると話が変わってきます。
お察しかもしれませんが、主に労働関係ですね
日々利用されるアプリケーションやAPIのサーバ、内部のバッチ処理など、この現代社会において止まると困るものは多岐に渡ります。
例えばTwitterが落ちたらTwitter民が発狂して暴動が起きますよね、そういう事です。
開発・運用する側の人間として、そもそもバグらないように作り込むというのは当然あるのですが、エンジニアも決して完璧ではないのでAPIに処理を追加した時にバグらせてしまったり、突然サーバ自体が落ちるなど不慮の事故に見舞われる事もあります。
正常に処理が行われてない場合、内容だったり程度によりますが下記のような問題が発生してしまいます。

  • 利用者の不満が溜まる
  • 金銭的な損失
  • 信用の低下
  • サービス終了
  • 上司に詰められる
  • クビを切られる
  • 鬱病

そこで被害を抑えるため、サーバの生存や処理が正常に動作している事を見張り、問題があった場合すぐに対応するという事がエンジニアに求められます。
しかし、基本的にエンジニアは金儲け良いサービス提供のため、新規機能の追加や既出のバグ修正に追われていて、とてもじゃないですがそんな見張り役なんて普段やってられません。
なんなら新規機能の追加すら締切に間に合わないが(?)
なので、いわゆる監視ツールを導入する事でサーバやプログラムの処理状態を計測し、問題があると判断された場合に通知が来るように設定します。 こうする事で普段から見張らずとも異常時に気付き対応する事ができます。
開発に加え見張りまで人力でやろうとなると、人柱まっしぐらな気がします。

監視処理導入の必要性について述べたので、以下では監視ツールの1つであるPrometheusについて紹介しようと思います。

Prometheus紹介全集中 監視の呼吸

ワイ「あ^~心がぴょんぴょんするんじゃ^~(朝5時のアラート通知で起床)」
※ ノンフィクションです

Prometheusというのは、監視ツールの一種です。
実際には各種ExporterやAlertManagerというソフトウェアと組み合わせる事でサーバのリソース(メモリやディスクなど)などの監視や異常時の通知を実現します。
全体像の図は公式サイトで見る事ができます。
(初見だと何が何やら…って感じになりません…?)

Exporter壱ノ型 メトリクス出力

監視対象のサーバからメトリクスを集め、/metricsなどのエンドポイントとして出力します。
いろいろなExporterがあり、ものによって収集するメトリクスが変わってきます。
例えばnode_exporterの場合、監視対象のサーバに配置し実行するとリソース(メモリやディスク使用量など)を出力させる事ができます。

どんな感じに出力されるかをお見せするため、手元のラズパイにダウンロードして試してみましょう。
去年のアドカレ記事で露出狂という名前にされた彼です。)
公式のdownloadページから対応するバイナリをダウンロードし、解凍後実行します。

$ ./node_exporter
(実行時のログいろいろ)

9100ポートの/metricsにアクセスするとラズパイのメモリ使用量などのメトリクスが出力されているのが確認できます。

$ curl localhost:9100/metrics
# HELP go_gc_duration_seconds A summary of the pause duration of garbage collection cycles.
# TYPE go_gc_duration_seconds summary
go_gc_duration_seconds{quantile="0"} 0.000119685
go_gc_duration_seconds{quantile="0.25"} 0.000119685
go_gc_duration_seconds{quantile="0.5"} 0.000265944
go_gc_duration_seconds{quantile="0.75"} 0.000507354
go_gc_duration_seconds{quantile="1"} 0.000507354
(以下省略)

Exporterは他にもたくさんあります。
また、基本的に特定のフォーマットに沿ってテキストで出力しているだけなので、自作しようと思えばできるようです。

Prometheus弐ノ型 メトリクス収集 / 弐ノ型・改 アラート判定

監視ツールの本体です。
Exporterが出力したエンドポイントに定期的にアクセスし、メトリクスを収集・保存します。

普段使いのPCに導入し、ラズパイのnode_exporterが出力したメトリクスを収集してみましょう。
node_exporterと同様に公式のdownloadページから対応するバイナリをダウンロードし解凍します。
設定ファイル(prometheus.yml)にどのエンドポイントからメトリクスを取得するかを記載する箇所(targets)があるので、そこに先ほどのnode_exporterのものを入力し実行します。
デフォルトだと9090ポートでPrometheusが動作するので、ブラウザでアクセスします。
下記のようなシンプルなUIがPrometheusのUIになります。

f:id:massoumen:20201206171236p:plain

PrometheusではPromQLと呼ばれる独自クエリでメトリクスの表示や後述するアラート条件の設定をします。
例えば下記のようなクエリを投げるとnode_exporterで取得したnode_memory_MemAvailable_bytesというメトリクス(空きメモリ)の値を1024で3回割った値を出してくれます。
(単にギガバイト単位で出力したいなと思っただけで、あまり深い意味は無いですが…)

node_memory_MemAvailable_bytes / 1024 / 1024 / 1024

f:id:massoumen:20201206171249p:plain

また、時系列データとして保存されているので、グラフとして値の変化を見る事もできます。

f:id:massoumen:20201206172823p:plain

メモリに負荷をかけるコマンドを打った後にグラフを出力すると爆速で空きメモリの数値が減っていくのが分かります。
大事なサーバでいきなりこんな現象が起きたら発狂不可避ですね。

$ /dev/null < $(yes)

f:id:massoumen:20201206172955p:plain

また、設定ファイルに監視ルールを記載する事で、条件を満たした際に後述するAlertManagerにアラートを飛ばす事ができます。
例えば下記のような設定をするとディスクの空き容量が25%以下になった場合にアラートを出す事ができます。

groups:
  - name: example
    rules:
    - alert: HighDiskUsage
      expr: node_filesystem_avail_bytes{mountpoint="/"} / node_filesystem_size_bytes{mountpoint="/"} < 0.25
      for: 5m
      labels:
        severity: page
      annotations:
        summary: High disk usage

設定ファイルを編集した後Prometheusを再起動し、Alertsを選択すると監視ルールと状態の確認ができます。

f:id:massoumen:20201206182904p:plain

ラズパイ上に無駄にデカいファイルを生成し、ディスク容量を消費してみましょう。

$ fallocate -l 10G 10G.txt

しばらく待つと監視ルールが赤くなりました。無事死亡です。

f:id:massoumen:20201206183721p:plain

この状態になるとAlertManagerにアラートを飛ばすようになります。
配置した無駄にデカいファイルを削除すると正常値と判定されるようになり、静かになります。

AlertManager参ノ型 アラート通知

Prometheusから送られてきたアラートを受け取り、実際に通知処理を行います。
通知先にはメールやSlack、PagerDutyなど様々なものが対応しています。
補足ですが、PagerDutyというのは設定したルールに応じてアラートの集約や管理、電話通知などを行ってくれるサービスの事です。
察して下さい。

また、送られてきたアラートのラベルを参照し、アラートAはチームXに通知、アラートBはチームYに通知…という風にアラートを振り分けたりする事もできます。
AlertManagerも他と同様に公式のdownloadページからバイナリをダウンロードできます。
ここではメールを送信するように設定してみます。
AlertManagerの設定ファイルにメールサーバやパスワードを記述し、Prometheusの設定ファイルにアラートの送り先(AlertManaerのURL)を記述します。
設定が完了したら両方とも起動します。
再度ラズパイ上に無駄にデカいファイルを生成しアラートを発生させると、下記のようなメールが来ます。

f:id:massoumen:20201206223121p:plain

終わりに隙自語

どうしたって 消せないバグと 止まらないアラート

監視処理の一例としてPrometheusと関連ソフトウェアについて紹介しましたが、いかがでしたか?
メトリクスの収集やアラート判定、通知の設定を行う事で、自分たちの管理しているサーバやプログラムに異常があった際にすぐに気付き、対応する事ができるようになります。
とは言え、なんでもかんでも監視してアラートを設定すれば良いというものでも無いので、本当に重要な処理だけ監視するようにしたり、重要度を設定し高いものは電話、低いものは適当なチャンネルにSlack通知するだけといったような調整も考えていかないといけません。

4時にアラートの電話で叩き起こされた後7時にもう一度アラートの電話で叩き起こされた日がありました。結局眠すぎてその日午前休を取って寝ようとしたのですが、その後10時にまたアラートの電話で叩き起こされたので、本気で仕事辞めようかと思いました。

また、監視やアラートの話とは少しズレますが、少しでもわかりやすく、管理しやすいプログラムを書けるよう日々努力しましょう。(自戒)
クソコードを書いては先輩に咎められる毎日…
書いて終わりな趣味のコードなら良いですが、長く付き合うコードの場合は後で誰かが苦しむ事になるので…
自分とは限らないですよ。
察して下さい。