MinikubeにPrometheusとGrafanaをHelmチャートでデプロイする

MinikubeでPrometheusとGrafanaをHelmでインストールして動かしてみる。

以下のHelmチャートを使ってインストールする。

- https://github.com/helm/charts/tree/master/stable/prometheus
- https://github.com/helm/charts/tree/master/stable/grafana

|コンポーネント|バージョン|
|---|---|
|Minikube|v0.33.1|
|Kubernetes|v1.13.2|
|Prometheusチャート|8.4.5|
|Prometheus|2.6.1|
|Grafanaチャート|1.25.1|
|Grafana|5.4.3|

## 準備

Minikubeを起動する。

```shell
minikube start
```

Minikubeで`ingress`のアドオンを有効にする。

```shell
minikube addons enable ingress
```

MinikubeのIPアドレスを確認する。

```shell
minikube ip
```

`/etc/hosts`にMinikubeのIPを追記する。各コンポーネントへのIngress経由でのアクセスをパスで分けようとすると、パスのリライトやリダイレクトの整合性をとるのが難しいので、仮想ホストを分けた方が楽。

```:/etc/hosts
192.168.99.106  alertmanager.minikube prometheus.minikube grafana.minikube
```

PrometheusとGrafanaをデプロイする先のNamespaceを作成する。

```shell
kubectl create ns monitoring
```

`helm`を初期化し、クラスターに`tiller`をデプロイする。

```shell
helm init
```

## Prometheus

`helm repo`コマンドで登録済みのレポジトリを確認する。

```shell-session
$ helm repo list
NAME          	URL
stable        	https://kubernetes-charts.storage.googleapis.com
local         	http://127.0.0.1:8879/charts
$
```

`helm search`コマンドでPrometheusのチャートを確認する。

```shell-session
$ helm search prometheus
NAME                                 	CHART VERSION	APP VERSION	DESCRIPTION
stable/prometheus                    	8.4.5        	2.6.1      	Prometheus is a monitoring system and time seri...
stable/prometheus-adapter            	v0.4.1       	v0.4.1     	A Helm chart for k8s prometheus adapter
stable/prometheus-blackbox-exporter  	0.2.0        	0.12.0     	Prometheus Blackbox Exporter
stable/prometheus-cloudwatch-exporter	0.2.1        	0.5.0      	A Helm chart for prometheus cloudwatch-exporter
stable/prometheus-consul-exporter    	0.1.2        	0.4.0      	A Helm chart for the Prometheus Consul Exporter
stable/prometheus-couchdb-exporter   	0.1.0        	1.0        	A Helm chart to export the metrics from couchdb...
stable/prometheus-mysql-exporter     	0.2.1        	v0.11.0    	A Helm chart for prometheus mysql exporter with...
stable/prometheus-node-exporter      	1.1.0        	0.17.0     	A Helm chart for prometheus node-exporter
stable/prometheus-operator           	1.8.0        	0.26.0     	Provides easy monitoring definitions for Kubern...
stable/prometheus-postgres-exporter  	0.6.1        	0.4.7      	A Helm chart for prometheus postgres-exporter
stable/prometheus-pushgateway        	0.3.0        	0.6.0      	A Helm chart for prometheus pushgateway
stable/prometheus-rabbitmq-exporter  	0.3.0        	v0.29.0    	Rabbitmq metrics exporter for prometheus
stable/prometheus-redis-exporter     	1.0.1        	0.25.0     	Prometheus exporter for Redis metrics
stable/prometheus-snmp-exporter      	0.0.1        	0.14.0     	Prometheus SNMP Exporter
stable/prometheus-to-sd              	0.1.1        	0.2.2      	Scrape metrics stored in prometheus format and ...
stable/elasticsearch-exporter        	1.0.0        	1.0.2      	Elasticsearch stats exporter for Prometheus
stable/helm-exporter                 	0.1.0        	0.1.0      	Exports helm release stats to prometheus
stable/karma                         	1.1.9        	v0.21      	A Helm chart for Karma - an UI for Prometheus A...
stable/stackdriver-exporter          	0.0.6        	0.6.0      	Stackdriver exporter for Prometheus
stable/weave-cloud                   	0.3.1        	1.1.0      	Weave Cloud is a add-on to Kubernetes which pro...
stable/kube-state-metrics            	0.13.0       	1.4.0      	Install kube-state-metrics to generate and expo...
stable/mariadb                       	5.5.0        	10.1.37    	Fast, reliable, scalable, and easy to use open-...
$
```

