Prometheusをコンテナとして起動する方法

#1. Prometheusとは?
監視ツールです。
ここでは、Prometheusをコンテナとして起動してみます。


#2. Prometheusの構成
PrometheusはprometheusプロセスとExporterと呼ばれるプロセスから構成されています。
なお、以下の図のHOSTは、仮想マシンや実マシンを表します。

```console:プロセス構成
  +--- Host ---+
  |            |              +---------- Host -----------+
  |            |<------------ | Exporter(node_exporter)   |
  | prometheus |              +---------------------------+
  |     A      |
  |     |      |              +---------- Host -----------+
  |     |      |<------------ | Exporter(mysqld_exporter) |
  +-----|------+              +---------------------------+
        |
  +------------+
  | web browser|
  +------------+
```
・prometheusはExporterに対して情報を要求するプロセスです。
・Exporterは情報を収集して、収集した情報をprometheusに送信するプロセスです。
Exporterには、メモリ、ディスクアクセス状況の収集を目的したExporter(node_exporter)や、
Databasesに特化したExporter(mysqld_exporter)等、様々な種類があります。

なお、Exporterの一覧は以下を参照してください。
https://prometheus.io/docs/instrumenting/exporters/



#3. node_exporterを使ったホストの監視
ホストのメモリ,ディスクのアクセス状況を監視するため、node_exporterというExporterを使います。

##3.1 環境

```console:OS版数
master1,master2は仮想マシンです。OSはCentOS7.2です。
なお、master1,master2はホスト名です。
```

```console:使用するポート番号
ポート番号はそれぞれ以下のとおりです。
  - prometheus:9090
  - node_exporter:9100
```

```console:ネットワーク構成
                  +-------- master1 ---------+    +-------- master2 ---------+
                  |                          |    |                          |
 +-------------+  | +----------+  +--------+ |    |  +--------+              |
 | web browser |  | |prometheus|  |  node  | |    |  |  node  |              |
 +-------------+  | |          |  |exporter| |    |  |exporter|              |
        A         | +-- 9090 --+  +- 9100 -+ |    |  +- 9100 -+              |
        |         |   A   A A         A      |    |      A                   |
        |         |   |   | |         |      |    |      |                   |
        |         |   |   | +---------+      |    |      |                   |
        |         |   |   |                  |    |      |                   |
        |         |   |   |                  |    |      |                   |
        |         |   |   |                  |    |      |                   |
        |         +---|---|-- eth0 ----------+    +------|--- eth0 ----------+
        |             |   |    | .10                     |     | .20
        |             |   |    |                         |     |
        +-------------+   +------------------------------+     |
                               |                               |
    ---------------------------+-------------------------------+--------------
                                       192.168.0.0/24
```


##3.2 コンテナ(node_exporter)の起動手順

```console:master1でnode_exporterの起動
master1でコンテナ(node_exporter)を起動する。
[root@master1 ~]# docker run -d -p 9100:9100 --net="host" prom/node-exporter
310a1ef0c0e8ed17dbc6b0a843b9a97bd5a58d6fd0690c2f62bd196b3048fc1f

コンテナの状態を確認する。
[root@master1 ~]# docker ps
CONTAINER ID        IMAGE                COMMAND                CREATED             STATUS              PORTS               NAMES
310a1ef0c0e8        prom/node-exporter   "/bin/node_exporter"   26 seconds ago      Up 7 seconds                            ecstatic_lamarr
```

```console:master2でnode_exporterの起動
master2でコンテナ(node_exporter)を起動する。
[root@master2 ~]# docker run -d -p 9100:9100 --net="host" prom/node-exporter
65801b8c1c5eba173c9a21680eb9820ba54e59134f69283c7c2a9e85e83e6638

コンテナの状態を確認する。
[root@master2 ~]# docker ps
CONTAINER ID        IMAGE                COMMAND                CREATED             STATUS              PORTS               NAMES
65801b8c1c5e        prom/node-exporter   "/bin/node_exporter"   28 seconds ago      Up 22 seconds                           grave_ride
```


