OSvでelasticsearchを動かしてみた
今日の内容
OSvもくもく会#4でelasticsearchを動かしてみたので、その内容でOSv Advent Calendarを書いてみます。
OSvとelasticsearchはGitHubからcloneしたものを利用しており、今回はOSvはコミットb79223584b(v0.16-27-gb792235)で、elasticsearchはコミット6d872843bdにて動作確認が取れています。
環境はFedora21を利用しています。
elasticsearch?
公式サイトによると、elasticsearchは"Elasticsearch is a flexible and powerful open source, distributed, real-time search and analytics engine. "と紹介されており、分散リアルタイム検索・分析エンジンのようです(ずっとKey Valueストアの実装のひとつだとばかり思っていました)。
elasticsearchのビルド
GitHubからcloneしてきたelasticsearchをビルドします。ソースコードからビルドするのには理由があります。elasticsearchはjarファイルなのですが、実行時にsigarという.so形式のシステムモニタリングライブラリをロードするため、バイナリ配布されているバージョンだと実行できません。
ただ、最新のGitHub上のソースファイルを見るとsigarはビルド時に無効化されているので、バイナリ配布のものでも大丈夫かもしれません(未確認です)。
- SIGAR - System Information Gatherer And Reporter
以下の手順でelasticsearchをビルドします。Maven等のビルドツールが必要なので予めインストールしてください。
fedora$ git clone https://github.com/elasticsearch/elasticsearch.git
fedora$ mvn clean package -DskipTests
ビルドが完了すると、以下のjarファイルが生成されます。
$ ls target/elasticsearch-2.0.0-SNAPSHOT*.jar
target/elasticsearch-2.0.0-SNAPSHOT-sources.jar
target/elasticsearch-2.0.0-SNAPSHOT-test-sources.jar
target/elasticsearch-2.0.0-SNAPSHOT-tests.jar
target/elasticsearch-2.0.0-SNAPSHOT.jar
OSvのビルド
続いてOSvをビルドします。REST API経由でjarファイルの転送を行うため、httpserver,javaを指定してビルドします。
cliも忘れずに指定してください。
fedora$ make image='cli,httpserver,java'
OSv上でのelasticsearch実行
OSvにアプリケーションを移植する場合、appsディレクトリ以下にビルド用の設定ファイルを用意し、"make image=elasticsearch"のような形でビルドできるようにするべきなのですが、今回はそこまでたどり着けていないので、ビルドしたjarファイルを実行する方法で進めてみます。
逆に、移植作業中は以下に示すようなトライアンドエラー的な手順で進め、ある程度動くようになってからappsディレクトリにファイルを用意する、という手もアリかもしれません。
OSv側での準備
まず、elasticsearch関連のファイルを配置するディレクトリとして/elsと/tmp/elsを予め作成します。
fedora$ sudo ./scripts/run.py -n
OSv v0.16-27-gb792235
eth0: 192.168.122.89
/# mkdir /els /tmp/els
elasticsearchをOSvにコピーする
次に、ホストOS上からelasticsearchのjarファイル群をOSvに転送します。OSvのIPアドレスは起動時に表示されるので、それを指定します。
ホントはOSv側上でifconfig等を実行してIPアドレスを確認したいのですが、CRaSHからLua CLIに切り替わってからはifconfigが提供されなくなってしまいました...。
ファイルの転送はREST API経由で行います。
fedora$ curl -XPOST http://192.168.122.89:8000/file/els/elasticsearch.jar -Fname=@./target/elasticsearch-2.0.0-SNAPSHOT.jar
fedora$ for i in `find ./target/lib/*.jar`
do
curl -XPOST http://192.168.122.89:8000/file/els/`basename ${i}` -Fname=@${i}
done
elasticsearchのjarファイルは以下のような配置になります。
/# ls -l /els
total 71052
-rwxrwxrwx 1 osv osv 167735 Dec 23 17:37 antlr-runtime-3.5.jar
-rwxrwxrwx 1 osv osv 448794 Dec 23 17:37 apache-log4j-extras-1.2.17.jar
-rwxrwxrwx 1 osv osv 47359 Dec 23 17:37 asm-4.1.jar
-rwxrwxrwx 1 osv osv 38090 Dec 23 17:37 asm-commons-4.1.jar
-rwxrwxrwx 1 osv osv 41123 Dec 23 17:37 commons-cli-1.2.jar
-rwxrwxrwx 1 osv osv 412739 Dec 23 17:37 commons-lang3-3.3.2.jar
-rwxrwxrwx 1 osv osv 110694 Dec 23 17:37 compiler-0.8.13.jar
-rwxrwxrwx 1 osv osv 79732 Dec 23 17:37 compress-lzf-1.0.2.jar
-rwxrwxrwx 1 osv osv 13247055 Dec 23 17:37 elasticsearch.jar
-rwxrwxrwx 1 osv osv 7065645 Dec 23 17:37 groovy-all-2.3.2-indy.jar
-rwxrwxrwx 1 osv osv 2256213 Dec 23 17:37 guava-18.0.jar
-rwxrwxrwx 1 osv osv 1307968 Dec 23 17:37 hppc-0.6.0.jar
-rwxrwxrwx 1 osv osv 225316 Dec 23 17:37 jackson-core-2.4.2.jar
-rwxrwxrwx 1 osv osv 45230 Dec 23 17:37 jackson-dataformat-cbor-2.4.2.jar
-rwxrwxrwx 1 osv osv 75008 Dec 23 17:37 jackson-dataformat-smile-2.4.2.jar
-rwxrwxrwx 1 osv osv 324650 Dec 23 17:37 jackson-dataformat-yaml-2.4.2.jar
-rwxrwxrwx 1 osv osv 914597 Dec 23 17:37 jna-4.1.0.jar
-rwxrwxrwx 1 osv osv 38460 Dec 23 17:38 joda-convert-1.2.jar
-rwxrwxrwx 1 osv osv 581571 Dec 23 17:38 joda-time-2.3.jar
-rwxrwxrwx 1 osv osv 794991 Dec 23 17:38 jts-1.13.jar
-rwxrwxrwx 1 osv osv 489884 Dec 23 17:38 log4j-1.2.17.jar
-rwxrwxrwx 1 osv osv 1529188 Dec 23 17:38 lucene-analyzers-common-5.0.0-snapshot-1646179.jar
-rwxrwxrwx 1 osv osv 365795 Dec 23 17:38 lucene-backward-codecs-5.0.0-snapshot-1646179.jar
-rwxrwxrwx 1 osv osv 2230594 Dec 23 17:38 lucene-core-5.0.0-snapshot-1646179.jar
-rwxrwxrwx 1 osv osv 75222 Dec 23 17:38 lucene-expressions-5.0.0-snapshot-1646179.jar
-rwxrwxrwx 1 osv osv 107452 Dec 23 17:38 lucene-grouping-5.0.0-snapshot-1646179.jar
-rwxrwxrwx 1 osv osv 139676 Dec 23 17:38 lucene-highlighter-5.0.0-snapshot-1646179.jar
-rwxrwxrwx 1 osv osv 65215 Dec 23 17:38 lucene-join-5.0.0-snapshot-1646179.jar
-rwxrwxrwx 1 osv osv 33735 Dec 23 17:38 lucene-memory-5.0.0-snapshot-1646179.jar
-rwxrwxrwx 1 osv osv 160334 Dec 23 17:38 lucene-misc-5.0.0-snapshot-1646179.jar
-rwxrwxrwx 1 osv osv 201533 Dec 23 17:38 lucene-queries-5.0.0-snapshot-1646179.jar
-rwxrwxrwx 1 osv osv 391276 Dec 23 17:38 lucene-queryparser-5.0.0-snapshot-1646179.jar
-rwxrwxrwx 1 osv osv 111979 Dec 23 17:38 lucene-sandbox-5.0.0-snapshot-1646179.jar
-rwxrwxrwx 1 osv osv 155557 Dec 23 17:38 lucene-spatial-5.0.0-snapshot-1646179.jar
-rwxrwxrwx 1 osv osv 177741 Dec 23 17:38 lucene-suggest-5.0.0-snapshot-1646179.jar
-rwxrwxrwx 1 osv osv 1302165 Dec 23 17:38 netty-3.9.3.Final.jar
-rwxrwxrwx 1 osv osv 428580 Dec 23 17:38 sigar-1.6.4.jar
-rwxrwxrwx 1 osv osv 25689 Dec 23 17:38 slf4j-api-1.6.2.jar
-rwxrwxrwx 1 osv osv 102177 Dec 23 17:38 spatial4j-0.4.1.jar
-rwxrwxrwx 1 osv osv 49754 Dec 23 17:38 t-digest-3.0.jar
OSv起動時にelasticsearchが立ち上がるようにする
OSvは基本的にシングルプロセスで動作するため、起動時にLua CLIではなくelasticsearchが起動するように設定します。
この設定もREST API経由で行います。
コマンドが長いのでシェルスクリプト経由で設定すると良さげです。
$ cat setup_els_to_osv.sh
#!/bin/sh
cmdline=""
cmdline="$cmdline java.so "
cmdline="$cmdline -Djava.awt.headless=true "
cmdline="$cmdline -Des.foreground=yes "
cmdline="$cmdline -Des.path.home=/tmp/els"
cmdline="$cmdline -cp /els/elasticsearch.jar:/els/* "
cmdline="$cmdline org.elasticsearch.bootstrap.Elasticsearch"
curl -X POST -d cmdline="$cmdline" http://192.168.122.89:8000/os/cmdline
curl -XGET http://192.168.122.89:8000/os/cmdline
設定後、OSvを再起動します(REST APIからでも再起動できます)。
/# reboot
OSv v0.16-27-gb792235
再起動すると、何やらいきなり例外が発生しますが、慌てずにぐっと我慢します。
/# reboot
OSv v0.16-27-gb792235
Failed to configure logging...
org.elasticsearch.ElasticsearchException: Failed to load logging configuration
at org.elasticsearch.common.logging.log4j.LogConfigurator.resolveConfig(LogConfigurator.java:139)
at org.elasticsearch.common.logging.log4j.LogConfigurator.configure(LogConfigurator.java:89)
at org.elasticsearch.bootstrap.Bootstrap.setupLogging(Bootstrap.java:96)
at org.elasticsearch.bootstrap.Bootstrap.main(Bootstrap.java:171)
at org.elasticsearch.bootstrap.Elasticsearch.main(Elasticsearch.java:32)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at io.osv.ContextIsolator.runMain(ContextIsolator.java:233)
at io.osv.ContextIsolator.access$400(ContextIsolator.java:32)
at io.osv.ContextIsolator$3.run(ContextIsolator.java:118)
Caused by: java.nio.file.NoSuchFileException: /tmp/els/config
at sun.nio.fs.UnixException.translateToIOException(UnixException.java:86)
at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:102)
at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:107)
at sun.nio.fs.UnixFileAttributeViews$Basic.readAttributes(UnixFileAttributeViews.java:55)
at sun.nio.fs.UnixFileSystemProvider.readAttributes(UnixFileSystemProvider.java:144)
at sun.nio.fs.LinuxFileSystemProvider.readAttributes(LinuxFileSystemProvider.java:97)
at java.nio.file.Files.readAttributes(Files.java:1684)
at java.nio.file.FileTreeWalker.walk(FileTreeWalker.java:109)
at java.nio.file.FileTreeWalker.walk(FileTreeWalker.java:69)
at java.nio.file.Files.walkFileTree(Files.java:2600)
at org.elasticsearch.common.logging.log4j.LogConfigurator.resolveConfig(LogConfigurator.java:123)
... 11 more
log4j:WARN No appenders could be found for logger (node).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
WARNING: fcntl(F_SETLK) stubbed
40171 [Thread-3] DEBUG Sigar - no libsigar-amd64-linux.so in java.library.path
org.hyperic.sigar.SigarException: no libsigar-amd64-linux.so in java.library.path
at org.hyperic.sigar.Sigar.loadLibrary(Sigar.java:172)
at org.hyperic.sigar.Sigar.<clinit>(Sigar.java:100)
at org.elasticsearch.monitor.sigar.SigarService.<init>(SigarService.java:40)
at org.elasticsearch.monitor.MonitorModule.configure(MonitorModule.java:70)
at org.elasticsearch.common.inject.AbstractModule.configure(AbstractModule.java:60)
at org.elasticsearch.common.inject.spi.Elements$RecordingBinder.install(Elements.java:204)
at org.elasticsearch.common.inject.spi.Elements.getElements(Elements.java:85)
at org.elasticsearch.common.inject.InjectorShell$Builder.build(InjectorShell.java:130)
at org.elasticsearch.common.inject.InjectorBuilder.build(InjectorBuilder.java:99)
at org.elasticsearch.common.inject.Guice.createInjector(Guice.java:93)
at org.elasticsearch.common.inject.Guice.createInjector(Guice.java:70)
at org.elasticsearch.common.inject.ModulesBuilder.createInjector(ModulesBuilder.java:59)
at org.elasticsearch.node.internal.InternalNode.<init>(InternalNode.java:200)
at org.elasticsearch.node.NodeBuilder.build(NodeBuilder.java:159)
at org.elasticsearch.bootstrap.Bootstrap.setup(Bootstrap.java:66)
at org.elasticsearch.bootstrap.Bootstrap.main(Bootstrap.java:196)
at org.elasticsearch.bootstrap.Elasticsearch.main(Elasticsearch.java:32)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at io.osv.ContextIsolator.runMain(ContextIsolator.java:233)
at io.osv.ContextIsolator.access$400(ContextIsolator.java:32)
at io.osv.ContextIsolator$3.run(ContextIsolator.java:118)
76791 [Thread-3] DEBUG threadpool - [Key] creating thread_pool [generic], type [cached], keep_alive [30s]
77264 [Thread-3] DEBUG threadpool - [Key] creating thread_pool [index], type [fixed], size [4], queue_size [200]
例外という名の嵐が過ぎ去ると、elasticsearchが起動してきます。
135654 [elasticsearch[Key][clusterService#updateTask][T#1]] INFO gateway - [Key] recovered [0] indices into cluster_state
135714 [elasticsearch[Key][clusterService#updateTask][T#1]] DEBUG cluster.service - [Key] processing [local-gateway-elected-state]: done applying updated cluster_state (version: 2)
142373 [elasticsearch[Key][clusterService#updateTask][T#1]] DEBUG cluster.service - [Key] processing [routing-table-updater]: execute
142460 [elasticsearch[Key][clusterService#updateTask][T#1]] DEBUG cluster.service - [Key] processing [routing-table-updater]: no change in cluster_state
elasticsearchをちょっと試してみる
さっそくホストOS(Fedora)側からOSv上のelasticsearchを触ってみます。
まずはelasticsearchの情報を取得してみます。
fedora$ curl -X GET http://192.168.122.89:9200/
{
"status" : 200,
"name" : "Magnus",
"cluster_name" : "elasticsearch",
"version" : {
"number" : "2.0.0",
"build_hash" : "6d872843bd30c485a4137b2f418bd833d963cc91",
"build_timestamp" : "2014-12-23T16:49:13Z",
"build_snapshot" : true,
"lucene_version" : "5.0.0"
},
"tagline" : "You Know, for Search"
}
次に、何となくそれっぽいデータを登録してみます。
fedora$ curl -XPUT 'http://192.168.122.89:9200/naruko/user/mimori' -d '{ "name": "東郷美森" }'
{"_index":"naruko","_type":"user","_id":"mimori","_version":1,"created":true}
$ curl -XPUT 'http://192.168.122.89:9200/naruko/tweet/1' -d '
{
"user" : "mimori",
"postDate": "2014-23-23T21:30:00",
"message" : "次こそはぼた餅食べてくださいね。有無は言わせない。"
}'
{"_index":"naruko","_type":"tweet","_id":"1","_version":1,"created":true}
登録したデータを取得してみます。勇者部部員向けのチャットアプリのバックエンドに利用できそうですね。
fedora$ curl -XGET 'http://192.168.122.89:9200/naruko/user/mimori?pretty=true'
{
"_index" : "naruko",
"_type" : "user",
"_id" : "mimori",
"_version" : 1,
"found" : true,
"_source":{ "name": "東郷美森" }
}
fedora$ curl -XGET 'http://192.168.122.89:9200/naruko/tweet/1?pretty=true'
{
"_index" : "naruko",
"_type" : "tweet",
"_id" : "1",
"_version" : 1,
"found" : true,
"_source":
{
"user" : "mimori",
"postDate": "2014-23-23T21:30:00",
"message" : "次こそはぼた餅食べてくださいね。有無は言わせない。"
}
}
既知の問題
さて、これでOSv上でelasticsearchが動作しましたが、現状ではelasticsearchを起動してそのまま放置しておくと、以下のエラーが発生してOSvが落ちてしまうようです。
CLIがまだCRaSHだった頃にelasticsearchを動かした時と同じエラーが発生しています...。
[backtrace]
0x00000000003ea99c <sched::timer_list::fired()+1100>
0x0000000000393576 <interrupt_descriptor_table::invoke_interrupt(unsigned int)+166>
0x000000000039369b <interrupt+91>
0x0000000000391ebc <???+3743420>
0x00000000003ed67f <sched::cpu::idle()+31>
0x00000000003ed6ae <???+4118190>
0x00000000003ed8e7 <thread_main_c+39>
0x0000000000391ee5 <???+3743461>
OSv上でアプリケーションが動くようになったら...
先述のような問題はありますが、OSvに何かアプリケーションを移植した場合は、OSvのMLにパッチを送ると取り込んでもらえるかもしれません。
パッチの送付方法は12/3のOSv Advent Calendarにて@deep_tkknさんがOSv のパッチを送るにはという記事を書かれているので、これに参考にします。
ただ、elasticsearchについては、まだLua CLIな環境で動作させるとこまでしかたどり着いてないので、make image=elasticsearchとか出来るようにするのはこれからです...。
まとめ
もっと早くにOSv Advent Calendarに記事を書こうと思っていたのですが、延び延びになっていました。
Javaアプリケーションであれば比較的簡単にOSvへの移植ができそうなので、他にも面白そうなアプリを探してみようと思います。
(それよりもパッチを送るのが先ですね...)