2014年12月7日

elasticsearch+kibana3を使ってログを可視化してみた


以前、Raspberry Piに温度/気圧センサーを取り付けて、その結果をXivelyにロギングしていたのですが、今回たまたま見かけたお名前.comクラウドの一万円クーポンがあったので、(遅ればせながら)Ubuntu環境にelasticsearchとkibana3を導入して、温度/気圧センサーのログを可視化してみる事にしました。

#クーポンのおかげ?か、例のメールが届きました。
#担当者さんの心中をお察しします。。

お名前.comクラウド上に仮想サーバを作成

まずはお名前.comクラウドのコントロールパネルにログインして、サービスメニューの”サーバ追加”より仮想サーバを起動します。OSは前述の通りUbuntu 12.04を選択し、タイプはvCPUx1/メモリ1GBのO-101を選択しました。
仮想サーバが起動したら、SSH公開鍵を使ってログインし、apt-get updateやファイアウォールの設定などの下準備を行います。

Oracle JDK 7のインストール

elasticsearchを動作させるためにはJavaランタイム環境が必要になるのですが、いつものapt-getではインストールできないため、下記のコマンドを実行します。
(”ランタイム環境”のみあればいいはずなので、OpenJRE/OracleJREでもよさそうですが、今回は公式のJDKで試しています)
$ sudo add-apt-repository ppa:webupd8team/java
$ sudo apt-get install oracle-java7-installer
(oracle-java8-installerで、最新のJava8がインストールできるようです)
インストールが終わった後に、"java -version"と入力してバージョン情報が表示されれば正しくインストールされているかと思います。

elasticsearchのインストール

Javaランタイム環境の準備ができたので、次はelasticsearchをインストールします。
$ sudo apt-get install elasticsearch
公式サイトではUbuntu向けにdebパッケージも提供されているため、そちらをダウンロードしてdpkg -iでインストールしてもOKです。
インストールが終了したら、curlコマンドで下記にアクセスして応答が返ってくる事を確認します。
$ curl -s "http://localhost:9200/"
{  "status" : 200,  "name" : "Thinker",  "cluster_name" : "elasticsearch",  "version" : {    "number" : "1.4.1",    "build_hash" : "89d3241d670db65f994242c8e8383b169779e2d4",    "build_timestamp" : "2014-11-26T15:49:29Z",    "build_snapshot" : false,    "lucene_version" : "4.10.2"  },  "tagline" : "You Know, for Search"}

Raspberry Piからelasticsearchにログを登録

elasticsearchにログを登録する場合は、logstashやfluentdを使うケースが多いみたいですが、今回は直接elasticsearchにログを登録する方法で試してみました。
こちらより、Raspberry Piに設置した温度/気圧センサー(BMP085)から値を取得するプログラムをダウンロードし、結果を出力する部分をJSON形式に改造します。
41a42
>#include <time.h>
236,238c237,248
<
< printf("Temperature\t%0.1f%cC\n", ((double)temperature)/10,0x00B0);
< printf("Pressure\t%0.2fhPa\n", ((double)pressure)/100);
---
>
> time_t timer;
> struct tm *date;
> char dt[255];
>
> timer = time(NULL);
> date = localtime(&timer);
> strftime(dt, 255, "%Y-%m-%dT%H:%M:%S", date);
>
> // printf("Temperature\t%0.1f%cC\n", ((double)temperature)/10,0x00B0);
> // printf("Pressure\t%0.2fhPa\n", ((double)pressure)/100);
> printf("{\"datetime\": \"%s\", \"temperature\": %0.1f, \"pressure\": %0.2f}\n", dt, ((double)temperature) / 10, ((double)pressure) / 100);
ソースの修正が終わったら、一緒にダウンロードしたsmbus.c, smbus.hとともにgccでコンパイルし、できたコマンドをrootで実行するようsetuidビットを設定します。
sudo gcc -Wall -o bmp085 ./testBMP085.c ./smbus.csudo chmod 4755 ./bmp085sudo mv ./bmp085 /usr/local/bin
これでBMP085から、現在時刻(datetime)と温度(temperrature)と気圧(pressure)がJSON形式で取得できるようになったので、以下のcurlコマンドをcronに登録してelasticsearchにログを登録します。

