OXY NOTES

fluentdと連動して集計処理を行うNorikraの導入方法

NorikraをCentOS6にインストール

ビックデータ時代のログ管理ソフトfluentd
その利便性と安定した動作から、業界ではログ管理の標準になりつつあります。

そんなfluentdにも苦手な分野があります。
条件を指定した集計処理です。環境によって異なる集計処理を実装するには数値を操作するプラグインを組み合わせる必要がありました。

カウント処理で言えば「fluent-plugin-datacounter」。小数点を切り上げるには「fluent-plugin-amplifier-filter」といった具合です。

そうした集計処理をSQLライクな文法で手軽に追加できるのが、今回導入するNorikraです。
今回はCentOS6系での導入を例に解説します。


目次


Norikraとは

NorikrajRubyで書かれたオープンソースのソフトウエアで、Fluentdの生みの親として有名な田籠聡氏によって開発されました。(コメントでご指摘いただきました。Fluentdの作者は古橋貞之氏の誤りでした、失礼しました。)
読み方は「ノリカ」と間違われることが多いそうですが、「ノリクラ」と発音するそうです。乗鞍岳のワインディングロードと動的データストリームに着想を得て名付けたそうです。さすが天才の発想は凡人には及びもつきません。

何ができるのかというと、イベントストリーム処理SQLライクに処理することができます。具体的にはFluentdから渡されるリアルタイムのイベントSQLに似た文法で集計処理できます。

Fluentd単体では難しい以下のような処理が可能です。

といった柔軟な集計処理が可能です。

技術的な利点としてはスキーマレス(tableを持たない)のためデータの追加や削除などの扱いが容易です。
メモリ上で展開するためレイテンシが短く大量のデータも高速に処理できます。環境にもよりますが、なんと120k req/sもの処理が可能なようです。

更に詳細に知りたい方は「NorikraのWebページ」もしくは「作者のスライド」をご覧ください。


Norikraの導入方法

Norikraを動かすにはjRubyが必要です。
既にサーバで運用しているRubyの環境を変えたくないなどの需要が多いようで、ディレクリ単位でRubyのバージョンを管理できるrbenvを用いたインストール方法が一般的なようです。
当サイトでもその慣習にならいます。

rbenvの導入

まずはGitHubからrbenvをクローン。続いてRubyをビルドするのでruby-buildもクローンします。
私の環境ではrootユーザーで作業するのでrootの「~/.rbenv」にクローンしました。(/usr/local/なんかにインストールするのが一般的なようです)

インストールの方法はrbenvの公式の解説を参考にしました。

rbenvをクローン

# su -
# git clone https://github.com/sstephenson/rbenv.git ~/.rbenv
Initialized empty Git repository in /root/.rbenv/.git/
remote: Counting objects: 2291, done.
remote: Compressing objects: 100% (52/52), done.
remote: Total 2291 (delta 27), reused 0 (delta 0), pack-reused 2239
Receiving objects: 100% (2291/2291), 401.35 KiB | 285 KiB/s, done.
Resolving deltas: 100% (1422/1422), done.

続いてruby-buildをクローン

# git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build
remote: Counting objects: 5111, done.
remote: Total 5111 (delta 0), reused 0 (delta 0), pack-reused 5111
Receiving objects: 100% (5111/5111), 938.50 KiB | 471 KiB/s, done.
Resolving deltas: 100% (2810/2810), done.

rbenvへパスを通し初期化スクリプトを.bash_profileへ追加

# echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile
# echo 'eval "$(rbenv init -)"' >> ~/.bash_profile

設定を有効にしてバージョンを確認

# source ~/.bash_profile
# rbenv --version
rbenv 0.4.0-205-g5fb9c84

rbenvの環境にRubyをインストール

rbenvでインストール可能なRubyのバージョンを調べます。

# rbenv install --list

Rubyは数字のみで表示されているものです。最新のものを選んでインストールします。

以下のエラーが出る場合はエラーメッセージにある「readline-devel」をインストールします。

BUILD FAILED (CentOS release 6.6 (Final) using ruby-build 20151028-11-gbd22205)

Inspect or clean up the working tree at /tmp/ruby-build.20151122162756.8588
Results logged to /tmp/ruby-build.20151122162756.8588.log