編集箇所はtargetsの2行(下記★印)のみ。
node_exporterが動作しているホストのIPアドレスを指定しました。

```console:定義ファイルの編集
定義ファイルをダウンロードする。
[root@master1 ~]# cd /tmp/
[root@master1 tmp]# wget https://raw.githubusercontent.com/prometheus/prometheus/master/documentation/examples/prometheus.yml

ファイルを確認する。
[root@master1 tmp]# ls prometheus.yml
prometheus.yml

定義ファイル(prometheus.yml)を編集する。
編集箇所はtargetsの2行(下記★印)のみ。node_exporterが動作しているホストのIPアドレスを指定する。
[root@master1 tmp]# vi prometheus.yml
[root@master1 tmp]# cat 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).

  # Attach these labels to any time series or alerts when communicating with
  # external systems (federation, remote storage, Alertmanager).
  external_labels:
      monitor: 'codelab-monitor'

# Load rules once and periodically evaluate them according to the global 'evaluation_interval'.
rule_files:
  # - "first.rules"
  # - "second.rules"

# 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: ['192.168.0.10:9100'] ★
      - targets: ['192.168.0.20:9100'] ★
```

```console:prometheusの起動
[root@master1 tmp]# docker run -d -p 9090:9090 -v /tmp/prometheus.yml:/etc/prometheus/prometheus.yml prom/prometheus
3190e11e8c7af01e8f8785fa1787ee38d5e2d04433a5bd5c5a160d17cab4a208
```


##3.3 動作確認