`helm inspect values`コマンドでパラメータのデフォルト値を表示させ、リダイレクトしてファイルに保存する。

```shell
helm inspect values stable/prometheus > prometheus-values.yaml
```

保存したファイルと、[チャートのREADME](https://github.com/helm/charts/blob/master/stable/prometheus/README.md)を参考に、設定値をカスタマイズする。デフォルト値を使うものは削除し、カスタマイズ部分だけを残す。今回は以下のようにした。

- storageClassを`standard`と指定
  - Minikubeではデフォルトで`storage-provisioner`と`default-storageclass`のアドオンが有効になっていて、storageClassを`standard`と指定することでPersistentVolumeを動的プロビジョニングさせることができる
- 性能情報の保管期間を12時間に指定
- pushgatewayは使わないので無効化
- alertmanagerとserver（Prometheus）にIngress経由でアクセスできるようにIngressを有効化し、それぞれの仮想ホストを指定

```yaml:prometheus-values.yaml
alertmanager:
  ingress:
    enabled: true
    hosts:
      - alertmanager.minikube
  persistentVolume:
    size: 1Gi
    storageClass: "standard"
server:
  ingress:
    enabled: true
    hosts:
      - prometheus.minikube
  persistentVolume:
    size: 1Gi
    storageClass: "standard"
  retention: "12h"
pushgateway:
  enabled: false

```

チャートをリリースする。

```shell-session
$ helm install --name prometheus --namespace monitoring -f prometheus-values.yaml stable/prometheus
NAME:   prometheus
LAST DEPLOYED: Fri Feb  1 18:49:48 2019
NAMESPACE: monitoring
STATUS: DEPLOYED

RESOURCES:
==> v1beta1/DaemonSet
NAME                      DESIRED  CURRENT  READY  UP-TO-DATE  AVAILABLE  NODE SELECTOR  AGE
prometheus-node-exporter  1        1        0      1           0          <none>         1s

==> v1beta1/Ingress
NAME                     HOSTS                  ADDRESS  PORTS  AGE
prometheus-alertmanager  alertmanager.minikube  80       1s
prometheus-server        prometheus.minikube    80       1s

==> v1/PersistentVolumeClaim
NAME                     STATUS  VOLUME                                    CAPACITY  ACCESS MODES  STORAGECLASS  AGE
prometheus-alertmanager  Bound   pvc-b68e41ef-2606-11e9-acbf-080027a3230f  1Gi       RWO           standard      1s
prometheus-server        Bound   pvc-b68ea305-2606-11e9-acbf-080027a3230f  1Gi       RWO           standard      1s

==> v1beta1/ClusterRole
NAME                           AGE
prometheus-kube-state-metrics  1s
prometheus-server              1s

==> v1beta1/ClusterRoleBinding
NAME                           AGE
prometheus-kube-state-metrics  1s
prometheus-server              1s

==> v1beta1/Deployment
NAME                           DESIRED  CURRENT  UP-TO-DATE  AVAILABLE  AGE
prometheus-alertmanager        1        1        1           0          1s
prometheus-kube-state-metrics  1        1        1           0          1s
prometheus-server              1        1        1           0          1s

==> v1/Pod(related)
NAME                                            READY  STATUS             RESTARTS  AGE
prometheus-node-exporter-tl47v                  0/1    ContainerCreating  0         1s
prometheus-alertmanager-77585bb469-9hggb        0/2    Pending            0         1s
prometheus-kube-state-metrics-68cfd7cbd9-4n7vr  0/1    Pending            0         1s
prometheus-server-5d8c6c-wv6fd                  0/2    Init:0/1           0         1s

==> v1/ConfigMap
NAME                     DATA  AGE
prometheus-alertmanager  1     1s
prometheus-server        3     1s

==> v1/ServiceAccount
NAME                           SECRETS  AGE
prometheus-alertmanager        1        1s
prometheus-kube-state-metrics  1        1s
prometheus-node-exporter       1        1s
prometheus-server              1        1s

==> v1/Service
NAME                           TYPE       CLUSTER-IP      EXTERNAL-IP  PORT(S)   AGE
prometheus-alertmanager        ClusterIP  10.106.187.167  <none>       80/TCP    1s
prometheus-kube-state-metrics  ClusterIP  None            <none>       80/TCP    1s
prometheus-node-exporter       ClusterIP  None            <none>       9100/TCP  1s
prometheus-server              ClusterIP  10.107.118.222  <none>       80/TCP    1s


NOTES:
The Prometheus server can be accessed via port 80 on the following DNS name from within your cluster:
prometheus-server.monitoring.svc.cluster.local

From outside the cluster, the server URL(s) are:
http://prometheus.minikube


The Prometheus alertmanager can be accessed via port 80 on the following DNS name from within your cluster:
prometheus-alertmanager.monitoring.svc.cluster.local

From outside the cluster, the alertmanager URL(s) are:
http://alertmanager.minikube



For more information on running Prometheus, visit:
https://prometheus.io/

$
```

PrometheusとAlertmanagerのそれぞれにアクセスできることを確認。

<img width="1008" alt="image.png" src="https://qiita-image-store.s3.amazonaws.com/0/86449/672ad327-ded1-d633-376a-c6c7ef9bc7ad.png">

<img width="1008" alt="image.png" src="https://qiita-image-store.s3.amazonaws.com/0/86449/f9f63067-5084-d9d8-d14e-efa9171d2933.png">

## Grafana

続いてGrafanaをインストールする。

`helm search`コマンドでGrafanaのチャートを確認する。

```shell-session
$ helm search grafana
NAME          	CHART VERSION	APP VERSION	DESCRIPTION
stable/grafana	1.25.1       	5.4.3      	The leading tool for querying and visualizing t...
$
```

Prometheusのときと同様に、パラメータのデフォルト値をファイルに保存する。

```shell
helm inspect values stable/grafana > grafana-values.yaml
```

保存したファイルと、[チャートのREADME](https://github.com/helm/charts/blob/master/stable/grafana/README.md)を参考に、設定値をカスタマイズする。今回は以下のようにした。

- Ingress経由でアクセスできるようにIngressを有効化し、仮想ホストを指定
- storageClassNameを指定してPersistentVolumeを動的プロビジョニングさせる

```yaml:grafana-values.yaml
ingress:
  enabled: true
  hosts:
    - grafana.minikube
persistence:
  enabled: true
  storageClassName: "standard"
  size: 1Gi
```

チャートをリリースする。

```shell-session
$ helm install --name grafana --namespace monitoring -f grafana-values.yaml stable/grafana
NAME:   grafana
LAST DEPLOYED: Fri Feb  1 18:53:42 2019
NAMESPACE: monitoring
STATUS: DEPLOYED

RESOURCES:
==> v1/Secret
NAME     TYPE    DATA  AGE
grafana  Opaque  3     0s

==> v1/ConfigMap
NAME     DATA  AGE
grafana  1     0s

==> v1/ServiceAccount
NAME     SECRETS  AGE
grafana  1        0s

==> v1beta1/RoleBinding
NAME     AGE
grafana  0s

==> v1beta1/PodSecurityPolicy
NAME     DATA   CAPS      SELINUX   RUNASUSER  FSGROUP   SUPGROUP  READONLYROOTFS  VOLUMES
grafana  false  RunAsAny  RunAsAny  RunAsAny   RunAsAny  false     configMap,emptyDir,projected,secret,downwardAPI,persistentVolumeClaim

==> v1/Pod(related)
NAME                      READY  STATUS    RESTARTS  AGE
grafana-65f656d6c4-227tr  0/1    Init:0/1  0         0s

==> v1/PersistentVolumeClaim
NAME     STATUS  VOLUME                                    CAPACITY  ACCESS MODES  STORAGECLASS  AGE
grafana  Bound   pvc-41e671a5-2607-11e9-acbf-080027a3230f  1Gi       RWO           standard      0s

==> v1/ClusterRole
NAME                 AGE
grafana-clusterrole  0s

==> v1/ClusterRoleBinding
NAME                        AGE
grafana-clusterrolebinding  0s

==> v1beta1/Role
NAME     AGE
grafana  0s

==> v1/Service
NAME     TYPE       CLUSTER-IP     EXTERNAL-IP  PORT(S)  AGE
grafana  ClusterIP  10.108.154.68  <none>       80/TCP   0s

==> v1beta2/Deployment
NAME     DESIRED  CURRENT  UP-TO-DATE  AVAILABLE  AGE
grafana  1        1        1           0          0s

==> v1beta1/Ingress
NAME     HOSTS             ADDRESS  PORTS  AGE
grafana  grafana.minikube  80       0s


NOTES:
1. Get your 'admin' user password by running:

   kubectl get secret --namespace monitoring grafana -o jsonpath="{.data.admin-password}" | base64 --decode ; echo

2. The Grafana server can be accessed via port 80 on the following DNS name from within your cluster:

   grafana.monitoring.svc.cluster.local

   From outside the cluster, the server URL(s) are:
     http://grafana.minikube


3. Login with the password from step 1 and the username: admin

$
```

Grafanaにアクセスできることを確認する。

<img width="1008" alt="image.png" src="https://qiita-image-store.s3.amazonaws.com/0/86449/922453fa-83f3-f953-35b3-272ea9235840.png">

チャートをリリースしたときのメッセージに出力されている通り、ログインパスワードは以下のコマンドで取得する。

```shell
kubectl get secret --namespace monitoring grafana -o jsonpath="{.data.admin-password}" | base64 --decode ; echo
```

## GrafanaとPrometheusの連携

Grafanaにログインしてデータソースを追加する。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/86449/09599e24-4670-4bf4-577a-31eb94ff0c50.png)

タイプはPrometheusを選択。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/86449/727769ec-841d-8bc5-d482-324127f493b8.png)

