Apache Kuduのexampleを使ったデータ生成

# はじめに
[Distributed computing (Apache Hadoop, Spark, ...) Advent Calendar 2016](http://qiita.com/advent-calendar/2016/distributed-computing)の20日目です。
Apache Kuduをインストールして、テーブルを作ってinsertやupdateを試してはみたけれど、の次のステップとしてStremっぽいテストデータの作成、クエリの実行とパフォーマンスの確認方法について見ていこうと思います。

Apache Kudu のコンポーネントや用語の説明については割愛しています。
適宜下記なども参照してください。
[Cloudera World Tokyo 2016 での発表資料](http://www.slideshare.net/Cloudera_jp/cwt2016-apache-kudu)
[Apache Kuduのドキュメント](https://kudu.apache.org/docs/index.html)

# 想定環境
- CentOS 7.2
- Cloudera Manager 5.9.0
- CDH 5.9.0 (4 node cluster/Impala構成済み)
- Apache Kudu 1.1.0

CDH5.9.0に含まれているImpala2.7からはKuduの表を扱えるようになっているので以前のようにKuduにアクセスするためのImpalaのforkであるImpala-Kuduをインストールする必要はなくなりました。
インストールせずに動かしたいだけなら単一ノードのQuickStart VMもあります。
http://kudu.apache.org/docs/quickstart.html


# Kudu-examples
今回はKuduの開発メンバーによって公開されている[kudu-examples](https://github.com/cloudera/kudu-examples)を使用します。
下記のようにすることでリポジトリを取得できます。

```
git clone https://github.com/cloudera/kudu-examples
````

## java/collectl
言語も内容も色々とあるのですが、せっかくなので、リアルタイムに更新されていく自分の環境データということでノードのパフォーマンスを収集するcollectlを使ってみたいと思います。Collectl自体はOSのコマンドでTCP/IP経由で収集したデータを送信できます。今回のサンプルはクラスタの各ノードから送られてくるパフォーマンスデータを待ち受けてKudu上にInsertしていく、というものになります。

サンプルのページに移動してビルド
```
cd kudu-examples/java/collectl
mvn package
```
(Mavenがインストールされていない場合は`sudo yum install maven`などとしてインストールしてください)

Kudu Masterを指定して実行(例)
```
java -DkuduMaster=n1:7051,n2:7051,n3:7051 -jar target/kudu-collectl-example-1.0-SNAPSHOT.jar
```
kuduMasterの書式は`<hostname>:<port>`で、Masterが複数ある場合は`,`で区切って指定します。
上記ではn1,n2,n3の3つのMasterを想定していますが、一つの場合は単一のMasterの`<hostname>:<port>`で問題ありません。

ここまで実行するとサンプルのプログラムが実行され、Kudu上での表の作成と各ノードからのcollectlでのデータ収集の準備が整った状態になります。
続けてデータの生成送付の処理をしていきます。

データの収集を行うcollectlコマンドのインストール
```
sudo yum install maven collectl
```

パフォーマンスデータを収集してn1にデータを送信する例
```
collectl --export=graphite,n1,p=/
```

ここまで終ればKuduにデータが流れ込んでいっています。必要に応じて実行ノードを増やすことで生成データを増加させることができます。
次に格納されたデータをImpalaを使って確認したいと思います。

# Impalaによるクエリの実行
これまでの処理でのKuduへのアクセスはJava APIを通じたものでした。そのため、Kuduには表ができていますが、Impalaからクエリを実行するためにはImpala側でも表を定義してKuduの表とのマッピングを行う必要があります。
マッピングに使うcreate table文の例は[ReadMe](https://github.com/cloudera/kudu-examples/tree/master/java/collectl)にも記載されていますが、KuduのWebUIからも確認することができます。
以下はMasterのWebUI（hostname:8051)にアクセスしたところからの例です。

Masterが複数ある場合、Leaderを確認する必要があります。
まず、Kudu MasterのWebUI上部のMastersをクリックします。
![2016-12-20-181703_289x119_scrot.png](https://qiita-image-store.s3.amazonaws.com/0/58396/9cf52c9c-b4fc-e337-d3bf-54187947309b.png)

MasterのLeaderをみつけたらLinkになっているUUIDをクリックしてLeaderのWebUIに遷移します。

![2016-12-20-181723_381x340_scrot.png](https://qiita-image-store.s3.amazonaws.com/0/58396/4a9095b4-6e85-741d-093a-65728deb086a.png)

LeaderページのTablesをクリックします。(1.1.0ではLeader以外ではエラーになります)
![2016-12-20-181753_1039x65_scrot.png](https://qiita-image-store.s3.amazonaws.com/0/58396/e9d7bfd3-ee03-f6dc-0dac-2ca7bb8a616b.png)

今回の対象であるmetric表を選択します。
![2016-12-20-181818_1118x205_scrot.png](https://qiita-image-store.s3.amazonaws.com/0/58396/e9809c1d-04e2-340e-8d97-1038749258fd.png)

ページの下部に下記のようにImpalaでCreate Tableする際の定義が表示されます。
これは表示するクラスタの内容(Masternodeの名前など)を反映したものになっているのでそのままコピーしてimpala-shellなどで実行できます。
![2016-12-20-181954_1105x354_scrot.png](https://qiita-image-store.s3.amazonaws.com/0/58396/06b1f50c-7622-9e3a-d623-6162deddc2b8.png)


## metric名の確認
Impala側でも表ができたらmetrics表にアクセスできるようになります。
どのようなメトリクスが収集されているかは下記のようにして確認できます。
```
> select distinct metric from metrics order by metric;
+---------------------+
| metric              |
+---------------------+
| cpuload.avg1        |
| cpuload.avg15       |
| cpuload.avg5        |
| cputotals.idle      |
| cputotals.irq       |
| cputotals.nice      |
| cputotals.soft      |
| cputotals.steal     |
| cputotals.sys       |
| cputotals.user      |
| cputotals.wait      |
| ctxint.ctx          |
| ctxint.int          |
| ctxint.proc         |
| ctxint.runq         |
| disktotals.readkbs  |
| disktotals.reads    |
| disktotals.writekbs |
| disktotals.writes   |
| nettotals.kbin      |
| nettotals.kbout     |
| nettotals.pktin     |
| nettotals.pktout    |
+---------------------+
```
## データ収集ノードの確認
収集元のノード名も持っているので、下記のようにして意図したノードからデータがあるかを確認することも可能です。
```
> select distinct host from metrics order by host;
+-------------------------------------+
| host                                |
+-------------------------------------+
| host-10-17-100-184.coe.cloudera.com |
| host-10-17-100-185.coe.cloudera.com |
| host-10-17-100-189.coe.cloudera.com |
| host-10-17-100-190.coe.cloudera.com |
+-------------------------------------+
```

## CPU使用率(idle)の変遷
状況によって実行したいクエリは変わると思いますが、例えばCPUにどれだけ余裕があるかを特定のノードについて時系列で確認する場合の例は下記のようになります。timestampはUNIX timeで格納されているので、表示時にunix time->UTC->JSTと変換をさせています。
```
> select host, from_utc_timestamp(from_unixtime(`timestamp`, 'yyyy-MM-dd HH:mm:ss'), 'JST') JST, value 
    from (select * from metrics 
                   where metric = 'cputotals.idle' and host='host-10-17-100-185.coe.cloudera.com') as met
    order by `timestamp` limit 10; 
+-------------------------------------|---------------------|-------+
| host                                | jst                 | value |
+-------------------------------------|---------------------|-------+
| host-10-17-100-185.coe.cloudera.com | 2016-12-20 18:11:05 | 98    |
| host-10-17-100-185.coe.cloudera.com | 2016-12-20 18:11:06 | 84    |
| host-10-17-100-185.coe.cloudera.com | 2016-12-20 18:11:07 | 81    |
| host-10-17-100-185.coe.cloudera.com | 2016-12-20 18:11:08 | 98    |
| host-10-17-100-185.coe.cloudera.com | 2016-12-20 18:11:09 | 97    |
| host-10-17-100-185.coe.cloudera.com | 2016-12-20 18:11:10 | 98    |
| host-10-17-100-185.coe.cloudera.com | 2016-12-20 18:11:11 | 98    |
| host-10-17-100-185.coe.cloudera.com | 2016-12-20 18:11:12 | 98    |
| host-10-17-100-185.coe.cloudera.com | 2016-12-20 18:11:13 | 98    |
| host-10-17-100-185.coe.cloudera.com | 2016-12-20 18:11:14 | 98    |
+-------------------------------------|---------------------|-------+
```

簡単なクエリの紹介だけですが、上記から各ノードから送付されるメトリクスの種別や頻度(毎秒)がわかると思いますので、クエリ作成の際の参考にしていただければと思います。

# Cloudera Managerによるパフォーマンスの確認
最後に実施した作業のワークロードを確認していきたいと思います。
Cloudera ManagerではChart Libraryを使って生成行数や読み取りデータ量を確認することができます。
その際、Kudu ServiceとTablet Serverなどのroleとで確認できるChartが異なっているので注意が必要です。

## Service
特定の表のデータ量の変遷や行の増加量などといった情報を確認することができます。
表全体としてのデータの状況やリソース消費を確認する際に有用です。
![2016-12-20-215118_1575x594_scrot.png](https://qiita-image-store.s3.amazonaws.com/0/58396/1d4392ef-9846-d531-24b7-7311e9e7508d.png)

## TabletServer
TabletServer上で特定のレプリカの処理を追跡することができます。
テーブル設計によってはデータの生成/スキャンに対してホットスポットとなるパーティションができてしまうことがあります。
テーブル全体のチャートからは判別できない負荷の偏りなどを確認する際に威力を発揮します。
![2016-12-20-215058_1547x597_scrot.png](https://qiita-image-store.s3.amazonaws.com/0/58396/00bb776d-9bfa-6085-fed6-7f95de40dec3.png)


# おわりに
いかがでしたでしょうか。
構築するシステムの負荷テストをする際には実際のデータを使うのが一番ですが、sampleを使用することでインストールしていくつかコマンドを実行してみる、というテストよりも少し動きのある検証ができるのでぜひ一度試してもらえればと思います。
今回の処理だけだとあまり負荷にはならないと思うので、裏でMapReduceを実行したりするとKudu上のデータをクエリする際にそれなりに動きのある情報が見れるかもしれないですね。
また、kudu-examplesの他のサンプルではランダムデータをinsertするものなどもあるのでinsertの負荷を上げたい場合などには試してみてください。