Amazon Elasticsearch Service を試してみた
近々導入する可能性もあって,検証も兼ねて,先月に Elasticsearch 2 系に対応した Amazon Elasticsearch Service を試してみた.
Elasticsearch domain を作成する
作成完了までのステップは計4個ある.
- Step 1: Define domain
- Step 2: Configure cluster
- Step 3: Set up access policy
- Step 4: Review
今回は以下のスペックで作成した.実際に運用する環境なら Node を増やして,Storage は gp2 以上にして,インスタンスタイプはユースケースに応じて考える必要がある.
- Domain Name
- Elasticsearch domain name
- kakakakakku
- Elasticsearch domain name
- Version
- Elasticsearch version
- 2.3
- Elasticsearch version
- Node configuration
- Instance count
- 1
- Instance type
- t2.micro.elasticsearch (Free tier eligible)
- Instance count
- Storage configuration
- Storage type
- EBS
- EBS volume type
- Magnetic
- EBS volume size
- 10
- Storage type
実際に起動 (Configuration state: Active) されるまでに10分程度待った.
起動後の状態を確認する
Elasticsearch 2.3.2 になっていた.
$ curl https://search-kakakakakku-xxx.ap-northeast-1.es.amazonaws.com/ { "name" : "Ringleader", "cluster_name" : "354924239642:kakakakakku", "version" : { "number" : "2.3.2", "build_hash" : "0944b4bae2d0f7a126e92b6133caf1651ae316cc", "build_timestamp" : "2016-05-20T07:46:04Z", "build_snapshot" : false, "lucene_version" : "5.5.0" }, "tagline" : "You Know, for Search" }
Amazon Elasticsearch Service の制約として,任意のプラグインをインストールすることはできないけど,analysis-kuromoji と kibana は入っていた.head 系は入ってないんだなぁ...!
$ curl https://search-kakakakakku-xxx.ap-northeast-1.es.amazonaws.com/_cat/plugins Ringleader analysis-icu 2.3.2 j Ringleader analysis-kuromoji 2.3.2 j Ringleader cloud-aws 2.3.2 j Ringleader elasticsearch-jetty 2.2.0 j Ringleader kibana 2.3.2 s /_plugin/kibana/
ドキュメントを登録する
試しに適当なドキュメントを登録してみた.普通に動いた.
$ curl -X PUT https://search-kakakakakku-xxx.ap-northeast-1.es.amazonaws.com/blog/articles/1 -d ' quote> { quote> "title": "xxx", quote> "body": "yyy", quote> "tags": ["z1", "z2"] quote> } quote> ' | jq . { "_index": "blog", "_type": "articles", "_id": "1", "_version": 1, "_shards": { "total": 2, "successful": 1, "failed": 0 }, "created": true } $ curl https://search-kakakakakku-xxx.ap-northeast-1.es.amazonaws.com/blog/articles/1 | jq . { "_index": "blog", "_type": "articles", "_id": "1", "_version": 1, "found": true, "_source": { "title": "xxx", "body": "yyy", "tags": [ "z1", "z2" ] } }
レストランデータをバルクで投入する
去年個人的に作った Elasticsearch ハンズオン資料に沿って,レストランデータをバルクで投入してみた.詳しくはハンズオン資料を参照で!
まず,マッピングを登録する.登録したマッピングは管理コンソールから確認することができる.
$ curl -X POST https://search-kakakakakku-xxx.ap-northeast-1.es.amazonaws.com/gourmet -d @mappings/restaurants.json {"acknowledged":true}%
加工したデータをバルクで投入したところエラーになった.ハンズオン資料に書いてある通り,独自構築の Elasticsearch なら elasticsearch.yml
の http.max_content_length
を広げることで対応できるけど,Amazon Elasticsearch Service の場合はインスタンスタイプによって制限されていた.
$ curl -X POST https://search-kakakakakku-xxx.ap-northeast-1.es.amazonaws.com/_bulk --data-binary @bulk_restaurants.json {"Message":"Request size exceeded 10485760 bytes"}%
ドキュメントだと Maximum size of HTTP request payloads
の部分に書いてあって,t2.micro.elasticsearch
の場合だと 10 MB
になっていた.もしバッチで大量のバルクをする可能性があるならインスタンスタイプの設計時に考慮しておくと良さそう.
今回はデータ量を100件に減らして投入することができた.
$ curl -X POST https://search-kakakakakku-xxx.ap-northeast-1.es.amazonaws.com/_bulk --data-binary @bulk_restaurants_100.json
レストランデータにクエリを投げてみる
普通にクエリを投げたら「application/x-www-form-urlencoded
の場合はクエリストリングを使えないよ」とエラーになった.調べたら elasticsearch-ruby
や Elastica
など各言語の Elasticsearch ライブラリに類似の Issues が出ていた.ふむ.
$ curl https://search-kakakakakku-xxx.ap-northeast-1.es.amazonaws.com/gourmet/restaurants/_search\?pretty -d ' quote> { quote> "query": { quote> "match": { "name": "焼肉" } quote> } quote> } quote> quote> ' {"message":"When Content-Type:application/x-www-form-urlencoded, URL cannot include query-string parameters (after '?'): '/gourmet/restaurants/_search?pretty'"}%
今回は application/x-www-form-urlencoded
ではなく,意図的に application/json
を指定して回避した.ワークアラウンド的な気もする.ちゃんとレストラン名に「焼肉」を含んでいる結果を取得することができた.
$ curl -H 'Content-Type:application/json' https://search-kakakakakku-xxx.ap-northeast-1.es.amazonaws.com/gourmet/restaurants/_search\?pretty -d ' { "query": { "match": { "name": "焼肉" } } } ' { "took" : 77, "timed_out" : false, "_shards" : { "total" : 5, "successful" : 5, "failed" : 0 }, "hits" : { "total" : 1, "max_score" : 0.79930615, "hits" : [ { "_index" : "gourmet", "_type" : "restaurants", "_id" : "20", "_score" : 0.79930615, "_source" : { "id" : "20", "name" : "焼肉フランス人", "property" : null, "alphabet" : null, "name_kana" : "やきにくふらんすじん", "pref_id" : "13", "area_id" : "7", "station_id1" : "3289", "station_time1" : "3", "station_distance1" : "220", "station_id2" : "8918", "station_time2" : "10", "station_distance2" : "772", "station_id3" : "2778", "station_time3" : "11", "station_distance3" : "848", "category_id1" : "402", "category_id2" : "0", "category_id3" : "0", "category_id4" : "0", "category_id5" : "0", "zip" : null, "address" : "港区六本木3-10-9ABIC六本木ビル3F", "north_latitude" : "35.39.36.421", "east_longitude" : "139.44.11.411", "description" : null, "purpose" : null, "open_morning" : "0", "open_lunch" : "0", "open_late" : "0", "photo_count" : "0", "special_count" : "0", "menu_count" : "0", "fan_count" : "0", "access_count" : "1452", "created_on" : "2000-09-10 11:22:02", "modified_on" : "2011-04-22 02:00:15", "closed" : "1" } } ] } }
N-Gram と形態素解析を確認する
全文検索をするなら必須の日本語処理も確認してみた.
N-Gram
今回は 2Gram と 3Gram でマッピングを定義していて,正常に動いた.
$ curl -H 'Content-Type:application/json' https://search-kakakakakku-xxx.ap-northeast-1.es.amazonaws.com/gourmet/_analyze\?tokenizer\=ngram_tokenizer\&pretty -d '東京都渋谷区で勤務しています' | grep token "tokens" : [ { "token" : "東京", "token" : "東京都", "token" : "京都", "token" : "京都渋", "token" : "都渋", "token" : "都渋谷", "token" : "渋谷", "token" : "渋谷区", "token" : "谷区", "token" : "谷区で", "token" : "区で", "token" : "区で勤", "token" : "で勤", "token" : "で勤務", "token" : "勤務", "token" : "勤務し", "token" : "務し", "token" : "務して", "token" : "して", "token" : "してい", "token" : "てい", "token" : "ていま", "token" : "いま", "token" : "います", "token" : "ます",
形態素解析
analysis-kuromoji を使った形態素解析も正常に動いた.
$ curl -H 'Content-Type:application/json' https://search-kakakakakku-xxx.ap-northeast-1.es.amazonaws.com/gourmet/_analyze\?tokenizer\=kuromoji\&pretty -d '東京都渋谷区で勤務しています' | grep token "tokens" : [ { "token" : "東京", "token" : "都", "token" : "渋谷", "token" : "区", "token" : "で", "token" : "勤務", "token" : "し", "token" : "て", "token" : "い", "token" : "ます",
Kibana を試してみた
Amazon Elasticsearch Service には Kibana もデフォルトで同梱されていて,普通に使うことができた.バージョンは Kibana Version 4.1.2-es-2.0
となっていた.
運用面を考える
稼働中のクラスタも Configure cluster でインスタンスタイプやディスクサイズを変更することができる.CloudSearch と違って自動スケールはしないため,CloudWatch でモニタリングしながら判断する必要がある.実際にインスタンスタイプを t2.micro.elasticsearch
から t2.small.elasticsearch
に変更してみたら,起動時と同様に10分程度待たされたけど,変更できた.
ちなみにインスタンスタイプの変更中も定期的にクエリを投げてみて 5xx 系が返ってくることは無かった.Amazon Elasticsearch Service は無停止でインスタンスタイプの変更ができるという理解で良いのだろうか?(追記 : FAQ にダウンタイムが無いと記載されていた)
Q: Amazon Elasticsearch ドメインをスケーリングするにはダウンタイムが必要ですか? いいえ。インスタンスおよびストレージボリュームの追加または変更による Amazon Elasticsearch ドメインのスケーリングはオンライン操作であり、ダウンタイムは必要ありません。
CloudWatch で取得できるメトリクスは充実してて良さそうだった.
その他はドキュメントにまとまっている.Amazon Elasticsearch Service のドキュメントは現時点だと日本語に翻訳されてなかった.
まとめ
Maximum size of HTTP request payloads
や URL cannot include query-string parameters
に少しハマったけど,普通にフルマネージドな Elasticsearch になっていて良かった.個人的に Elasticsearch は仕様や運用面で複雑だなと感じるところもあって,クラスタ運用を AWS に任せられるのはメリットだと思う.Reindex API などはまだ使えないらしく,今後のアップデートに期待したいところ.
あと個人的に作った Elasticsearch ハンズオン資料が便利だった(自画自賛).バージョンは 1.7 想定で作ってるけど,特にバージョンに依存しないような機能だけを使ってるので,今後 Elasticsearch に入門しようと思ってる人がいたら是非!
Black Belt
Amazon Elasticsearch Service の Black Belt 資料も合わせて読んでみた.
- Dedicated Master Nodes
- Split-brain を考慮して3台構成に
- Zone Awareness を ON にする
- クラスタを AZ に分散できる
- CloudSearch と Elasticsearch Service の比較
- Elasticsearch 2.3 だと Doc Values がデフォルトで有効になっている
- CloudWatch で JVM Memory Pressure を見て考える
- doc_values | Elasticsearch Reference [2.4] | Elastic
あと去年の AWS re:Invent 2015 の資料もあった.
www.slideshare.net