Prometheusで始める次世代のシステム監視

# はじめに
本記事は次世代のシステム監視ツールとして定着しつつあるPrometheusについて、概要や導入方法についてまとめています。

## 次世代のシステム監視
システムを構築する際に、AWSなど事業者が提供するパブリッククラウドサービスの利用を第一に考える**クラウドファースト**という考え方は、デファクトスタンダードと言っても過言ではありません。

コロナなどの不確実性、市場のニーズや価値観の変化など、ビジネスに求められるスピードは必然的に高くなっています。そのため、変化に対応しやすく迅速にシステムをスケールさせるためには、マイクロサービスの考え方やコンテナ技術の活用は必須です。

従って、ビジネスを継続させるためにシステム監視の手段についても、専用のモジュールをインストールする従来のエージェント型（※）から、エージェントレス型の監視方式やコンテナ監視等、システム監視に対する考え方も変わってきました。

（※）監視対象サーバーにエージェントをインストールし、マネージャーとなる管理サーバーから集中監視する様な監視方式のこと

## Prometheus概要
Prometheusは、[SoundCloud](https://soundcloud.com/)のエンジニアによって開発されたオープンソースのシステム監視ツールになります。2016年には、Kubernetesに続く2番目のホストプロジェクトとしてCNCF（Cloud Native ComputingFoundation）に参加しました。

Prometheusはkubernetesなどコンテナ環境を監視するために開発されましたが、オンプレミスの環境でも使用することができます。また、エージェントレス型の監視方式となっているため、導入がしやすいのも魅力です。

### アーキテクチャ
Prometheusのアーキテクチャについて以下に記載します。

![prometheus.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221759/e5cc1d73-c7a0-064f-b618-0981b0d3bc06.png)

- Prometheus　serverが監視対象に対して、pull型の監視を行う
- スクレイプして取得された時系列データは、Prometheus　Web UIや、Grafanaなどと連携してダッシュボードで表示することができる
- ルールとアラートを設定し、Alertmanagaerを用いてEmailやWebhookでアラートを通知する
- ほとんどのPrometheusコンポーネントはGoで記述されているため、静的バイナリとして簡単にビルドおよびデプロイできる

## Prometheus導入
Prometheusを実行するためには、[Prometheusのサイト](https://prometheus.io/download/)からバイナリ（※）をダウンロードします。

（※）本記事では本記事執筆時点である2.28.1のバージョンを使用。

### Prometheusのダウンロード
本記事では/opt配下にダウンロードしています。

- Prometheusのダウンロード及び展開  
`# cd /opt`  
`# wget https://github.com/prometheus/prometheus/releases/download/v2.28.1/prometheus-2.28.1.linux-amd64.tar.gz`  
`# tar xzvf prometheus-2.28.1.linux-amd64.tar.gz`

### Prometheusの設定
展開したディレクトリに移動し、`prometheus.yml`ファイルを編集します。
Prometheusは設定ファイルとして**YAML形式**を使用しています。

スクレイプの監視間隔を変更するために、globalセクションのscrape_intervalの値について、デフォルト値の15秒から10秒に変更します。

- prometheus.ymlの編集
`# cd prometheus-2.28.1.linux-amd64/`
`# vi prometheus.yml`

- prometheus.yml

```yaml
global:
  scrape_interval:     10s # Set the scrape interval to every 15 seconds. Default is every 1 minute.
  evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute.
  # scrape_timeout is set to the global default (10s).
```

### Prometheusの起動
systemctlに登録してサービスの管理を行います。
また、管理しやすい様に、シンボリックリンクを作成します。

`# ln -s /opt/prometheus-2.28.1.linux-amd64 /opt/prometheus`
`# vi /etc/systemd/system/prometheus.service`

- /etc/systemd/system/prometheus.service
  
```text 
[Unit]
Description = Prometheus
After=local-fs.target
ConditionPathExists=/opt/prometheus

[Service]
ExecStart=/opt/prometheus/prometheus.sh
Restart=no
Type=oneshot
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target
```

`prometheus.service`から実行する起動スクリプトを作成します。
また、スクリプトに実行権限を付与します。

`# vi /opt/prometheus/prometheus.sh`
`# chmod +x /opt/prometheus/prometheus.sh`

- prometheus.sh

```bash
#! /bin/bash

cd /opt/prometheus
nohup ./prometheus &
```

以下のコマンドを実行し、systemctlの登録を行います。

`# systemctl daemon-reload`

systemctl登録後、prometheusを起動します。
prometheus起動後、statusがactiveになっていることを確認します。

`# systemctl start prometheus.service`
`# systemctl status prometheus.service`

```console
● prometheus.service - Prometheus
     Loaded: loaded (/etc/systemd/system/prometheus.service; disabled; vendor preset: enabled)
     Active: active (exited) since Sat 2021-07-24 23:36:16 JST; 1s ago
    Process: 1281 ExecStart=/opt/prometheus/prometheus.sh (code=exited, status=0/SUCCESS)
   Main PID: 1281 (code=exited, status=0/SUCCESS)
      Tasks: 5 (limit: 1100)
     Memory: 16.8M
     CGroup: /system.slice/prometheus.service
             └─1291 ./prometheus

Jul 24 23:36:16 ubuntu prometheus.sh[1291]: level=info ts=2021-07-24T14:36:16.953Z caller=head.go:794 component=tsdb msg="On-disk memory mappable chunks r>
Jul 24 23:36:16 ubuntu prometheus.sh[1291]: level=info ts=2021-07-24T14:36:16.953Z caller=head.go:800 component=tsdb msg="Replaying WAL, this may take a w>
Jul 24 23:36:16 ubuntu prometheus.sh[1291]: level=info ts=2021-07-24T14:36:16.955Z caller=tls_config.go:191 component=web msg="TLS is disabled." http2=fal>
Jul 24 23:36:16 ubuntu prometheus.sh[1291]: level=info ts=2021-07-24T14:36:16.956Z caller=head.go:854 component=tsdb msg="WAL segment loaded" segment=0 ma>
Jul 24 23:36:16 ubuntu prometheus.sh[1291]: level=info ts=2021-07-24T14:36:16.956Z caller=head.go:860 component=tsdb msg="WAL replay completed" checkpoint>
Jul 24 23:36:16 ubuntu prometheus.sh[1291]: level=info ts=2021-07-24T14:36:16.960Z caller=main.go:851 fs_type=EXT4_SUPER_MAGIC
Jul 24 23:36:16 ubuntu prometheus.sh[1291]: level=info ts=2021-07-24T14:36:16.961Z caller=main.go:854 msg="TSDB started"
Jul 24 23:36:16 ubuntu prometheus.sh[1291]: level=info ts=2021-07-24T14:36:16.961Z caller=main.go:981 msg="Loading configuration file" filename=prometheus>
Jul 24 23:36:16 ubuntu prometheus.sh[1291]: level=info ts=2021-07-24T14:36:16.961Z caller=main.go:1012 msg="Completed loading of configuration file" filen>
Jul 24 23:36:16 ubuntu prometheus.sh[1291]: level=info ts=2021-07-24T14:36:16.961Z caller=main.go:796 msg="Server is ready to receive web requests."
```

サーバ起動時にprometheusを自動起動させたい場合は、以下のコマンドを実行します。

`# systemctl enable prometheus.service `

### 式ブラウザ
Prometheusは、**PromQL（Prometheus Query Language）**と呼ばれる関数型クエリ言語を提供します。
式ブラウザでPromQLを用いてクエリを実行し、式の結果をグラフとして表示することができます。

PromQLは独自のクエリ言語となっていますが、直感的に分かりやすい仕様となっています。
また、ラベルを使ったフィルタリングや時系列データが簡単に操作できるのが特徴です。
その他、取得したメトリクスに対して、四則演算や論理演算を行いデータを加工して表示することもできます。

prometheusはデフォルトでTCPポート9090を使用します。
ブラウザを起動し、http://＜サーバのIPアドレス＞:9090にアクセスします。
このUIに表示されている式ブラウザから、PromuQLクエリを実行することができます。

![スクリーンショット 2021-08-15 15.55.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221759/1edf1630-a804-3b8a-f45b-608490de95ab.png)

prometheusが監視対象としているターゲットを確認したい場合は、[Status]タブから[Targets]を選択します。

![スクリーンショット 2021-08-15 15.46.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221759/905e5f3a-9159-6edb-db5d-a9bd3a84d1da.png)

prometheus自身が監視されていることが分かります。

![スクリーンショット 2021-08-15 15.46.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221759/798cd87d-95b4-873c-ca7a-3e099726e032.png)

デフォルトのページに戻って、PromuQLクエリを実行してみます。
試しに検索窓に`up`を入力すると、PromuQLクエリの式である予測候補が表示されます。

![スクリーンショット 2021-08-15 15.47.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221759/eec30a0e-1e81-0f3a-98ce-a7556431aa4a.png)

[Execute]ボタンを押します。

![スクリーンショット 2021-08-15 15.47.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221759/8ab59046-9e71-ef94-4a19-44b6484222dc.png)

式ブラウザで`up`を実行した結果が表示されます。
この場合、`up`はprometheus自身が自分をスクレイプした結果として、成功を意味する**1**が表示されているのが確認できます。よって、prometheusの稼働状態が正常であることが確認できます。

![スクリーンショット 2021-08-15 15.58.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221759/e8d7c1cf-dae8-0919-5c18-77eda7fd1a20.png)

式ブラウザからPromQLを用いてクエリを実行する場合、取得するメトリクスに対して、ラベルを使用することでメトリクスの補完ができます。例えば、先ほどの`up`は以下の様に`instance`ラベルでターゲットの監視先を指定し、`job`ラベルで名前を指定することができます。

```text
up{instance="localhost:9090", job="prometheus"}
```

![スクリーンショット 2021-08-29 21.59.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221759/b63c602c-e349-5809-473c-cadd76adbc15.png)

## Node exporter
Node exporterはLinuxなどのCPU、メモリ、ディスク容量等一般的なシステムリソースのメトリクスを取得して、ダッシュボードで可視化することができます。

Node exporterはPrometheusと同じく[Prometheusのサイト](https://prometheus.io/download/)からバイナリ（※）をダウンロードします。

### Node exporterのダウンロード

本記事では/opt配下にダウンロードしています。

- Node exporterのダウンロード及び展開   
`# cd /opt`  
`# wget https://github.com/prometheus/node_exporter/releases/download/v1.2.0/node_exporter-1.2.0.linux-amd64.tar.gz` 　　  
`# tar xzvf node_exporter-1.2.0.linux-amd64.tar.gz`　　

### Node exporterの設定
Node exporterの設定を追加するため、`prometheus.yml`ファイルを編集し、scrape_configsセクションに新しく、以下`job_name: 'node'`で始まるスクレイプ設定を追加します。

- prometheus.ymlの編集 
`# cd node_exporter-1.2.0.linux-amd64/` 
`# vi prometheus.yml`

- prometheus.yml

```yaml
scrape_configs:
  # The job name is added as a label `job=<job_name>` to any timeseries scraped from this config.
  - job_name: 'prometheus'

    # metrics_path defaults to '/metrics'
    # scheme defaults to 'http'.

    static_configs:
    - targets: ['localhost:9090']
  - job_name: 'node'
    static_configs:
    - targets: ['localhost:9100']
```

設定ファイル編集後、prometheusのサービスを再起動します。

`# systemctl restart prometheus.service`

prometheusのサービス再起動後、再度`up`を入力すると、Node exporterが追加されたことが分かります。

![スクリーンショット 2021-08-15 16.36.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221759/d8c2fc9d-967e-aa11-295d-e0eacca68f87.png)

Node exporterの状態は0になっているため、試しにサーバ側で以下のコマンドを実行します。

`# ./node_exporter `

Node exporter起動後、再度`up`を入力すると、Node exporterの状態が1になったことが分かります。

![スクリーンショット 2021-08-15 16.36.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221759/8f5c7da0-d497-e11c-0621-cf61ecd6213f.png)

上記、Prometheusに書いた様に、Node exporterもsystemctlで管理することができます。

# おわりに
SREとして重要なのは従来のシステム監視の考え方として、アラートに対して人間が全ての判断を行って対応するのではなく、基本的にソフトウェアがアラートを解釈して必要な時のみ人が対応を行うように、監視システムを作り込むことです。

この様な効果的なモニタリングを行うには、Prometheusはこれから身につけておくべきツールの一つです。

## 参考
- [DOCS](https://prometheus.io/docs/introduction/overview/)
- [How Prometheus Monitoring works | Prometheus Architecture explained](https://www.youtube.com/watch?v=h4Sl21AKiDg)