Last 10 log lines:
installing rdoc:              /root/.rbenv/versions/2.2.3/share/ri/2.2.0/system
installing capi-docs:         /root/.rbenv/versions/2.2.3/share/doc/ruby
The Ruby readline extension was not compiled.
ERROR: Ruby install aborted due to missing extensions
Try running `yum install -y readline-devel` to fetch missing dependencies.
# yum install readline-devel
(省略)
Dependencies Resolved

================================================================================
 Package              Arch         Version                     Repository  Size
================================================================================
Installing:
 readline-devel       x86_64       6.0-4.el6                   base       134 k
Installing for dependencies:
 ncurses-devel        x86_64       5.7-4.20090207.el6          base       641 k
Updating for dependencies:
 ncurses-base         x86_64       5.7-4.20090207.el6          base        61 k
 ncurses-libs         x86_64       5.7-4.20090207.el6          base       245 k

Transaction Summary
================================================================================
Install       2 Package(s)
Upgrade       2 Package(s)
(省略)

Ruby 2.2.3インストールします。

# rbenv install 2.2.3
-> https://dqw8nmjcqpjn7.cloudfront.net/df795f2f99860745a416092a4004b016ccf77e8b82dec956b120f18bdc71edce
Installing ruby-2.2.3...
Installed ruby-2.2.3 to /root/.rbenv/versions/2.2.3

rbenvの環境にjRubyのインストール

rbenvでインストール可能なjRubyのバージョンを調べる。

# rbenv install --list

jrubyのバージョンがjruby-1.7.22から、jruby-9.0.0.0に飛んでいると思います。
これは9系からruby2.2に対応したため、わかりやすくバージョンを切り替えたそうです。

ということで最新の「jruby-9.0.4.0」をインストールします。

# rbenv install jruby-9.0.4.0

ここでも以下のエラーでインストールできない場合は「1.7-compatible JRE」をインストールします。

ERROR: Java 7 required. Please install a 1.7-compatible JRE.
BUILD FAILED (CentOS release 6.6 (Final) using ruby-build 20151028-11-gbd22205)
# yum install java-1.7.0-openjdk-devel

Dependencies Resolved

================================================================================
 Package                    Arch     Version                    Repository
                                                                           Size
================================================================================
Installing:
 java-1.7.0-openjdk-devel   x86_64   1:1.7.0.91-2.6.2.2.el6_7   updates   9.5 M
Installing for dependencies:
 ConsoleKit                 x86_64   0.4.1-3.el6                base       82 k
 ConsoleKit-libs            x86_64   0.4.1-3.el6                base       17 k
 GConf2                     x86_64   2.28.0-6.el6               base      964 k
 ORBit2                     x86_64   2.14.17-5.el6              base      168 k
 dbus                       x86_64   1:1.2.24-8.el6_6           base      207 k
 eggdbus                    x86_64   0.6-3.el6                  base       91 k
 flac                       x86_64   1.2.1-7.el6_6              base      242 k
 giflib                     x86_64   4.1.6-3.1.el6              base       37 k
 java-1.7.0-openjdk         x86_64   1:1.7.0.91-2.6.2.2.el6_7   updates    26 M
 jpackage-utils             noarch   1.7.5-3.14.el6             base       60 k
 libIDL                     x86_64   0.8.13-2.1.el6             base       83 k
 libXfont                   x86_64   1.4.5-5.el6_7              updates   137 k
 libasyncns                 x86_64   0.8-1.1.el6                base       24 k
 libfontenc                 x86_64   1.0.5-2.el6                base       24 k
 libogg                     x86_64   2:1.1.4-2.1.el6            base       21 k
 libsndfile                 x86_64   1.0.20-5.el6               base      233 k
 libvorbis                  x86_64   1:1.2.3-4.el6_2.1          base      168 k
 pcsc-lite-libs             x86_64   1.5.2-15.el6               base       28 k
 polkit                     x86_64   0.96-11.el6                base      162 k
 pulseaudio-libs            x86_64   0.9.21-21.el6              base      462 k
 sgml-common                noarch   0.6.3-33.el6               base       43 k
 ttmkfdir                   x86_64   3.0.9-32.1.el6             base       43 k
 tzdata-java                noarch   2015g-2.el6                updates   177 k
 xorg-x11-font-utils        x86_64   1:7.2-11.el6               base       75 k
 xorg-x11-fonts-Type1       noarch   7.2-11.el6                 base      520 k