URLはクラスター内でアクセスするのでServiceの名前とポートを指定すればよく、`http://prometheus-server`を指定する。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/86449/8b441fb2-51fe-d849-a047-d32be5eaebcc.png)

データソースが追加できたら今度はダッシュボードを追加する。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/86449/cde52bf4-b085-93d9-9c21-83fd72f97ae5.png)

Graphのパネルを追加する。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/86449/94f6744d-d549-bb76-b935-396685da8ba0.png)

パネルのタイトルを右クリックしてメニューを開き、Editをクリックする。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/86449/db65b291-b066-ead8-673d-a4f679dabb04.png)

Metricsタブで、5分間で計測したPod毎のCPU使用率を表示する以下のクエリーを入力する。

```
sum(rate(container_cpu_usage_seconds_total{image!=""}[5m])) by (namespace, pod_name) * 100
```

凡例のフォーマットには以下を指定。

```
{{ namespace }}/{{ pod_name }}
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/86449/45e7f832-a612-b1cf-b1c7-ad07402e96e0.png)

Generalタブでパネルのタイトルを指定する。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/86449/f205f089-d2bf-6274-5e7e-8775842f6353.png)

Legendタブで凡例を右にテーブルで表示するようにチェックを入れる。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/86449/811de9ca-4577-de7d-ae54-68cc6708c7e3.png)

右にある「×」ボタンを押して編集パネルを閉じ、パネルの右下をドラッグしてサイズを調整する。

メモリーのパネルも同様に以下のクエリーを指定して追加し、以下のようなダッシュボードが完成。

```
sum(container_memory_usage_bytes{image!=""}) by (namespace, pod_name)
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/86449/43dc9e0e-7572-86fb-d45f-05771cc1173e.png)