process-exporter + Prometheus + Grafana でバッチ処理のリソース状況を可視化する

はじめに

こんにちは、システム本部新興メディアシステム1部スマイティ担当の山下です。

みなさま、バッチ処理のリソース監視はやっていますか?
今回は「process-exporter」というPrometheusのExporterを使って、スマイティのバッチ処理のリソース状況をGrafanaで可視化した話をしようと思います。

process-exporterとは

process-exporter は時系列データベースであるPrometheusにプロセスのメトリクスを渡すためのExporterです。
PrometheusのExporterはミドルウェアの情報やサーバーのリソース情報を出力するものが多いですが、process-exporterは実行したサーバー内で動くプロセスごとのCPU使用率やメモリ使用量といった情報を出力します。
具体的にはlinux/proc配下の情報を出力しているようです。

環境

今回の環境は以下のようになってます。

  • process-exporter 0.7.10
  • prometheus 2.7.1
  • grafana 8.1.2
  • process-exporterを動かすバッチサーバー CentOS 7.2

インストール

公式Github を参考にインストールします。
他の一般的なPrometheusのExporterと同様に情報を渡したい方のサーバーで動作させます。なので今回はスマイティのバッチサーバーにインストールしています。

ここでは releases からlinux-amd64版のパッケージを取得してインストールしています。
/usr/local/prometheus配下にファイルを置いて/usr/bin/process-exporterにバイナリファイルへのシンボリックリンクを作成しています。

cd /tmp
wget https://github.com/ncabatoff/process-exporter/releases/download/v0.7.10/process-exporter-0.7.10.linux-amd64.tar.gz
tar xvzf process-exporter-0.7.10.linux-amd64.tar.gz
sudo mkdir -p /usr/local/prometheus
sudo cp -r /tmp/process-exporter-0.7.10.linux-amd64 /usr/local/prometheus
sudo ln -s /usr/local/prometheus/process-exporter-0.7.10.linux-amd64/process-exporter /usr/bin/process-exporter

設定ファイルとなるconfig.ymlも作成しておきます。

sudo touch /etc/process-exporter/config.yml

インストールしたらService化して常駐させます。
まずService化のために必要なファイルを作成します。

sudo touch /usr/lib/systemd/system/process-exporter.service
sudo vi /usr/lib/systemd/system/process-exporter.service

sudo touch /etc/sysconfig/process-exporter
sudo vi /etc/sysconfig/process-exporter

/usr/lib/systemd/system/process-exporter.serviceの中身は以下です。

[Unit]
Description=Process Exporter for Prometheus

[Service]
User=root
Type=simple
EnvironmentFile=/etc/sysconfig/process-exporter
ExecStart=/usr/bin/process-exporter $OPTIONS
KillMode=process
Restart=always

[Install]
WantedBy=multi-user.target

/etc/sysconfig/process-exporterの中身は以下です。

OPTIONS='--config.path /etc/process-exporter/config.yml --web.listen-address=:9256 --web.telemetry-path="/metrics"'

作成したファイルを読み込ませて常駐させます。

sudo systemctl daemon-reload
sudo systemctl enable process-exporter.service
sudo systemctl start process-exporter

インストールは以上です。

ここでは.serviceファイルなどを自分で作りましたが、 公式リポジトリ内 にもデフォルトのファイルは配置されていますのでそれをベースにしてもいいと思います。
デフォルトの設定ファイル もあり、すべてのプロセスのメトリクスを出力する設定になっています。

設定

config.ymlに書きます。
スマイティでは以下のような設定にしています。

process_names:
  - name: "php_symfony_batch_{{.Matches.BatchName}}"
    exe:
      - php
    cmdline:
      - 'php\s+.*\s+(?P<BatchName>batch:\S+).*'
  - name: "php_batch_{{.Matches.FileName}}" 
    exe:
      - php
    cmdline:
      - 'php\s+.*/(?P<FileName>[^/ ]+\.php).*'
  - name: "sh_{{.Matches.FileName}}" 
    cmdline:
      - '.*/(?P<FileName>[^/ ]+\.sh).*'

process-exporterは、例えば物理メモリ使用量であれば次のようなメトリクスを出力します。

namedprocess_namegroup_memory_bytes{groupname="xxx",memtype="resident"} (value)

configのnameは、このgroupnamexxxに入る値になります。

すべてのプロセスのメトリクスを出力すると多すぎるので、スマイティでは自分たちで作ったバッチのプロセスに対象を絞っています。

絞る条件は、comm, exe, cmdline の3つの方法のいずれかで指定します。複数指定した場合は全ての条件にマッチしたプロセスに絞られます。
cmdline正規表現で抽出します。実行ファイルの引数まで含めて完全一致している必要があります。
正規表現(?P<name>) の括弧内にマッチした文字列はname{{.Matches.name}} で参照できます。
exeは実行ファイル名だけの一致で抽出します。
条件はcmdlineだけで指定するより、execommを先に記述して限定したほうがパフォーマンスがあがるそうです。