Transaction Summary
================================================================================
Install      26 Package(s)

再びインストール

# rbenv install jruby-9.0.4.0
Downloading jruby-bin-9.0.4.0.tar.gz...
-> https://dqw8nmjcqpjn7.cloudfront.net/fcf828c4ad5b92430a349f1e873c067a15e0952d167d07368135c513fe0d18fb
Installing jruby-9.0.4.0...
Installed jruby-9.0.4.0 to /root/.rbenv/versions/jruby-9.0.4.0

最後に入ったバージョンを調べます。

# rbenv versions
  2.2.3
  jruby-9.0.4.0

無事にRuby 2.2.3jRuby 9.0.4.0がインストールできました。


Norikraのインストール

こちらも公式ドキュメントを参考にインストールします。

gemでbundleを入れて、bundle installでインストールする方法も解説されていますが、rootだとできないので却下。普通にインストールします。

# gem install norikra
(省略)
Successfully installed norikra-1.3.1-java
23 gems installed

これで、「~/norikra」に環境が整いました。
ということでディレクトリを移動してNorikraを起動します。

# cd ~/norikra
# norikra start

2015-11-22 17:49:41 +0900 [INFO] : thread configurations, engine:{:inbound=>{:threads=>0, :capacity=>0}, :outbound=>{:threads=>0, :capacity=>0}, :route_exec=>{:threads=>0, :capacity=>0}, :timer_exec=>{:threads=>0, :capacity=>0}}, rpc:{:threads=>2}, web:{:threads=>2}
2015-11-22 17:49:41 +0900 [INFO] : logging configurations, level:nil, dir:nil, filesize:nil, backups:nil, bufferlines:nil
2015-11-22 17:49:41 +0900 [WARN] : status file path (--stats) NOT specified
2015-11-22 17:49:41 +0900 [WARN] : TARGETS AND QUERIES WILL NOT BE SAVED ON SHUTDOWN !
2015-11-22 17:49:41 +0900 [INFO] : Loading UDF plugins
2015-11-22 17:49:41 +0900 [INFO] : Loading Listener plugins
2015-11-22 17:49:41 +0900 [INFO] : Listener loaded, name:Norikra::Listener::Stdout
2015-11-22 17:49:41 +0900 [INFO] : Listener loaded, name:Norikra::Listener::Loopback
2015-11-22 17:49:41 +0900 [INFO] : RPC server 0.0.0.0:26571, 2 threads
2015-11-22 17:49:41 +0900 [INFO] : WebUI server 0.0.0.0:26578, 2 threads
2015-11-22 17:49:41 +0900 [INFO] : Norikra server started.

status file path関係で警告が出てますが、とりあえず起動できることが確認できました。

外部からポート26578へアクセスするため、iptablesでポートを開放します。

# iptables -A INPUT -p tcp -m state --state NEW --dport 26578 -j ACCEPT

これで「http://<サーバのIP>:26578」でNorikraの設定画面にアクセスできます。
(動作確認ができたらIPで規制したり、パスワード制にするなどアクセス規制を行ってください)

起動できることが確認できたら、必要な準備をしていきます。まずは必要なディレクトリを作成します。

# mkdir /etc/norikra
# mkdir /var/log/norikra
# mkdir /var/run/norikra

そしてpidfilelogdirstatsを指定して起動します。
また、JavaライクにメモリをXmxXmsで指定することができます。サーバのリソースも有限なので、とりあえずXmx256mとして最大サイズを256MBに限定します。
また、daemonizeオプションを付けて、デーモンとして起動します。

更に細かい起動オプションを知りたい方は公式解説ページをご覧ください。

何も指定しないで起動すると以下のようになります。

STARTED: Fri, 04 Dec 2015 20:41:11 +0900
UPTIME: 0 days, 00:01
HEAP MEMORY USED: 43MB (9.8%), COMMITTED: 69MB, MAX: 437MB
NON-HEAP MEMORY USED: 45MB (21.0%), COMMITTED: 73MB, MAX: 214MB

