Elasticsearch River の配置カスタマイズとサーバー構成
データをフィードする為の River を単独サーバーで動かすためのメモ
River は、WebコンテンツやTwitter ストリーム、リレーショナルDBなど外部のリソースからデータを Elasticsearch クラスター内に取り込む為の機能(プロセス)のため、単独のサーバーで動かせないか調べてみました。
実現したいサーバー構成は以下の図のようなイメージです。
主に、サーチやインデックスを担うサーバー群(Search & Index Servers)と、リバーを稼働させるサーバー群(River Servers)を明示的に分けることで、Search & Index Servers の各サーバーのサーバーリソースの使用を平準化するのが目的です。(例えばリバーがフル稼働しているサーバーに検索に行ったら遅くなるなどの弊害を回避したいなどの要件)
ちなみに River は作成した River 毎に、1つのノード(サーバー)に自動的に起動される仕組みです。また、そのノードが停止された場合には、他のノードへ自動的に起動します。
River の配置ノードをコントロールする
上記サーバー構成を実現するには、まずRiverの配置されるノードをコントロールする必要があります。
調べてみるとちゃんと用意されていました(river » cluster allocation)。node.river オプションを使用することでコントロールできるようです。まず、 River を起動させたくない場合には、_none_ を設定するとそのノードではRiverは起動しなくなります。カンマ区切りで、River のタイプまたは、River の名前を列挙することで起動したいRiverを明示的に指定することが出来ます。
設定方法:
Search & Index Server の elasticsearch.yml に次のプロパティを追加します。
node.river: _none_
または、Search & Index Servers 起動時に次のプロパティを追加して起動します。
$ bin/elasticsearch -Des.node.river=_none_
NOTE: バージョン1.0以降は、コマンド起動時の -Des. プレフィックスなしに指定できるようです。—node.river=_none_ こんな感じ。
reference [1.x] » breaking changes in 1.0 » system and settings
確認方法:
ローカルに2つのElasticsearchを起動します。わかり易くする為に、node.name プロパティでそれぞれのサーバーに名前を付けています。また、以下の ”Search Server” にのみ上記の設定をしています。
$ curl 'localhost:9200/_cat/nodes?h=name,master,ip,port'
River Server m 192.168.1.128 9301
Search Server * 192.168.1.128 9300
テスト用の dummy リバーを使って、次のコマンドで3つのリバーを作成します。
$ curl -XPUT 'localhost:9200/_river/my_river1/_meta' -d '{
"type" : "dummy"
}'$ curl -XPUT 'localhost:9200/_river/my_river2/_meta' -d '{
"type" : "dummy"
}'$ curl -XPUT 'localhost:9200/_river/my_river3/_meta' -d '{
"type" : "dummy"
}'
次のコマンドで、それぞのリバーが起動しているサーバーを確認します。
$ curl 'localhost:9200/_river/my_river1/_status' -s|jq '._source.node.name'
"River Server"$ curl 'localhost:9200/_river/my_river2/_status' -s|jq '._source.node.name'
"River Server"$ curl 'localhost:9200/_river/my_river3/_status' -s|jq '._source.node.name'
"River Server"
おおっ!すべて、River Server で起動してますね。
TIPS:_status の出力をわかり易くする為に、jq コマンドラインを使用しています。ここからインストール出来ます。
ちなみに、”Search Server” のみ起動してリバーを作成すると、作成は成功しますが起動はしません。その後、”River Server” を起動したタイミングで、作成したリバーが起動します。
Shard の配置ノードをコントロールする
次に、River が起動するサーバーには、サーチとかインデックスの処理は必要ありませんので、Shard が配置されないように、Shard の配置されるノードをコントロールする必要があります。
Shard の配置方法はインデックスレベル、クラスタレベル、ノード毎のシャード数、ディスク使用率によるコントロールなどいろいろあります。今回は、cluster.routing.allocation.exclude.* プロパティを使用して今回の要件を実現しました。
NOTE:cluster.routing.allocation.enable: none の設定もためしてみましたが、この設定はREST API で呼び出したときのみ有効で、さらにノードの指定は出来ないので、cluster.routing.allocation.exclude.* を使用しています。
設定方法:
River Servers の elasticsearch.yml に次のプロパティを追加します。
node.server_group: river
cluster.routing.allocation.exclude.server_group: river
次に、Search & Index Servers の elasticsearch.yml に次のプロパティを追加します。
node.server_group: search
cluster.routing.allocation.exclude.server_group: river
※ node.server_group: search は使用していないため、無くてもOKです。明示的に区別するためだけに記述しています。
NOTE:ノードを識別する為の node.xxx プロパティは任意の名前が使用できます。今回は server_group と言う名前を使ってリバーサーバーの識別に使用しています。
確認方法:
Shard 配置可能な Search サーバー2台と、River サーバー1台の合計3台を以下のように起動しました。わかり易くする為に、node.name プロパティでそれぞれのサーバーに名前を付けています。
$ curl 'localhost:9200/_cat/nodes?h=name,master,ip,port'
River m 192.168.1.128 9301
Search2 m 192.168.1.128 9302
Search1 * 192.168.1.128 9300
次に、適当にインデックスを作成して、Shard の配置状況を次のコマンドで確認します。
$ curl 'localhost:9200/_cat/shards'
twitter 4 r STARTED 0 79b 192.168.1.128 Search2
twitter 4 p STARTED 0 79b 192.168.1.128 Search1
twitter 0 r STARTED 0 79b 192.168.1.128 Search2
twitter 0 p STARTED 0 79b 192.168.1.128 Search1
twitter 3 r STARTED 0 79b 192.168.1.128 Search2
twitter 3 p STARTED 0 99b 192.168.1.128 Search1
twitter 1 r STARTED 0 79b 192.168.1.128 Search2
twitter 1 p STARTED 0 99b 192.168.1.128 Search1
twitter 2 r STARTED 1 2.6kb 192.168.1.128 Search2
twitter 2 p STARTED 1 2.7kb 192.168.1.128 Search1
すばらしい!Search1 と Search 2 のサーバーのみ Shard が割り当てられているのが確認できました。
まとめ
以上の設定で今回の要件は満たせそうです。ただ、作成した1つのリバーはサーバーを増やしてもスケール出来なそうなので、作成する単位を工夫して複数起動するか、サーバーのスペックを上げるなどの対応は必要そうです。