スマイティではPHP+Symfonyを採用しており、バッチは例えば以下のようなコマンドで実行しています。

php bin/console batch:batch-name-hogehoge --opt=xxx --env=prod

上記のコマンドは1つ目のnameの条件にマッチします。

  - name: "php_symfony_batch_{{.Matches.BatchName}}"
    exe:
      - php
    cmdline:
      - 'php\s+.*\s+(?P<BatchName>batch:\S+).*'

上記のコマンドのnamephp_symfony_batch_batch:batch-name-hogehoge となります。
これがメトリクスのgroupnameに入り、次のようなメトリクスが出力されることになります。

namedprocess_namegroup_memory_bytes{groupname="php_symfony_batch_batch:batch-name-hogehoge",memtype="resident"} (value)

※なお、この設定ではコマンドの--opt=xxx --env=prodの部分はnameに含めていないため、何が指定されていても同じメトリクスとして出力されます。

同様に、2つ目のnameでは素のphpのプロセスに、3つ目のnameでは.shのプロセスに、それぞれマッチさせる条件を書いています。

もし、動的にファイル名やパスを変えてphpやshを実行するシステムがあるとメトリクスが爆発的に増えてPrometheusが悲鳴をあげるので注意しましょう。その場合はそれらを除外するか同一視するような条件を書けばOKです。

設定ファイルを変えたらprocess-exporterを再起動して読み込ませます。

sudo systemctl restart process-exporter

Prometheusにメトリクスをためる

バッチサーバーでprocess-exporterが出力するメトリクスをPrometheusのスクレイピング対象とします。
方法は他の一般的なPrometheusのexporterと同じなので割愛します。

Grafanaで可視化

以下のようにバッチプロセスごとのCPU使用率やメモリ使用量をグラフ化できました。
※バッチ名は伏せてあります。

色分けされている凡例のところがconfigのname、すなわち各バッチになります。

グラフをだすためのクエリ(PromQL)は今回詳しく触れませんが例えばメモリ使用量の方だと次のようになっています。

sum(namedprocess_namegroup_memory_bytes{instance="$node:9256",memtype="resident"}) by (groupname) > (50 * 1024 * 1024)

$nodeはバッチサーバーのホストが入る変数です。
50MB以上に限定して表示しているのは凡例に表示されるバッチが多すぎると見辛かったからです。メモリ使用量を気にするなら50MB以上使っているバッチを見るだけで十分と判断しました。

何に使えるのか?

バッチリリース後にメモリやCPUのリソースを使いすぎていないか確認できる

バッチごとにメモリ使用量をログに出力して確認するよりは楽なのではないでしょうか?
もちろん本当にサーバーリソースを逼迫するリスクが高いものは本番で動かす前にも検証は必要です。

バッチのリソース消費量の変化をグラフで観察できる

時系列データなので言わずもがなです。

サーバーのリソースが逼迫してきたときに、新サーバーに処理をうつすバッチを吟味できる

サーバー全体のCPUやメモリのリソース状況みるだけでは、どのバッチを…というところまでは検討できませんが、バッチごとに可視化されていれば可能です。

他の時系列データとバッチのグラフを俯瞰することで新たな発見ができるかもしれない

Grafanaは同じタイムスパンで複数のグラフを俯瞰するのに適したUIになっており、バッチプロセスのリソース状況もそこに並べることで他の時系列データとタイムスパンを合わせて眺めることが容易になります。

1つ前の項目と被りますが、サーバー全体のCPU使用率とバッチプロセスごとのCPU使用率を俯瞰すれば、何のバッチがCPUを使っているのか一目瞭然かもしれません。

他には例えば、バッチはDBに書き込む処理を行なっていることも多いと思います。
ならMasterDBのロードアベレージバッチ処理の時系列データを並べて眺めるとMDB負荷の原因に気づくこともあるかもしれません。

サーバー全体のCPU使用率、メモリ使用量、ロードアベレージといったメトリクスは node_exporter で取得できます。
Grafanaでダッシュボードを作ってグラフを並べておくと良いでしょう。

総括

バッチ処理のリソース状況の可視化はサービスに必須とは言いませんが、調査を楽にしてくれるもの、新しい気づきを提供してくれるもの、だと思います。

また、process-exporterはもちろんプロセスの死活監視にもつかえます。そちらは他のツールですでに行なっていることも多いと思われますので今回は触れませんでした。

カカクコムでは、ともにサービスをつくる仲間を募集しています!

カカクコムのエンジニアリングにご興味のある方は、ぜひこちらをご覧ください!

カカクコム採用サイト