Xmx256mオプションをつけて起動します。

# norikra start -Xmx256m --daemonize --pidfile=/var/run/norikra.pid --logdir=/var/log/norikra --stats=/etc/norikra/norikra.json
STARTED: Fri, 04 Dec 2015 22:41:37 +0900
UPTIME: 0 days, 00:00
HEAP MEMORY USED: 43MB (19.1%), COMMITTED: 61MB, MAX: 224MB
NON-HEAP MEMORY USED: 44MB (20.5%), COMMITTED: 66MB, MAX: 214MB

無事にメモリを制御できました。


Norikraの起動スクリプトを作成する

Norikraを起動するとき気になるのが、startで起動するとそのまま停止して、コマンドプロンプトの入力待ちの状態に戻りません。
Ctrl + C」で停止できますが、すると今度はNorikraのプロセスが停止してしまいます。また、「norikra stop」で停止したときにプロセスが残ることがある点も気になりました。

jRubyのプログラムは触るのが初めてなので、何か対処法があるのかもしれませんが、自動起動も兼ねて、起動スクリプトを作ることにしました。
(というより、みなさんどうやって制御しているのか、よかったらコメントください;;)

# vi /etc/rc.d/init.d/norikra

#!/bin/sh
# chkconfig: - 90 10
# description: norikra init script

export USER="root"
export NAME="norikra"
export PID_FILE="/var/run/norikra/norikra.pid"
export LOG_DIR="/var/log/norikra"
export STATS="/etc/norikra/norikra.json"
export PROG_FILE="/$USER/.rbenv/versions/jruby-9.0.4.0/bin/norikra"
export WORK_DIR="/$USER/norikra"
export LOCK_FILE="/var/lock/subsys/norikra"

# Source function library.
. /etc/rc.d/init.d/functions

start() {
  if [ -f "$LOCK_FILE" ]; then
    echo "norikra already started."
    exit 1;
  fi
  echo -n "Starting $NAME: "
  cd $WORK_DIR
  $PROG_FILE start -Xmx256m --daemonize --pidfile=$PID_FILE --logdir=$LOG_DIR --stats=$STATS & echo $! && success || failure
  retval=$?
  echo
  [ $retval -eq 0 ] && touch $LOCK_FILE
  return $retval
}

stop() {
  echo -n "Stopping $NAME: "
  rm -f $PID_FILE
  pkill -f $PID_FILE
  retval=$?
  [ $retval -eq 0 ] && success || failure
  [ $retval -eq 0 ] && rm -f $LOCK_FILE
  echo
  return $retval
}

case $1 in
    start)
        start
        ;;
    stop)
        stop
        ;;
    restart)
        stop
        start
        ;;
    *)
        echo "Syntax Error: release [start|stop|restart]"
        ;;
esac

Source function libraryを利用する一般的な起動スクリプトの形式です。
ユーザー名やプログラムファイルの場所は環境に合わせて適宜変更してください。

本来「norikra start」の終了ステータスを「success || failure」に渡したいのですが、入力待ちの状態になるため「echo $!」でプロセスIDを書き出し、そのステータスを渡す形にしました。

またライブラリを利用する場合は「daemon ~ killproc」で起動と停止を制御しますが、上記と同じ理由で不可能なためpkillでプロセスを停止しています。「norikra」をフラグにするとこのスクリプトも停止してしまうのでpidファイルをフラグに使っています。

norikra起動スクリプトをcheconfigへ登録

# chkconfig --add norikra

norikra自動起動設定

# chkconfig norikra on

norikra自動起動設定確認

# chkconfig --list norikra
norikra          0:off   1:off   2:on    3:on    4:on    5:on    6:off ← ランレベル2~5のonを確認

起動スクリプトへ実行権限付加

# chmod +x /etc/rc.d/init.d/norikra

動作テスト

# /etc/init.d/norikra stop ← 停止
# /etc/init.d/norikra start ← 起動
# /etc/init.d/norikra restart ← 再起動

これで無事にNorikraをインストールし、起動スクリプトも作成できました。
次は「Norikraの使い方をサンプルのクエリとイベントを交えて解説」します。