Prometheus+GrafanaでKubernetesクラスターを監視する ~Binaryファイルから起動+yamlファイルから構築~

# はじめに
先日[Kubernetesの監視ってどうやるのかを調べました](https://qiita.com/FY0323/items/82eeca93d00cbb4682e7)が、実際の使い方を知りたくなり、動かしてみました。Kubernetesを監視するツールとして代表的なものは[Datadog](https://www.datadoghq.com/)と[Prometheus](https://prometheus.io/)ですが、今回はPrometheusの使い方を調べて実践しました。また、Prometheusとセットで使われることの多い[Grafana](https://grafana.com/)という可視化ツールも合わせて利用します。

# Prometheusとは
もともとはSoundCloudが開発した、監視とアラート機能を持つツールです。2016年からCNCFに参画し、[2018年8月にGraduationのステータスになりました](https://www.cncf.io/announcement/2018/08/09/prometheus-graduates/)。

全体のアーキテクチャは以下のようになります。
![アーキテクチャ](https://prometheus.io/assets/architecture.png)

中身の説明に関しては、以下の記事が参考になりました。
[次世代監視の大本命！ Prometheus を実運用してみた](https://qiita.com/sugitak/items/ff8f5ad845283c5915d2)
[10分で理解する Prometheus](https://qiita.com/Chanmoro/items/ac0eb1bf93760566b338)

[公式の紹介ページはこちら](https://prometheus.io/docs/introduction/overview/)

# Prometheusの起動
Prometheusを利用する方法は、大きく2つの方法があります。
1. Binaryファイルをインストールして起動
2. コンテナイメージを利用して開始

2つ目はKubernetesやdockerから開始することができますが、今回はyamlファイルを作成してkubectlコマンドから起動した手順を紹介します。

## 環境
[こちらの記事で構築した環境](https://qiita.com/FY0323/items/c84b01e7976d45801d48)を利用します。

OS: Centos7
Kubernetes version: 1.13.1
User: 以下の作業は全てrootユーザで実行しています。

## Binaryファイルを起動
Binaryファイルから開始する方法は公式ページの[Getting started](https://prometheus.io/docs/prometheus/latest/getting_started/)で紹介されています。

### Binaryファイルのインストール
[こちらのページ](https://prometheus.io/download/)からバージョンを指定してインストールします。

```
wget https://github.com/prometheus/prometheus/releases/download/v2.6.0/prometheus-2.6.0.linux-amd64.tar.gz
tar xvfz prometheus-2.6.0.linux-amd64.tar.gz
cd prometheus-2.6.0.linux-amd64
```

### prometheus.ymlファイルの確認
Prometheusのコンフィグファイルである```prometheus.yml```は、デフォルトでは以下のようになっています。設定変更がある場合はこのファイルを変更してPrometheusを起動します。後ほどコンフィグファイルを一部変更します。

```prometheus.yml 
# my global config
global:
  scrape_interval:     15s # 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).

# Alertmanager configuration
alerting:
  alertmanagers:
  - static_configs:
    - targets:
      # - alertmanager:9093

# Load rules once and periodically evaluate them according to the global 'evaluation_interval'.
rule_files:
  # - "first_rules.yml"
  # - "second_rules.yml"

# A scrape configuration containing exactly one endpoint to scrape:
# Here it's Prometheus itself.
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']
```

### Binaryファイルから起動
以下のようにコンフィグファイルを指定して起動します。

```
./prometheus --config.file=prometheus.yml
```

コマンドを実行すると以下のようなログが表示されます。```Server is ready to receive web requests.```という表記が見えたらアクセス可能です。

```
level=info ts=2019-01-04T03:31:45.335407864Z caller=main.go:243 msg="Starting Prometheus" version="(version=2.6.0, branch=HEAD, revision=dbd1d58c894775c0788470944b818cc724f550fb)"
level=info ts=2019-01-04T03:31:45.335501267Z caller=main.go:244 build_context="(go=go1.11.3, user=root@bf5760470f13, date=20181217-15:14:46)"
level=info ts=2019-01-04T03:31:45.33552679Z caller=main.go:245 host_details="(Linux 3.10.0-957.1.3.el7.x86_64 #1 SMP Thu Nov 29 14:49:43 UTC 2018 x86_64 k8s-master (none))"
level=info ts=2019-01-04T03:31:45.335552521Z caller=main.go:246 fd_limits="(soft=1024, hard=4096)"
level=info ts=2019-01-04T03:31:45.335572558Z caller=main.go:247 vm_limits="(soft=unlimited, hard=unlimited)"
level=info ts=2019-01-04T03:31:45.336808997Z caller=main.go:561 msg="Starting TSDB ..."
level=info ts=2019-01-04T03:31:45.336861457Z caller=web.go:429 component=web msg="Start listening for connections" address=0.0.0.0:9090
level=info ts=2019-01-04T03:31:45.362425157Z caller=main.go:571 msg="TSDB started"
level=info ts=2019-01-04T03:31:45.3624917Z caller=main.go:631 msg="Loading configuration file" filename=prometheus.yml
level=info ts=2019-01-04T03:31:45.36354544Z caller=main.go:657 msg="Completed loading of configuration file" filename=prometheus.yml
level=info ts=2019-01-04T03:31:45.363564736Z caller=main.go:530 msg="Server is ready to receive web requests."
```

### GUIから接続
デフォルトの設定では```localhost:9090```からPrometheusの画面にアクセスできます。ここでは```http://<k8s-masterのグローバルIPアドレス:9090>```からアクセスします。
アクセスすると、以下のような画面が表示されます(```<k8s-masterのグローバルIPアドレス:9090/graph>```)。

![prometheus-binary-1.jpg](https://qiita-image-store.s3.amazonaws.com/0/177048/3fa56a9d-45d6-f12e-fdda-f0fb30af906c.jpeg)

上記画面から```http://<k8s-masterのグローバルIPアドレス:9090/metrics>```にアクセスすると、このようにメトリクスの一覧が表示されます。アクセスには画面上部のタブから選択することもできます。

![prometheus-binary-2.jpg](https://qiita-image-store.s3.amazonaws.com/0/177048/7603448a-d854-2fec-ffdf-b6c758da930d.jpeg)

[Getting Started](https://prometheus.io/docs/prometheus/latest/getting_started/)では、取得するメトリクスの例も書かれています。ここでは```prometheus_target_interval_length_seconds```というメトリクスを取得します。

画面の```Expression```という入力欄に```prometheus_target_interval_length_seconds```を入力し、```Execute```ボタンをクリックします。
![prometheus-binary-5.jpg](https://qiita-image-store.s3.amazonaws.com/0/177048/00ea1910-d875-0e47-06c9-caa341dd8d4f.jpeg)

すると入力したメトリクスを表示するので、```Graph```を選択してみます。
![prometheus-binary-6.jpg](https://qiita-image-store.s3.amazonaws.com/0/177048/387de2d2-f13d-c213-27d2-f061b432bf6f.jpeg)

するとこのようにグラフが表示されます。
![prometheus-binary-7.jpg](https://qiita-image-store.s3.amazonaws.com/0/177048/4bda1a3a-adc5-4db0-4de1-8f84fb6a5e9e.jpeg)

### Node Exporterの起動
PrometheusはPull型の監視ツールのため、被監視対象のサーバからメトリクスを受け取る必要があります。KubernetesはデフォルトでPrometheusに対応したメトリクスを提供しますが、Exporterというツールを起動してメトリクスを出力させてみます。
Exporterの種類は[Prometheusのページで紹介されており](https://prometheus.io/docs/instrumenting/exporters/)、ハードウェアからDBなど様々なメトリクスに対応しています。ここではNode ExporterというExporterを利用します。[Node Exporterを使ったPrometheusの監視についても公式ページで紹介されており](https://prometheus.io/docs/guides/node-exporter/)、基本的にそちらの方法を採用します。

Node Exporterもbinaryファイルが提供されており、Prometheusのダウンロードページから確認することができます。手順としてはPrometheusの時と同様に、binaryファイルのインストール・解凍、そして起動となります。

```
[root@k8s-master ~]# wget https://github.com/prometheus/node_exporter/releases/download/v0.17.0/node_exporter-0.17.0.linux-amd64.tar.gz
[root@k8s-master ~]# tar xvfz node_exporter-0.17.0.linux-amd64.tar.gz
[root@k8s-master ~]# cd node_exporter-0.17.0.linux-amd64
[root@k8s-master node_exporter-0.17.0.linux-amd64]# ./node_exporter &
```

以下のようなログが表示され、起動します。

```
INFO[0000] Starting node_exporter (version=0.17.0, branch=HEAD, revision=f6f6194a436b9a63d0439abc585c76b19a206b21)  source="node_exporter.go:82"
INFO[0000] Build context (go=go1.11.2, user=root@322511e06ced, date=20181130-15:51:33)  source="node_exporter.go:83"
INFO[0000] Enabled collectors:                           source="node_exporter.go:90"
INFO[0000]  - arp                                        source="node_exporter.go:97"
INFO[0000]  - bcache                                     source="node_exporter.go:97"
INFO[0000]  - bonding                                    source="node_exporter.go:97"
INFO[0000]  - conntrack                                  source="node_exporter.go:97"
INFO[0000]  - cpu                                        source="node_exporter.go:97"
INFO[0000]  - diskstats                                  source="node_exporter.go:97"
INFO[0000]  - edac                                       source="node_exporter.go:97"
INFO[0000]  - entropy                                    source="node_exporter.go:97"
INFO[0000]  - filefd                                     source="node_exporter.go:97"
INFO[0000]  - filesystem                                 source="node_exporter.go:97"
INFO[0000]  - hwmon                                      source="node_exporter.go:97"
INFO[0000]  - infiniband                                 source="node_exporter.go:97"
INFO[0000]  - ipvs                                       source="node_exporter.go:97"
INFO[0000]  - loadavg                                    source="node_exporter.go:97"
INFO[0000]  - mdadm                                      source="node_exporter.go:97"
INFO[0000]  - meminfo                                    source="node_exporter.go:97"
INFO[0000]  - netclass                                   source="node_exporter.go:97"
INFO[0000]  - netdev                                     source="node_exporter.go:97"
INFO[0000]  - netstat                                    source="node_exporter.go:97"
INFO[0000]  - nfs                                        source="node_exporter.go:97"
INFO[0000]  - nfsd                                       source="node_exporter.go:97"
INFO[0000]  - sockstat                                   source="node_exporter.go:97"
INFO[0000]  - stat                                       source="node_exporter.go:97"
INFO[0000]  - textfile                                   source="node_exporter.go:97"
INFO[0000]  - time                                       source="node_exporter.go:97"
INFO[0000]  - timex                                      source="node_exporter.go:97"
INFO[0000]  - uname                                      source="node_exporter.go:97"
INFO[0000]  - vmstat                                     source="node_exporter.go:97"
INFO[0000]  - xfs                                        source="node_exporter.go:97"
INFO[0000]  - zfs                                        source="node_exporter.go:97"
INFO[0000] Listening on :9100                            source="node_exporter.go:111"
```

Web GUIから```http://<k8s-masterのグローバルIPアドレス:9100>```にアクセスすると、以下のような画面が表示されます。
![prometheus-binary-12.jpg](https://qiita-image-store.s3.amazonaws.com/0/177048/7e79c33d-821c-43d3-70c2-a4978c1c845a.jpeg)

画面中の```Metrics```をクリックすると、メトリクスがずらっと表示されます。
![prometheus-binary-13.jpg](https://qiita-image-store.s3.amazonaws.com/0/177048/326ea00c-a1d4-35af-ae69-a62d80bdfde7.jpeg)


### prometheus.ymlの編集
起動したNode Exporterからのメトリクスを受け取るには、prometheus.ymlを編集してターゲットを特定する必要があります。ここでは以下のように```targets```のポート番号を変更します。

```prometheus.yml
# my global config
global:
  scrape_interval:     15s # 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).

# Alertmanager configuration
alerting:
  alertmanagers:
  - static_configs:
    - targets:
      # - alertmanager:9093

# Load rules once and periodically evaluate them according to the global 'evaluation_interval'.
rule_files:
  # - "first_rules.yml"
  # - "second_rules.yml"

# A scrape configuration containing exactly one endpoint to scrape:
# Here it's Prometheus itself.
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:9100']　  #ポート番号を変更する
```

再びPrometheusの画面から```Status```→```Targets```を選択すると、ターゲットのポート番号が変更されています。
![prometheus-binary-3.jpg](https://qiita-image-store.s3.amazonaws.com/0/177048/641cfdc7-97c2-d696-02a4-5cee5609f9c6.jpeg)
![prometheus-binary-8.jpg](https://qiita-image-store.s3.amazonaws.com/0/177048/1e18b63b-8248-3644-4d68-293dff8f25f0.jpeg)

先ほどは利用できなかったメトリクスが利用できるようになります。ここでは```node_cpu_second_total```というメトリクスをグラフで表示しています。

![prometheus-binary-9.jpg](https://qiita-image-store.s3.amazonaws.com/0/177048/cb4f57c3-9a48-3df0-17da-1849a1e9880c.jpeg)

Node Exporterからどんなメトリクスが取得できるかは、[Node Exporterのgithubページから確認できます](https://github.com/prometheus/node_exporter)。

### 別nodeからのメトリクスを取得
ここまでは全てmaster(k8s-master)のメトリクスを取得していましたが、今度はworker(k8s-node-1)のメトリクスを取得します。worker側で上記と同じ手順でNode Exporterのインストール・起動を完了したら、再びprometheus.ymlを編集します。編集箇所は先ほどと同様```targets```の部分です。

```prometheus.yml
# my global config
global:
  scrape_interval:     15s # 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).

# Alertmanager configuration
alerting:
  alertmanagers:
  - static_configs:
    - targets:
      # - alertmanager:9093

# Load rules once and periodically evaluate them according to the global 'evaluation_interval'.
rule_files:
  # - "first_rules.yml"
  # - "second_rules.yml"

# A scrape configuration containing exactly one endpoint to scrape:
# Here it's Prometheus itself.
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:9100','k8s-node-1:9100']  #ターゲットを追加する
```

再びPrometheusのGUI画面から```Targets```をクリックすると、ターゲットが増えていることが確認できます。
![prometheus-binary-10.jpg](https://qiita-image-store.s3.amazonaws.com/0/177048/cea44dea-71e1-80a2-fca6-5b116616a4ac.jpeg)

### Grafanaの起動
ここまででPrometheusからメトリクスを確認することができました。しかし画面を見ていただくとわかるように、**かなり寂しい、そして見にくい**です。そこで可視化ツールとしてGrafanaを起動します。
Grafanaの利用方法についても、[Prometheusの公式ページで紹介されています](https://prometheus.io/docs/visualization/grafana/)。やはりセットで使われることが想定されているようです。
起動方法はこれまでと同様ですが、別の記事ではsystemctlから起動していたので、そちらを採用しました。

```
[root@k8s-master ~]# wget https://dl.grafana.com/oss/release/grafana-5.4.2-1.x86_64.rpm
[root@k8s-master ~]# yum localinstall -y grafana-5.4.2-1.x86_64.rpm
[root@k8s-master ~]# systemctl start grafana-server
[root@k8s-master ~]# systemctl status grafana-server
```

statusを確認すると、以下のようにちゃんと起動しているのがわかります。

```
● grafana-server.service - Grafana instance
   Loaded: loaded (/usr/lib/systemd/system/grafana-server.service; disabled; vendor preset: disabled)
   Active: active (running) since Fri 2019-01-04 04:29:21 UTC; 8s ago
     Docs: http://docs.grafana.org
 Main PID: 2830 (grafana-server)
    Tasks: 11
   Memory: 18.5M
   CGroup: /system.slice/grafana-server.service
           └─2830 /usr/sbin/grafana-server --config=/etc/grafana/grafana.ini --pidfile=/var/run/grafana/grafana-server.pid --packaging=rpm cfg:defaul...

Jan 04 04:29:21 k8s-master grafana-server[2830]: t=2019-01-04T04:29:21+0000 lvl=info msg="Initializing CleanUpService" logger=server
Jan 04 04:29:21 k8s-master grafana-server[2830]: t=2019-01-04T04:29:21+0000 lvl=info msg="Initializing NotificationService" logger=server
Jan 04 04:29:21 k8s-master grafana-server[2830]: t=2019-01-04T04:29:21+0000 lvl=info msg="Initializing ProvisioningService" logger=server
Jan 04 04:29:21 k8s-master grafana-server[2830]: t=2019-01-04T04:29:21+0000 lvl=info msg="Initializing PluginManager" logger=server
Jan 04 04:29:21 k8s-master grafana-server[2830]: t=2019-01-04T04:29:21+0000 lvl=info msg="Starting plugin search" logger=plugins
Jan 04 04:29:21 k8s-master systemd[1]: Started Grafana instance.
Jan 04 04:29:21 k8s-master grafana-server[2830]: t=2019-01-04T04:29:21+0000 lvl=info msg="Plugin dir created" logger=plugins dir=/var/lib/gra.../plugins
Jan 04 04:29:21 k8s-master grafana-server[2830]: t=2019-01-04T04:29:21+0000 lvl=info msg="Initializing TracingService" logger=server
Jan 04 04:29:21 k8s-master grafana-server[2830]: t=2019-01-04T04:29:21+0000 lvl=info msg="Initializing Stream Manager"
Jan 04 04:29:21 k8s-master grafana-server[2830]: t=2019-01-04T04:29:21+0000 lvl=info msg="HTTP Server Listen" logger=http.server address=0.0.... socket=
Hint: Some lines were ellipsized, use -l to show in full.
```

GUI画面から```http://<k8s-masterのプライベートIPアドレス:3000>```にアクセスします。以下のような画面が表示されることがあるのでしばらく待ちます。
![prometheus-binary-11.jpg](https://qiita-image-store.s3.amazonaws.com/0/177048/fa9dc2ae-e371-35c2-2b6b-1182df0cc107.jpeg)

ログイン画面が表示されます。初期ログインのID/PWは```admin/admin```です。すでにPrometheusの時より画面が美しいですね!
![prometheus-binary-14.jpg](https://qiita-image-store.s3.amazonaws.com/0/177048/556c0bc0-a879-23f1-a9ce-4179aa7a1011.jpeg)

入力して次へ進むとパスワードの変更を求められます。
![prometheus-binary-15.jpg](https://qiita-image-store.s3.amazonaws.com/0/177048/20e46a8b-e229-c9b5-cb61-70cef199273e.jpeg)

入力後は以下のような画面が表示されます。
![prometheus-binary-16.jpg](https://qiita-image-store.s3.amazonaws.com/0/177048/4a06e79c-be24-3d51-1cd0-40697a032afa.jpeg)

### Prometheus Dashboardの準備
ここからPrometheusのDashboardを準備します。
画面左側の```Configuration```から```Data Sources```を選択します。
![prometheus-binary-17.jpg](https://qiita-image-store.s3.amazonaws.com/0/177048/258ec370-0a2a-801e-f47b-a5924807c69c.jpeg)

以下のような画面が表示されるので、中央にある```Add data source```をクリックします。
![prometheus-binary-18.jpg](https://qiita-image-store.s3.amazonaws.com/0/177048/346d86a6-d47b-c4c5-f2d1-c5e94018bd44.jpeg)

続いてData sourceのタイプを選択します。ここでは```Prometheus```を選択します。
![prometheus-binary-19.jpg](https://qiita-image-store.s3.amazonaws.com/0/177048/1f66aa98-1ad1-c26d-9f5b-1e52f295abae.jpeg)

Settings画面が表示されたら、必要な箇所を入力します。ここでは```URL```,```Scrape Interval```,```Query timeout```を入力しました。
![prometheus-binary-20.jpg](https://qiita-image-store.s3.amazonaws.com/0/177048/9288e3c6-0316-9b1b-4c6c-7b7b5ec7ad59.jpeg)

入力後、```Save & Test```をクリックすると、接続テスト?が行われ、正常に作動した場合は以下のように表示されます。
![prometheus-binary-21.jpg](https://qiita-image-store.s3.amazonaws.com/0/177048/40415e8f-370b-4a90-4723-2b326f7e31f0.jpeg)

続いて、同画面の別タブである```Dashboards```に移動します。表示された```Import```を全てクリックし、有効にします。
![prometheus-binary-23.jpg](https://qiita-image-store.s3.amazonaws.com/0/177048/880d04e4-da09-57b6-7496-5118c63d1623.jpeg)
![prometheus-binary-24.jpg](https://qiita-image-store.s3.amazonaws.com/0/177048/c5cf0331-ec18-3da8-01c3-d4f047655bb1.jpeg)

その後、```Configuration```→```Dashboards```→```Home```をクリックし、表示された中からImportしたDashboardsを選択します。ここでは```Prometheus Stats```を選択します。すると以下のようにDashboardが表示されます。
![prometheus-binary-25.jpg](https://qiita-image-store.s3.amazonaws.com/0/177048/f4bdc443-dac3-b3d3-4b21-ce7d7e5adbab.jpeg)

正しく読み込めていないように見えますが、ここでは一旦無視して、新規でグラフを作成します。画面上部から```Add panel```を選択します。
![prometheus-binary-26.jpg](https://qiita-image-store.s3.amazonaws.com/0/177048/f7e777e2-34c9-7154-9a30-fea8250d5933.jpeg)

次に```Graph```を選択します。
![prometheus-binary-27.jpg](https://qiita-image-store.s3.amazonaws.com/0/177048/0d9868e1-3bb4-a2b7-37c0-5104f9addd53.jpeg)

グラフ上部の```Panel Title```あたりをクリックすると、メニューが表示されるので、```Edit```を選択します。
![prometheus-binary-28.jpg](https://qiita-image-store.s3.amazonaws.com/0/177048/ba3f7350-3b5a-9fcb-fed0-bd08ae663669.jpeg)

すると以下のような画面が表示されます。ここでグラフごとの設定を決めていきます。取得するメトリクスもここから入力します。
![prometheus-binary-29.jpg](https://qiita-image-store.s3.amazonaws.com/0/177048/0260025b-8805-f341-9107-46876eba4371.jpeg)

まずメトリクスを入力します。```Metrics```→```default```の画面の入力欄に取得するメトリクスを入力します。ここでは試しに```node_memory_Active_file_bytes```を入力しました。すると早速グラフが表示されます。
![prometheus-binary-30.jpg](https://qiita-image-store.s3.amazonaws.com/0/177048/1d7d9fe9-a2d2-203a-8739-7ea250e9d900.jpeg)

あとはグラフのタイトルや細かな設定等を変更すればグラフの完成です。

ここで先ほどN/Aと表示されていたグラフを見てみます。ここでは```Uptimes```のグラフを選択しました。
![prometheus-binary-31.jpg](https://qiita-image-store.s3.amazonaws.com/0/177048/b16b9d81-cac9-724b-8613-77920a2869f9.jpeg)

メトリクスの箇所を見ると、ノードの名前(ここではinstanceと表記された箇所)が変数となっています。この部分がうまくいかず、メトリクスを取得できなかったようです。
試しに```localhost:9100```と入力すると、ちゃんとグラフに表示されます。
![prometheus-binary-32.jpg](https://qiita-image-store.s3.amazonaws.com/0/177048/ec1a8344-ada6-fc78-3d37-bc04cf722a82.jpeg)

【追記】[こちらの記事で説明されていました](https://qiita.com/miyacomaru/items/6fa4121e7ba765e9efd6)が、どうやらcAdvisorを取得できていないために正しくグラフが表示されなかったようです。

ここまでがBinaryファイルからPrometheus + Grafanaを起動する方法でした。

## yamlファイルを作成してデプロイ
続いてyamlファイルを作成してPrometheus + Grafanaをデプロイする方法を紹介します。

### Prometheusのデプロイ
Prometheusをデプロイするための各種yamlファイルを作成します。作成手順は[こちらを参考にしました](https://devopscube.com/setup-prometheus-monitoring-on-kubernetes/)。

ここでは4種類のyamlファイルを作成します。

#### ClusterRole, ClusterRoleBinding
~~※上記記事を参考に作成したためClusterRole, ClusterRoleBindingを作成しましたが、記事内ではGKE環境を想定しており、今回は必要ないものと思われます。~~

```clusterRole.yml
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
  name: prometheus
rules:
- apiGroups: [""]
  resources:
  - nodes
  - nodes/proxy
  - services
  - endpoints
  - pods
  verbs: ["get", "list", "watch"]
- apiGroups:
  - extensions
  resources:
  - ingresses
  verbs: ["get", "list", "watch"]
- nonResourceURLs: ["/metrics"]
  verbs: ["get"]
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
  name: prometheus
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: prometheus
subjects:
- kind: ServiceAccount
  name: default
  namespace: monitoring
```

#### ConfigMap
Binaryから起動する際には```prometheus.yml```を編集して設定を変更しました。yamlファイルから起動する際にもこれを利用しますが、幾つか指定する方法があるようです。

* ConfigMapで利用するデータを書き込む
* Deploymentで```args```でconfigファイルを指定する

今回はConfigMapに利用するデータを書き込み指定します。```data:```の箇所でファイルの内容を書き込みます。

```prometheus-configmap.yml
apiVersion: v1
kind: ConfigMap
metadata:
  name: prometheus-server-conf
  labels:
    name: prometheus-server-conf
  namespace: monitoring
data:
  prometheus.yml: |-
    # my global config
    global:
      scrape_interval:     15s # 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).

    # Alertmanager configuration
    alerting:
      alertmanagers:
      - static_configs:
        - targets:
          # - alertmanager:9093

    # Load rules once and periodically evaluate them according to the global 'evaluation_interval'.
    rule_files:
      # - "first_rules.yml"
      # - "second_rules.yml"

    # A scrape configuration containing exactly one endpoint to scrape:
    # Here it's Prometheus itself.
    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:9100','k8s-node-1:9100']
```

#### Deployment
このファイルでPrometheusを起動します。

```prometheus-deployment.yml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: prometheus-deployment
  namespace: monitoring
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: prometheus-server
    spec:
      containers:
        - name: prometheus
          image: prom/prometheus:latest
          # configfileで指定した場所には該当のファイルが存在しません。。。
          args:
            - "--config.file=/etc/prometheus/prometheus.yml"
            - "--storage.tsdb.path=/prometheus/"
          ports:
            - containerPort: 9090
```

#### Service
上記Deploymentファイルをデプロイしただけではアクセスができません。外部から接続できるようにします。[参考記事](https://devopscube.com/setup-prometheus-monitoring-on-kubernetes/)では2つの方法を紹介しています。

* kubectl port forwardingを利用する
* NodePort, LoadBalancer等を用いる

ここでは後者の方法を用います。NodePortによって外部からの接続を可能にします。接続するポートは30000番を指定しています。

```prometheus-service.yml
apiVersion: v1
kind: Service
metadata:
  name: prometheus-service
spec:
  selector: 
    app: prometheus-server
  type: NodePort
  ports:
    - port: 8080
      targetPort: 9090 
      nodePort: 30000
```

### 各種yamlファイルのデプロイ
それではデプロイします。まず監視用のnamespaceを作成します。

```
[root@k8s-master ~]# kubectl create namespace monitoring
namespace/monitoring created
[root@k8s-master ~]# kubectl get ns
NAME          STATUS   AGE
default       Active   11d
kube-public   Active   11d
kube-system   Active   11d
monitoring    Active   6s
[root@k8s-master ~]#
```

続いてClusterRoleのファイルをデプロイします。

```
[root@k8s-master ~]# kubectl create -f clusterRole.yml 
clusterrole.rbac.authorization.k8s.io/prometheus created
clusterrolebinding.rbac.authorization.k8s.io/prometheus created
[root@k8s-master ~]# 
[root@k8s-master ~]# kubectl get clusterrole prometheus -n monitoring
NAME         AGE
prometheus   13m
[root@k8s-master ~]# 
```

ConfigMapをデプロイします。

```
[root@k8s-master ~]# kubectl create -f prometheus-configmap.yml -n monitoring
configmap/prometheus-server-conf created
[root@k8s-master ~]# kubectl get configmap -n monitoring
NAME                     DATA   AGE
prometheus-server-conf   1      57s
[root@k8s-master ~]#
```

Deploymentファイルをデプロイします。

```
kubectl create -f prometheus-deployment.yml -n monitoring
deployment.extensions/prometheus-deployment created
[root@k8s-master ~]# kubectl get deployments -n monitoring
NAME                    READY   UP-TO-DATE   AVAILABLE   AGE
prometheus-deployment   1/1     1            1           16s
[root@k8s-master ~]#
```

最後にServiceファイルをデプロイします。

```
[root@k8s-master ~]# kubectl create -f prometheus-service.yml -n monitoring
service/prometheus-service created
[root@k8s-master ~]# kubectl get svc -n monitoring
NAME                 TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
prometheus-service   NodePort   10.108.59.161   <none>        8080:30000/TCP   9s
[root@k8s-master ~]# 
```

これでGUIからアクセスすることができます。```http://<k8s-masterのグローバルIPアドレス:30000>```にアクセスすると、以下のようにアクセスできます。

![prometheus-yaml-1.jpg](https://qiita-image-store.s3.amazonaws.com/0/177048/fe3cae92-eb9b-980f-fc09-e971b435cd08.jpeg)

メトリクスを指定してグラフに表示することもできます。

![prometheus-yaml-2.jpg](https://qiita-image-store.s3.amazonaws.com/0/177048/98b6c242-1366-6a2c-0e73-d0efa038b449.jpeg)

### Grafanaのデプロイ
続いてGrafanaをデプロイします。先ほど作成したPrometheus用のDeployment, Serviceファイルをもとに、Grafana用のファイルを作成しました。変更したのは、名前とコンテナイメージの部分、あとはポート番号くらいです。

```grafana-deployment.yml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: grafana-deployment
  namespace: monitoring
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: grafana-server
    spec:
      containers:
        - name: grafana
          image: grafana/grafana:latest
          #args:
          #  - "--config.file=/root/prometheus.yml"
          #  - "--storage.tsdb.path=/prometheus/"
          ports:
            - containerPort: 3000
```

```grafana-service.yml
apiVersion: v1
kind: Service
metadata:
  name: grafana-service
spec:
  selector: 
    app: grafana-server
  type: NodePort
  ports:
    - port: 8100
      targetPort: 3000
      nodePort: 30020
```

ではデプロイします。

```
[root@k8s-master ~]# kubectl create -f grafana-deployment.yml -n monitoring
deployment.extensions/grafana-deployment created
[root@k8s-master ~]# kubectl get pods -n monitoring
NAME                                     READY   STATUS    RESTARTS   AGE
grafana-deployment-75d8d6dcc5-hkwt7      1/1     Running   0          11s
prometheus-deployment-5cc78d984f-b5pxw   1/1     Running   0          10m
[root@k8s-master ~]# kubectl create -f grafana-service.yml -n monitoring
service/grafana-service created
[root@k8s-master ~]# kubectl get svc -n monitoring
NAME                 TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
grafana-service      NodePort   10.102.56.76    <none>        8100:30020/TCP   11s
prometheus-service   NodePort   10.102.96.204   <none>        8080:30000/TCP   11m
[root@k8s-master ~]#
```

これでGrafanaも使えるので、GUIから```http://<k8s-masterのグローバルIPアドレス:30020>```にアクセスします。ログイン画面から同様に設定すると、以下のようにDashboardが表示されるようになりました。

![prometheus-yaml-3.jpg](https://qiita-image-store.s3.amazonaws.com/0/177048/ff437e08-e9e5-6b0c-3eae-6f7ac7124892.jpeg)

# まとめ・感想

* binary: 公式ページが推奨?している手順だけあって、非常に簡単に起動ができます。設定ファイルも比較的わかりやすく、ターゲットの追加も簡単です。
* yaml: yamlファイルの準備ができさえすればとても簡単にできますが、yamlファイルの準備がとても大変です。

本当はyamlファイルでもNode Exporterを起動し、メトリクスの取得まで実施したかったのですが、書き方が間違っているのかうまくいきませんでした(デプロイはできましたが、結局メトリクスを取得できませんでした)。yamlファイルの書き方も含め、引き続き調べていきます。
個人的にはbinaryから実行する方がやりやすく感じたのですが、柔軟性やコンフィグの管理などを考えるとyamlからデプロイの方が都合が良さそうです。

# 参考リンク
[prometheus のデータを grafana でグラフ表示してみた](https://qiita.com/tukiyo3/items/da379f6e5844c99b65df)
[Prometheusのfile_sd_configsを試してみる](https://qiita.com/buncho/items/bce45fbbb5c5139df478)
[KubernetesのRBACについて](https://qiita.com/sheepland/items/67a5bb9b19d8686f389d)
[Kubernetesの全NodeをPrometheusで監視する方法](https://www.tmp1024.com/server/observe-kubernetes-all-nodes-of-prometheus)
[Prometheusをコンテナとして起動する方法](https://qiita.com/hana_shin/items/16a7ee88ef502a3fc0eb)