* * * * * /usr/bin/curl -s -X POST "http://[リモートIPアドレス]:9200/bmp085/stats" -d "$(/usr/local/bin/bmp085)" > /dev/null
URLパスの"bmp085"がインデックス名、"stats"がタイプ名になります。
なお、登録されるデータは、先ほどのコマンドで出力されるJSONデータ(日時フィールドの"datetime"、気温の"temparature"、気圧の"pressure")になります。
ログが正しく登録されているかは、下記コマンドで確認することができます。
$ curl -s -X GET http://[リモートIPアドレス]:9200/bmp085/stats/_search
{
  "took": 3, "timed_out": false,
  "_shards": {
    "total": 5, "successful": 5, "failed": 0
  },
  "hits": {
    "total": 1213, "max_score": 1,
    "hits": [
      {
        "_index": "bmp085",
        "_type": "stats",
        "_id": "AUogPm0qkUV2E2kcxVxl",
        "_score": 1,
        "_source": {
          "datetime": "2014-12-07T00:36:09",
          "temperature": 15.8,
          "pressure": 1009.74
        }
      },
... 

kibana3のインストール

elasticsearchのログを可視化するためのツールとして、今度はkibana3をインストールします。
公式サイトよりパッケージをダウンロードし、ApacheやnginxなどのWebサーバのドキュメントルートに配置します。
(今回はnginxを使ってみました)
$ sudo apt-get install nginx
$ cd /usr/share/nginx/www
$ sudo curl -O https://download.elasticsearch.org/kibana/kibana/kibana-3.1.2.zip
$ sudo unzip kibana-3.1.2.zip
$ sudo mv kibana-3.1.2 kibana
なお今回試していませんが、Apacheやnginxをインストールしなくても、elasticsearchのプラグインとしてkibana3をインストールすれば、elasticsearch自身がkibana3をホストしてくれるみたいです。

クロスドメイン通信許可の設定

早速、前述で設置したkibana3(http://[リモートIPアドレス]/kibana)にアクセスしてみると、下記エラー画面(Connection Failed)が表示されるはずです。
これは、elasticsearch+kibana3をローカル環境ではなくリモート環境に構築している関係かと思われますが、elasticsearch.ymlにクロスドメイン通信許可の設定を加えることでアクセスできるようになります。
$ sudo vim /etc/elasticsearch/elasticsearch.yml
  http.cors.allow-origin: "/.*/"
  http.cors.enabled: true$ sudo service elasticsearch restart

ダッシュボードの作成

elasticsearchにログが記録され、kibana3の表示が確認できたところで、いよいよログを可視化するためのダッシュボードを作成します。
前述の通り今回はlogstashやfluentdなどを使わずログの記録を行っているため、一番下の"Blank Dashboard"より作成を開始します。
すると、"QUERY"と"FILTERING"などが表示された空のダッシュボード画面が表示されますので、そこから右上の歯車アイコン(Configure dashboard)をクリックし、ダッシュボードの設定画面へ進みます。

まず最初のGeneralで、ダッシュボードのタイトルを入力します。
次のIndexでは、名前の通りelasticsearch上のインデックス名を入力します。
Rowsでは、まずAdd RowのTitleにタイプ名を入力します。入力が終わったら【Create Row】ボタンを押下します。
すると左側のRowsに追加されます。
最後に、TimepickerでTime Fieldにelasticsearchに登録されているデータの日時フィールド名を入力します。終わったら【Save】ボタンを押下して入力内容を保存します。 
作成中のダッシュボードに戻ると、"Add panel to empty row"と書かれた項目が追加されているので、文字リンクをクリックしてパネルの設定に進みます。
まず、パネルで表示するグラフのタイプを選択します。今回は時系列で温度と気圧を折れ線グラフで可視化するため、"histogram"を選択します。
次にグラフのタイトルを入力します。
チャートの値は平均(mean)とし、その値ソースとして気温フィールド名を入力します。
Time Optionsでは、同じく日時フィールド名を入力します。
最後にパネルのスタイル設定として、棒グラフ(Bars)のチェックを外して折れ線グラフ(Lines)にチェックを入れます。ここまでの入力内容に問題が無ければ【Save】ボタンを押下して入力内容を保存します。


おわりに

予想以上に設定作業が大変で、今回のような温度や気圧程度であれば、elasticsearch+kibana3ではなく、GrowthForecastFocuslightの方がお手軽な感じもしますが、フィルターなどを駆使して自分の分析したい切り口でダッシュボードを作っていく流れは、ツール開発者が作った出来合いの管理画面をただ見るだけとは一線を画す感じがしました。
現在ベータ版のkibana4では、上記の設定フロー周りが改善されているらしいので、今後はもっと使われるケースが多くなってくるのかもしれません。

2014年10月13日

WOL(Wake On LAN)非対応のNUCにリモートから電源を入れる

去年購入したNUC(DC3217BY)ですが、投げ売りされていただだけあって有線LANを持たず、WOL(Wake On LAN)を使ってリモートから電源を入れることができませんでした。

なので今までは省スペースPCという事もあり電源入れっぱで運用していたのですが、さすがにそれだと電気代が気になってくるので、こちらの記事を参考にしてRaspberry Pi経由で電源を入れる機能に挑戦してみました。

ピンヘッダをショート?

PCに電源ボタン以外で電源を入れる場合、マザーボードから出ているピンヘッダをショート(短絡)させるらしいのですが、”ショートって壊れるイメージ”ってくらいド素人なので、まずはこちらの資料をみつつジャンパーコードを使って手動で試して(よく映画とかで盗んだ車のエンジンを入れるイメージw)みたところ、確かに電源が入りました。

パーツを調達


ピンヘッダから電源が入ることを確認できたので、早速アキバで必要なパーツを調達する事に。購入した(使った)パーツは以下の通り。
前にRaspberry Piに温度/気圧センサーをつけた時は、単純にジャンパーワイヤーで所定の箇所につなぐだけでよかったのですが、今回ははんだづけが必要な様子。

しかも「降圧」「抵抗分圧」など専門用語が飛び交ってて何がなんやら。。ググってみたところ、前者はRaspberry PiのGPIOから3.3Vの信号がくるのに対し、LK-RB1は2Vの入力感度になるため抵抗を使って電圧を落とす?必要があり、後者は抵抗を使ったその方法になるようです。

確かにこちらの計算式に従って計算してみると、確かに出力は2.2Vになり参考記事の値と一致しました。

ブレッドボードを使っての仮組みとテスト

パーツが揃った(LK-RB1は先にはんだづけして組み上げ)段階で、まずはブレッドボードとクリップ付コードを使って本当に動作するか仮組みしてしてみたところ動作せず。。

てかそもそもどこが悪いのかさっぱり分からないので、追加でテスターを調達して改めて仮組みしてみたところ、「パチッ」というリレーの音とともにPCとつなぐ部分端子からテスターの反応を確認する事ができました!

NUCに配線して本組み

動作確認が取れたところで、NUCのマザーボードにあるピンヘッダからリレースイッチまでのコードを配線。NUC側はケンジントンロックの穴にわずかな隙間があったので、そこにコード線を無理やり通して対応しました。最後にRaspberry Pi側から以下のプログラムを実行して電源が入るかをテストしたところ。。無事電源が入ることを確認!
#!/bin/bash
GPIO_ID=17
B_TIME=0.5
echo ${GPIO_ID} > /sys/class/gpio/export
echo out > /sys/class/gpio/gpio${GPIO_ID}/direction
echo 0 > /sys/class/gpio/gpio${GPIO_ID}/value
echo 1 > /sys/class/gpio/gpio${GPIO_ID}/value
sleep ${B_TIME}
echo 0 > /sys/class/gpio/gpio${GPIO_ID}/value
一つ一つの作業自体は大変でしたが、電子工作?初心者には手軽でかつ実用的な範囲に収まってよかったです。でもテスター購入とかあって”電気代節約”という本来の目的とは程遠い結果になってしまったので、これを使って次のネタを考えねばと思っています(苦笑)

    2014年9月15日

    ConoHaオブジェクトストレージを使ってみた

    今月上旬にVPSサービスのConoHaで、オブジェクトストレージのモニターを募集していたので応募してみたところ、当選の通知が来ておりました。

    というわけで、まずは技術ブログの手順に従ってAPIユーザを作成し、別途ソフトウェアのインストールを伴わないcurlコマンドで触ってみました。
    (さくらのBASE Storageと同様にs3cmdで、と説明も見ずにインストールしてたら、OpenStackのswiftというオブジェクトストレージを使っているというのを知ってcurlコマンドを使ったという。。)
    APIユーザの作成が完了すると、テナントID/テナント名/ユーザ名/API Auth URL/オブジェクトストレージエンドポイントが発行されます。

    トークンを取得

    curlコマンドでオブジェクトストレージを操作するためには、前述のAPIユーザ情報を使ってトークンを取得する必要があります。
    curl -i -X POST 'https://*****-*****.*****.jp/v2.0/tokens' \
      -H "Content-Type: application/json" \
      -H "Accept: application/json" \
      -d '{"auth":{"tenantName":"1234567","passwordCredentials":{"username":"1234567","password":"*******"}}}'
    実行すると{"access":{"token":...から始まるJSONが返却されますが、この中の"token"オブジェクトに含まれる"id"がトークンになります。以後のAPI呼び出しは"X-Auth-Token"ヘッダにトークンをつけて呼び出す形になります。

    コンテナの作成

    オブジェクトをストレージに格納するためには、まず「コンテナ」を作成する必要があります。コンテナはAmazon S3でいうところのBucketになる概念かと思われますが、特に全サーバで共通の名前でないといけないような感じではありませんでした("hoge"とかでも作れた)。また、ConoHa独自の機能として、コンテナの中にフォルダを作成する事ができるようです。
    curl -i -X PUT https://*****-*****.*****.jp/v1/3134..cdef/hoge \
      -H "X-Auth-Token: 0123..abcd"

    オブジェクトのアップロード

    コンテナを作成したらそこに対してオブジェクトをアップロードします。
    基本的にはコンテナの作成で使用したエンドポイントの末尾にファイル名を指定し、curlコマンドの-Tオプションでアップロードするファイル名のパスを指定する事でアップロードができました。
    curl -i -X PUT https://*****-*****.*****.jp/v1/3134..cdef/hoge/image.jpg \
      -T /Users/test/image.jpg \
      -H "X-Auth-Token: 0123..abcd"

    オブジェクトのダウンロード

    オブジェクトのダウンロードは、アップロードのPUTメソッドをGETメソッドに変えるだけです。
    curl -i -X GET https://*****-*****.*****.jp/v1/3134..cdef/hoge/image.jpg -O \
      -H "X-Auth-Token: 0123..abcd"

    オブジェクトのコピー

    ちょっと珍しいと思ったのがオブジェクトのコピーで、COPYメソッドを指定してコピー先をDestinationヘッダで指定する方式を取ってました。「HTTPにコピーメソッドって定義されてたっけ?」と調べたら、WebDAV関連で定義されているようです。
    curl -i -X COPY https://*****-*****.*****.jp/v1/3134..cdef/hoge/image.jpg \
      -H "Destination: hoge/image2.jpg" \
      -H "X-Auth-Token: 0123..abcd"

    オブジェクトの削除

    DELETEメソッドを指定する事でオブジェクトの削除となります。レスポンスヘッダが"204 No Content"と返ってくると削除成功となります。コンテナの削除も同様の手順で実行できますが、コンテナ下にオブジェクトがあると"409 Conflict"が返ってきて削除できませんでした。

    感想など

    以前試してみたさくらのBASE Storageと違ってAmazon S3互換が無いのはどうかなーと思っていたのですが、API自体はシンプルなので利用の障害にはならなそうな印象でした。しかもこちらの方は容量による課金でAPIコール数や転送量に対しては課金されないことから、用途によってはAmazon S3よりメリットがありそうです。