HeapsterでKubernetesを使わないDockerコンテナのリソース監視

# はじめに

[前回](http://qiita.com/atskimura/items/4c4aaaaa554e2814e938)、cAdvisorのInfluxDB連携機能を試しましたが、やはりHeapsterも試してみます。
前回はcAdvisorが直接InfluxDBにデータを入れたが、Heapsterを使う場合、HeapsterがcAdvisorのAPIを呼び、HeapsterがInfluxDBにデータを入れるという形になる。

そのため、Heapsterは監視対象のサーバーを知っている必要がある。ドキュメントには書かれていないが、ソースを見るとこの方法は３つ用意されている。

- Kubernetesから取得
- CoreOSのFleetから取得
- 設定ファイルから取得

今回はKubernetesもCoreOSも使わない環境を想定しているので、3番目の設定ファイルから取得を試してみる。Kubernetesを使わないのにHeapsterを使う需要はないかもしれませんが…

※なお、これも3月中旬に試した時の内容です。

# 設定ファイルから取得する設定を調べる

ドキュメントには設定方法は記載されていないのでソースを読む。

`external_hosts_file`オプションで指定したファイルにホストリストを設定する。デフォルトは`/var/run/heapster/hosts`である。設定ファイルはJSONで、構造は`ExternalNodeList`型で定義されている。（[sources/nodes/external.go#L48](https://github.com/GoogleCloudPlatform/heapster/blob/6f4f4d7ac6fe6c8ad52b6f3838929591dc00e946/sources/nodes/external.go#L40)）
設定ファイルでの設定を有効にするには、`kubernetes_master`および`coreos`オプションに何も指定しなければよい。（[sources/types.go#L34](https://github.com/GoogleCloudPlatform/heapster/blob/3f281aca7c3f2ad57019b72b164c69660b4f053a/sources/types.go#L34)、[sources/kube.go#L40](https://github.com/GoogleCloudPlatform/heapster/blob/cf13bf4e0a519c2e7cb4ffd866d06a303f435ce5/sources/kube.go#L40)）

以下がExternalNodeList型（[sources/api/types.go#L53](https://github.com/GoogleCloudPlatform/heapster/blob/6f4f4d7ac6fe6c8ad52b6f3838929591dc00e946/sources/api/types.go#L53)）

```go
// An external node represents a host which is running cadvisor. Heapster will expect
// data in this format via its external files API.
type ExternalNode struct {
	Name string `json:"name,omitempty"`
	IP   string `json:"ip,omitempty"`
}

// ExternalNodeList represents a list of all hosts that are running cadvisor which heapster will monitor.
type ExternalNodeList struct {
	Items []ExternalNode `json:"items,omitempty"`
}
```

つまり、以下のようなJSONファイルにすればよい。
参考：[Goのjson.Marshal/Unmarshalの仕様を整理してみる - I Will Survive](http://blog.restartr.com/2014/08/13/golang-json-marshal-unmarshal/)

```json
{
  "items": [
    {"name":"hostA", "ip":"x.x.x.x"},
    {"name":"hostB", "ip":"x.x.x.x"}
  ]
}
```

# Heapsterセットアップ手順

設定方法がわかったので、前回と同じ3台構成でセットアップしていく。

1. **Heapster**, influxDB, Grafana
2. Dockerホスト、cAdvisor（2台）

[前回](http://qiita.com/atskimura/items/4c4aaaaa554e2814e938)の記事で作った環境を下敷きにしているので、細かいところは前回の記事を参照してください。

## cAdvisorの起動方法を変更

先にcAdvisorの設定を変更して、InfluxDBと連携しないようにします。
前のcAdvisorコンテナは停止してください。
その後、新しくオプションを変更してcAdvisorを起動します。

```console
$ sudo docker run \
  --volume=/:/rootfs:ro \
  --volume=/var/run:/var/run:rw \
  --volume=/sys:/sys:ro \
  --volume=/var/lib/docker/:/var/lib/docker:ro \
  --publish=8080:8080 \
  --detach=true \
  --name=cadvisor \
  --privileged \
  google/cadvisor:latest \
  --log_dir=/
```

## Heapsterをインストール

Heapsterはインストールパッケージが提供されていません。Dockerコンテナはあるのですが、Dockerコンテナを監視するツールをDockerで動かしてもしょうがない気がするので、ソースからビルドしてみます。

### Goのインストール

インストール手順は[公式ドキュメント](http://golang.org/doc/install)の通りです。

[Downloads - The Go Programming Language](https://golang.org/dl/)から最新のパッケージのURLを確認して以下のようにコマンドを実行します。

```console
$ wget https://storage.googleapis.com/golang/go1.4.2.linux-amd64.tar.gz
$ sudo tar -C /usr/local -xzf go1.4.2.linux-amd64.tar.gz
```
`/etc/profile`に以下を書き加えてしまいます。

```bash
export PATH=$PATH:/usr/local/go/bin
```

`/etc/profile`を反映して、確認します。

```console
$ source /etc/profile
$ go version
go version go1.4.2 linux/amd64
```

`sudo`したときもPATHが通るようにしておきます。

```bash
$ sudo visudo
```

以下を追加し、

```
Defaults    env_keep +=  "PATH"
```

以下をコメントアウト

```
# Defaults    secure_path = /sbin:/bin:/usr/sbin:/usr/bin
```

### Godepのインストール

Heapsterはビルドにgodepを使っているので、godepを入れます。

```bash
$ sudo yum -y install git
$ cd /opt
$ sudo GOPATH=/opt/godep go get github.com/tools/godep
$ sudo ln -s /opt/godep/bin/godep /usr/local/bin/
```

### Heapsterのインストール

```
$ sudo yum -y install mercurial
$ sudo GOPATH=/opt/godep go get github.com/GoogleCloudPlatform/heapster
$ cd /opt/godep/src/github.com/GoogleCloudPlatform/heapster
$ sudo GOPATH=/opt/godep godep get
$ sudo ln -s /opt/godep/bin/heapster /usr/local/bin/
```

## Heapsterの設定

`/var/run/heapster/hosts`を設定します。

```bash
$ sudo mkdir /var/run/heapster
$ sudo /var/run/heapster/hosts
```

`/var/run/heapster/hosts`を設定します。
IPアドレスは環境に合わせて設定してください。

```json
{
  "items": [
    {"name":"cAdvisor1", "ip":"172.30.0.104"},
    {"name":"cAdvisor2", "ip":"172.30.0.105"}
  ]
}
```

## Heapster起動

Heapsterを起動する前に保存先のInfluxDBのデータベースを作成します。デフォルトは`k8s`というDB名なのでそれで作成してください。
作成したら、Heapsterを以下のコマンドで起動します。

```
$ sudo heapster --sink influxdb
```

InfluxDBをデフォルトで設定したままなら他の設定は不要ですが、必要に応じて設定してください。（[sinks/external.go#L28](https://github.com/GoogleCloudPlatform/heapster/blob/3ae30ba56a9358c8eba193bfb08e6c3636819c70/sinks/external.go#L28)）

| オプション | デフォルト値 | 説明 |
|:-----------|:------------|:------------|
| sink_influxdb_username | root | InfluxDB username |
| sink_influxdb_password | root | InfluxDB password |
| sink_influxdb_host | localhost:8086 | InfluxDB host:port |
| sink_influxdb_name | k8s | Influxdb database name |
| sink_influxdb_no_columns | false | When true, prefixes metric series names with metadata instead of storing metadata in additional columns. Metadata includes hostname, container name, etc. |

# 確認

## InfluxDBで確認

`k8s`データベースで`list series`を実行し、どんな`series`が作られているか確認します。

![スクリーンショット 2015-03-19 15.52.32.png](https://qiita-image-store.s3.amazonaws.com/0/27267/c498930e-3b4e-ce01-61db-826e853305ed.png)

以下のseriesが作成されていました。cAdvisorでは一つのseriesにカラムで分けられていましたが、Heapsterではseriesで分けて入れるようです。

- cpu/usage_ns_cumulative
- memory/page_faults_gauge
- memory/usage_bytes_gauge
- memory/working_set_bytes_gauge
- network/rx_bytes_cumulative
- network/rx_errors_cumulative
- network/tx_bytes_cumulative
- network/tx_errors_cumulative
- uptime_ms_cumulative

試しに`select * from "memory/usage_bytes_gauge" limit 10`と実行すると以下のようなデータが取得できます。

![スクリーンショット 2015-03-19 16.00.27.png](https://qiita-image-store.s3.amazonaws.com/0/27267/2fd6e287-9581-c95a-9d07-983bf8b2c2a4.png)

どのseriesでもカラムは同じです。わかりやすいです。

## Grafanaで確認

`/opt/grafana-1.9.1/config.js`に`k8s`データベースを追加します。

```
      datasources: {
        k8s: {
          type: 'influxdb',
          url: "http://<IPアドレス>:8086/db/k8s",
          username: 'root',
          password: 'root',
        },
        test: {
          type: 'influxdb',
          url: "http://<IPアドレス>:8086/db/test",
          username: 'root',
          password: 'root',
        },
        cadvisor: {
          type: 'influxdb',
          url: "http://<IPアドレス>:8086/db/cadvisor",
          username: 'root',
          password: 'root',
        },
        grafana: {
          type: 'influxdb',
          url: "http://<IPアドレス>:8086/db/grafana",
          username: 'root',
          password: 'root',
          grafanaDB: true
        },
      },
```

HeapsterのリポジトリにGrafana用のダッシュボード設定例があったので、これを読み込んでみます。
[grafana/kubernetes-dashboard.json](https://github.com/GoogleCloudPlatform/heapster/blob/337936b48fe88f2055c5887a98851313ae919c7d/grafana/kubernetes-dashboard.json)をダウンロードします。

![スクリーンショット 2015-03-19 16.03.52.png](https://qiita-image-store.s3.amazonaws.com/0/27267/f215df25-21ca-b6a7-9a98-8f7fc18fec61.png)

右上の「ファイルを開くアイコン」>「Import」からダウンロードしたJSONを選択すると、読み込まれ以下のように表示されます。

![スクリーンショット 2015-03-19 16.15.00.png](https://qiita-image-store.s3.amazonaws.com/0/27267/3206220b-371d-fe67-571f-d39db256b244.png)

例えばCPU usageの方は以下のような設定になっています。

![スクリーンショット 2015-03-19 16.17.51.png](https://qiita-image-store.s3.amazonaws.com/0/27267/3280dd54-09b2-6b3a-b5c2-efa6ebbbd656.png)

クエリは以下です。

```sql
select container_name, derivative(value) from "cpu/usage_ns_cumulative" where $timeFilter group by time($interval), container_name order asc
```

しかし、なんかCPU使用率がまともに表示されないと思ったら、変な値が入っています。累計のCPU使用時間のはずなのに3桁変わるレベルで変動しているし、減ったりしている。

![スクリーンショット 2015-03-19 22.26.53.png](https://qiita-image-store.s3.amazonaws.com/0/27267/d407f562-fcc6-1db7-b307-df279c53320c.png)

謎です。面倒なので深堀りはせずここで終わります。

# おわりに

当然なのかもしれませんが、KubernetesかCoreOSを使わない場合はHeapsterを使うメリットはないのではない気がします。前回のcAdvisorから直接InfluxDBに入れるのでよいと思います。

よかったら前回の記事もご覧ください。
[cAdvisor, InfluxDB, GrafanaでDockerコンテナのリソース監視 - Qiita](http://qiita.com/atskimura/items/4c4aaaaa554e2814e938)