master1のprometheusにアクセスしてみます。ブラウザで下記URLにアクセスします。
http://192.168.0.10:9090
![prometheus.png](https://qiita-image-store.s3.amazonaws.com/0/146813/a8e84c53-0e66-f323-2dcb-c4f10e653a50.png)

master1,master2の状態。master2はシャットダウンしたので、Stateが"DOWN"になっている。
![prometheus-status.png](https://qiita-image-store.s3.amazonaws.com/0/146813/2130c4b1-ccf7-3aff-d4a5-c9d254184462.png)



#4 Kubernetes,etcdの監視
ここでは、node-exporterに加え、kubernetes,etcdの監視項目の追加手順を説明します。
kubernetes,etcdはprometheusに対する情報収集のインタフェースを持っているため、
kubernetes,etcdに対するExporterは不要です。


##4.1 環境

```console:OS版数
master1,master2は仮想マシン。OSはCentOS7.2です。
なお、master1,master2はホスト名です。
```

```console:使用するポート番号
使用するポート番号はそれぞれ以下のとおりです。
  - prometheus:9090
  - node_exporter:9100
  - kube-proxy:30900
     => kube-proxyがiptablesに対してDNAT(宛先ポート番号を30900から9090に変換)を設定する。
```

master1がマスタ、master2がノードとして機能します。
つまり、master1でkube-apiserverが動作しています。

```console:ネットワーク構成
                  +-------- master1 ---------+    +-------- master2 ---------+
                  |                          |    |                          |
 +-------------+  | +----------+  +--------+ |    |  +--------+              |
 | web browser |  | |prometheus|  |  node  | |    |  |  node  |              |
 +-------------+  | |          |  |exporter| |    |  |exporter|              |
        A         | +-- 9090 --+  +- 9100 -+ |    |  +- 9100 -+              |
        |         |   A   A A A       A      |    |      A                   |
        |         |   |   | | |       |      |    |      |                   |
        |         |   |   | | +-------+      |    |      |                   |
        |         |   |   | |                |    |      |                   |
        |         |   |   | |     +--------+ |    |      |                   |
        |         |   |   | +---> |  etcd  | |    |      |                   |
        |         |   |   |       +- 2379 -+ |    |      |                   |
        |         |   |   |                  |    |      |                   |
        |         | +----------+             |    |      |                   |
        |         | |kube-proxy|             |    |      |                   |
        |         | +-- 30900 -+             |    |      |                   |
        |         |   |   |                  |    |      |                   |
        |         +---|---|-- eth0 ----------+    +------|--- eth0 ----------+
        |             |   |    | .10                     |     | .20
        |             |   |    |                         |     |
        +-------------+   +------------------------------+     |
                               |                               |
    ---------------------------+-------------------------------+--------------
                                       192.168.0.0/24
```



##4.2 インストール手順
master1で実行します。インストール手順は、下記記事を参考にしました。
https://coreos.com/blog/prometheus-and-kubernetes-up-and-running.html


```console:ファイルのダウンロード(全部で3つ)
configmapをダウンロードする。
[root@master1 prometheus]# wget https://coreos.com/assets/blog/promk8s/prometheus-configmap-1.yaml
-以下、略-

deploymentとserviceを定義したファイルをダウンロードする。
[root@master1 prometheus]# wget https://coreos.com/assets/blog/promk8s/prometheus-deployment.yaml
-以下、略-

node_exporterの定義ファイルをダウンロードする。
[root@master1 prometheus]# wget https://coreos.com/assets/blog/promk8s/node-exporter.yaml
-以下、略-

ダウンロードしたファイルを確認する。
[root@master1 prometheus]# ls
node-exporter.yaml  prometheus-configmap-1.yaml  prometheus-deployment.yaml
```


```console:定義ファイル(prometheus-deployment.yaml)の編集
nodeSelectorを使って、prometheusがmaster1で動くようにする。
各ホストのラベルを表示する。master1は"kubernetes.io/hostname=master1"であることがわかる。
[root@master1 prometheus]# kubectl get node --show-labels
NAME      STATUS    AGE       LABELS
master1   Ready     2h        kubernetes.io/hostname=master1
master2   Ready     2h        kubernetes.io/hostname=master2

nodeSelectorを追加する（下記"新規追加"の部分)
[root@master1 prometheus]# vi prometheus-deployment.yaml
-中略-
    spec:
      containers:
      - name: prometheus
        image: quay.io/coreos/prometheus:0.19.2
        args:
          - '-storage.local.retention=6h'
          - '-storage.local.memory-chunks=500000'
          - '-config.file=/etc/prometheus/prometheus.yml'
        ports:
        - name: web
          containerPort: 9090
        volumeMounts:
        - name: config-volume
          mountPath: /etc/prometheus
      nodeSelector:                      #新規追加
        kubernetes.io/hostname: master1  #新規追加
      volumes:
      - name: config-volume
        configMap:
          name: prometheus
-以下、略-
```


```console:定義ファイル(prometheus-configmap-1.yaml)の編集
configmapファイルを編集する。
[root@master1 prometheus]# vi prometheus-configmap-1.yaml

    - job_name: 'etcd'
      target_groups:
      - targets:
        - 192.168.0.10:2379      #変更 (172.17.4.51:2379 => 192.168.0.10:2379)

    - job_name: 'node_exporter'  #新規追加
      target_groups:             #新規追加
      - targets:                 #新規追加
        - 192.168.0.10:9100      #新規追加
        - 192.168.0.20:9100      #新規追加

    - job_name: 'kubernetes_components'
      kubernetes_sd_configs:
```

```console:configmapリソースの作成
configmapリソースを作成する。
[root@master1 prometheus]# kubectl create -f prometheus-configmap-1.yaml
configmap "prometheus" created

作成したリソースを確認する。
[root@master1 prometheus]# kubectl get configmap
NAME         DATA      AGE
prometheus   1         12s
```

```console:deployment,serviceリソースの作成
deploymentとserviceリソースを作成する。
[root@master1 prometheus]# kubectl create -f prometheus-deployment.yaml
You have exposed your service on an external port on all nodes in your
cluster.  If you want to expose this service to the external internet, you may
need to set up firewall rules for the service port(s) (tcp:30900) to serve traffic.

See http://releases.k8s.io/release-1.2/docs/user-guide/services-firewalls.md for more details.
service "prometheus" created
deployment "prometheus" created

作成したdeploymentを確認する。"prometheus"というdeploymentが作成されたことがわかる。
[root@master1 prometheus]# kubectl get deployment
NAME         DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
prometheus   1         1         1            1           24s

作成したserviceを確認する。"prometheus"というserviceが作成されたことがわかる。
[root@master1 prometheus]# kubectl get svc
NAME         CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
kubernetes   10.254.0.1      <none>        443/TCP    1d
prometheus   10.254.149.17   nodes         9090/TCP   32s
```


```console:node-exporter用のservice,daemonsetリソース作成
serviceとdaemonsetリソースを作成する。
[root@master1 prometheus]# kubectl create -f node-exporter.yaml
service "node-exporter" created
daemonset "node-exporter" created

作成したserviceを確認する。"node-exporter"というserviceが作成されたことがわかる。
[root@master1 prometheus]# kubectl get svc
NAME            CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
kubernetes      10.254.0.1      <none>        443/TCP    1d
node-exporter   None            <none>        9100/TCP   1m
prometheus      10.254.149.17   nodes         9090/TCP   3m

作成したdaemonsetを確認する。"node-exporter"というserviceが作成されたことがわかる。
[root@master1 prometheus]# kubectl get daemonset
NAME            DESIRED   CURRENT   NODE-SELECTOR   AGE
node-exporter   1         1         <none>          48s
```


```console:実行結果の確認(podの状態確認)
master1、master2でnode_exporterが動作していることがわかる。
[root@master1 prometheus]# kubectl get pod -o wide
NAME                          READY     STATUS    RESTARTS   AGE       NODE
node-exporter-6hh05           1/1       Running   0          47s       master2
node-exporter-w66rw           1/1       Running   0          1h        master1
prometheus-1189099554-6xt11   1/1       Running   1          1h        master1
```

```console:TCPポート番号の確認
kube-proxyのポート番号を確認する。
[root@master1 prometheus]# lsof -i:30900
COMMAND    PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
kube-prox 1024 root    7u  IPv6  26028      0t0  TCP *:30900 (LISTEN)

node_exporterのポート番号を確認する。
[root@master1 prometheus]# lsof -i:9100
COMMAND    PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
node_expo 2444 root    3u  IPv6  32252      0t0  TCP *:jetdirect (LISTEN)

etcdのポート番号を確認する。
[root@master1 prometheus]# lsof -i:2379
COMMAND    PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
etcd      1027 etcd    7u  IPv6  20991      0t0  TCP *:2379 (LISTEN)
```


##4.3 動作確認
master1のprometheusにアクセスしてみます。ブラウザで下記URLにアクセスします。
http://192.168.0.10:30900
![prometheus_kubernetes_etcd.png](https://qiita-image-store.s3.amazonaws.com/0/146813/ed022258-9b60-3c07-9b1c-20c8016d99ba.png)

30900はkube-proxyがListenしているTCPポート番号です。
kube-proxyは30900番ポート宛てのパケットを受信すると、宛先ポート番号を9090に変換(DNAT)します。
そして宛先ポート番号9090のパケットをprometheusプロセスに転送します。


##4.4 課題

(1) kube-apiserverの情報が表示できない。
etcdとnode_exporterの情報は表示できている。
たぶん、kube-apiserverに対するhttpsアクセスが正しく設定できていないためだと思われる（調査中）。



#5.参考情報
[Prometheus](https://github.com/prometheus/prometheus)
[node_exporter](https://github.com/prometheus/node_exporter)
[Prometheus and Kubernetes up and running](https://coreos.com/blog/prometheus-and-kubernetes-up-and-running.html)