PrometheusをDockerでさくっと動かしてコンテナで稼働するサービスの稼働監視

PrometheusをDockerで動かして簡易に動作確認する方法についてのメモ。
すでに似たような情報沢山なので詳しくはそちらを参照で。

今回試した環境はPrometheus v2.2.1


# prometheus.ymlの作成

Prometheusサーバの監視設定をまず作成します。
ホストOS上に以下のファイルを作成

```yml:~/prometheus-data/prometheus.yml
global:
 scrape_interval:     15s

scrape_configs:
 - job_name: 'node'
   static_configs:
     - targets:
       - '172.19.0.8:9100'
```
必要最小限の設定です。
上記は172.19.0.8の9100ポートで稼働するexporterから15秒間隔でデータをポーリングして収集する設定です。
job_nameは任意の文字列で指定可能で、重要なのはtargetsの設定箇所です。Prometheusサーバから接続する先のexporterの稼働IP:ポート情報が正しくないと監視できないので注意。
job_nameは後述のPromQLのフィルタリング条件として活用できる1つのラベル情報の扱いとなります。

# Prometheus Serverを起動

Prometheusの公式のDockerイメージを使ってPrometheusのサーバを起動します。
Prometheusの監視設定を記載するprometheus.ymlのデータは先程作成したホスト側のディレクトリをマウントして見せるようにボリューム設定します。

```shell-session
$ docker run -p 9090:9090 -v /home/prometheus-data:/prometheus-data prom/prometheus --config.file=/prometheus-data/prometheus.yml
```

これだけで起動OKです。

# node exporterを起動

prometheus.ymlで指定したnode exporterのtargets上にnode exporterを稼働させます。

https://github.com/prometheus/node_exporter/releases
今回は、このページからbuild済みのバイナリを取得して実行させました。

```shell-session
$ wget https://github.com/prometheus/node_exporter/releases/download/v0.16.0-rc.1/node_exporter-0.16.0-rc.1.linux-amd64.tar.gz
$ tar xvzf node_exporter-0.16.0-rc.1.linux-amd64.tar.gz
$ cd node_exporter-0.16.0-rc.1.linux-amd64
$ ./node_exporter
```
とりあえずデフォルト設定のまま起動。

# ダッシュボードで状況確認

ダッシュボードで結果を確認します。
http://DockerホストのIP:9090
にアクセスします。

以下のように「Graph」メニューから見たい情報を選択して出力させればOKです。
この例ではnode exporterから収集したload average 1分平均の値を出力しています。

![prometheus1.png](https://qiita-image-store.s3.amazonaws.com/0/45851/95c1712c-3b95-b142-9f38-ec865018a653.png)

# cAdvisorによるコンテナ監視

次にDockerコンテナの監視のため、cAdvisorを導入してみます。
コンテナ用の公式のexporterはないようで、サードパーティ製のものとなります。
container-exporterというのもありますが、こちらはcAdvisorにdeprecatedとなっているのでcAdvisorを使うのが良さそうです。

## cAdvisorが稼働するコンテナを起動

```shell-session
docker run -v /:/rootfs:ro -v /var/run:/var/run:rw -v /sys:/sys:ro -v /var/lib/docker/:/var/lib/docker:ro -v /dev/disk/:/dev/disk:ro -p 8080:8080 -d --name=cadvisor google/cadvisor:latest
```
このコンテナを起動することで、/var/run/docker.sock経由でコンテナからホストのdocker情報を収集できるようになります。

## prometheus.ymlを修正

最初に作成したprometheus.ymlに上記のcAdvisorが稼働するポートから情報を取得するように定義します。

```yml
global:
 scrape_interval:     15s

scrape_configs:
 - job_name: 'node'
   static_configs:
     - targets:
       - '172.19.0.8:9100'
## 以下を追記 ##
 - job_name: 'docker-container'
   static_configs:
     - targets:
       - '172.19.0.10:8080'
```

cAdvisorが稼働している172.19.0.10:8080をscrapeして情報収集します。
画面で確認するとこんな感じでホスト上で稼働する各コンテナの統計情報が自動で収集されます。

![prometheus2.png](https://qiita-image-store.s3.amazonaws.com/0/45851/33b617d9-8a8f-0536-588f-33204c45c6bb.png)

# PromQLで必要な情報のみをピックアップ

ここまで試してみて、取れる情報がたくさん入ってくるようになっています。
ここから「見たい情報」「知りたい情報」をうまくピックアップする必要があります。

PrometheusにはPromQLというクエリ実行による監視結果データのフィルタリング機能があります。

## 特定のコンテナの情報のみを表示

先程のコンテナの監視結果のうち、特定のコンテナの情報のみピックアップしたい場合は以下のようなクエリになります。

```prometheus
container_cpu_user_seconds_total{name='zabbix-server_1'}
```
コンテナのCPU ユーザ時間の合計値の内、コンテナ名がzabbix-server_1のもののみの情報を抽出する例です。

## 特定のimageから起動されたコンテナの情報に対して関数処理して表示

Dockerコンテナで運用する場合、同じイメージをもとにしたコンテナを複数スケールさせて稼働させるケースも多いと思います。
例えばそんな状態で、1個ずつのコンテナの情報を確認するのではなく、スケールした全体を通してどういう状況かを確認することも簡単にできます。

```prometheus
sum(container_cpu_user_seconds_total{image='nginx'}) # nginxイメージから稼働しているコンテナのCPUユーザ時間の合計
avg(container_cpu_user_seconds_total{image='nginx'}) # nginxイメージから稼働しているコンテナのCPUユーザ時間の平均
```
その他にも様々な関数が利用可能です。
[参考](https://prometheus.io/docs/prometheus/latest/querying/functions/#deriv())

# まとめ

以前紹介したsysdigもそうでしたが、最近の流れとして、取れる情報は極力集約し、その集まったデータから何をどう情報として取り出すかの処理が行いやすくなってきているというのがポイントかと思います。Prometheusのexporterの考えやPromQLの考えは興味深く活用の幅が非常に広がる仕組みかと思います。