Prometheusでnasneを監視する

# はじめに

こんにちは、 ゼットラボ株式会社のエンジニアの @hatotaka です。今回は自宅nasneの監視について紹介したと思います。

# 解決したい課題

以下の課題を解決するために、自宅nasneを監視をすることにしました。

- nasneのディスクの容量が少なくなったら知りたい
- nasneの録画予約が重複したときに知りたい
- 自宅Kubernetesクラスタの有効活用
  - https://qiita.com/hatotaka/items/48a88ecb190e1f5e03c3

nasneを監視をするにPrometheusを選択しました。なぜPrometheusかというと、普段から業務で利用しているため、自宅でも利用することを選択しました。

# Prometheusとは?

[Prometheus](https://prometheus.io)とは、オープンソースのモニタリングシステムです。2012年からSoundCloudで開発され、現在は独立したオープンソースプロジェクトとして管理されています。2016年には[CNCF](https://www.cncf.io)に[Kubernetes](https://kubernetes.io)に続く2つめのプロジェクトとして参加しました。

Prometheusの特徴の一つとして、HTTP経由のpull型でのメトリクス収集というものがあります｡メトリクスの取得はPrometheusが行い、アプリケーション側はHTTPでPrometheusの形式のメトリクスを公開するだけでPrometheus対応を行えます。また､exporterと呼ばれるものもあり､Prometheusに対応してないソフトウェアであっても、そのソフトウェアに対応したexporterを用意すればソフトウェア固有のAPIから情報を取得し､Prometheus形式のメトリクスを出力することができます｡Promehtues公式ではMySQLやConsul､Memchached用のexporterが用意されています｡公式以外のexporterもあり､私が普段利用するようなソフトウェアは大体そろっています[^prometheus_exporters]。

公式や非公式のexporterが存在しない場合でもexporterを自身で実装すればPrometheus対応をすることができます｡exporterの実装は、クライアントライブラリを利用することで容易に行うことができます。Prometheusの公式では、Go、Java、Scala、Python、Rubyのライブラリが提供されています[^prometheus_client_libraries]。

# nasne_exporterについて

Prometheusを利用してnasneを監視するために [hatotaka/nasne_exporter](https://github.com/hatotaka/nasne_exporter)というexporterを開発しました。

## 構成

自宅の構成は以下の通りです。

![nasne_exporter.png](https://qiita-image-store.s3.amazonaws.com/0/100305/37b1defa-bbc3-efbb-0607-59f73582bdb7.png)

自宅Kubernetesで開発したnasne_exporter以外に、prometheusやalertmanagerを動作させています。alertmanagerの通知先はslackにしており、問題があるとスマートフォンに通知される仕組みとなっています。また、監視対象のnasneは3台あり、nasne_exporterで3台のnasneを監視しています。

## 実装方法について

開発言語はgolangを使っています。また、Prometheusの公式のクライアントライブラリである[prometheus/client_golang](https://github.com/prometheus/client_golang)を利用しています。exporterの実装方法の詳細については公式のドキュメント [WRITING EXPORTERS](https://prometheus.io/docs/instrumenting/writing_exporters/) や https://qiita.com/takuhiro/items/4630e003cebff1d6df02 を参照することをおすすめします。

nasne_exporterを実装するにはnasneの情報を取得する必要があります。しかし、nasneには公開されているAPIが存在しません。調べてみると、Web UIやトルネのUIを実現するために、多くのAPIが実装されていることがわかりました。

今回nasne_exporterを作成するために、[naokiy/node-nasne](https://github.com/naokiy/node-nasne)を参考にしたのと、nasne Web UIをChromeのデベロッパーツールで確認しながらどのようなAPIをたたいて情報を取得しているか確認しながら実装しました。

実装についての詳細な説明は省略します。興味のある方はコードを参照してもらえるとうれしいです。おかしなところがあればPR大歓迎です。


## 実行方法について

nasne_exporterの実行方法について説明します。dockerコンテナを公開しているので、dockerを使える環境であれば以下の手順で起動することができます。


```shell
$ docker run quay.io/hatotaka/nasne_exporter --nasne-addr 192.0.2.1 --nasne-addr 192.0.2.2
```

`--nasne-addr`ではnasneのIPアドレスを指定します。複数のnasneがある場合は、複数指定すれば1つのexporterで複数のnasneのメトリクスを取得することができます。上記の例では `192.0.2.1`と`192.0.2.2`の2つのnasneを指定しています。

起動後、以下のURLでメトリクスを見ることができます。

```
http://<実行した環境>:8080/metircs
```

その他のフラグ詳細については、以下のコマンドで確認してください。

```shell
$ docker run quay.io/hatotaka/nasne_exporter --help
```

## アラート条件について

私の自宅で設定しているアラート条件は以下の通りです。

ストレージの空き容量が20%を下回った場合にアラートする

```yaml
- alert: NasneHDDWillFull
  expr: sum(nasne_hdd_usage_bytes) by (name) / sum(nasne_hdd_size_bytes) by (name) > 0.8
  for: 5m
  annotations:
    summary: "Nasne {{ $labels.name }} becomes full."
    description: "Nasne ({{ $labels.name }}) hard disk space is less than 20%. (current value: usage/size = {{ $value }})"
```

録画予約が衝突した場合にアラートする

```yaml
- alert: NasneConflictReserved
  expr: nasne_reserved_conflict_titles > 0
  for: 5m
  annotations:
    summary: "Nasne {{ $labels.name }} conflict reserved."
    description: "Conflicts of recording reservation has occurred at {{ $labels.name }}. (current value: {{ $value }})"
```

それ以外にも以下のメトリクスを取得しているので、これらのメトリクスを利用したアラートも設定可能です。たとえば、接続されているクライアント数を`nasne_dtcpip_clients`で取得しているので、深夜に子供がnasneでテレビや録画した番組を見たときにアラートを受け取ると行ったことも実現可能です。

| メトリクス名 | メトリクスタイプ | ラベル | 説明 |
| --- | --- | --- | --- |
| `nasne_info` | Gauge | `hardware_version` `name` `product_name` `software_version` | nasne 情報 |
| `nasne_hdd_size_bytes` | Gauge | `format` `id` `name` `product_id` `vendor_id` | ハードディスクの容量 |
| `nasne_hdd_usage_bytes` | Gauge | `format` `id` `name` `product_id` `vendor_id` | ハードディスクの使用容量 |
| `nasne_dtcpip_clients` | Gauge | `name` | 接続されているDTCP-IPのクライアント数 |
| `nasne_recordings` | Gauge | `name` | 録画中の件数 |
| `nasne_recorded_titles` | Gauge | `name` | 録画されている件数 |
| `nasne_reserved_titles` | Gauge | `name` | 予約されている件数 |
| `nasne_reserved_conflict_titles` | Gauge | `name` | コンフリクトした録画件数 |
| `nasne_reserved_notfound_titles` | Gauge | `name` | 見つからない録画件数 |
| `nasne_last_collect_time` | Gauge | | 最後にメトリクスを収集した時間 |
| `nasne_collect_duration_seconds` | Histogram | `name` | メトリクス収集にかかった時間 |


# 最後に

以上のようにnasne_exporterを利用することでnasneを監視することができます。自宅Kubernetesクラスタで動かすアプリケーションがない方は試してみてはいかがでしょうか?

以下にサンプルのマニフェストがあるので参考にしていただけると幸いです。

- https://github.com/hatotaka/nasne_exporter/tree/master/examples/k8s

このエントリは、Z Lab Advent Calendar 2018 の15日目として業務時間中に書きました。nasne_exporterについては趣味で業務時間外に書きました。

[^prometheus_exporters]: https://prometheus.io/docs/instrumenting/exporters/
[^prometheus_client_libraries]: https://prometheus.io/docs/instrumenting/clientlibs/