Tech Beans

Web企業で働くエンジニアのBlog


Elasticsearch 5.xの新機能と、1.xから5.xへのアップグレード


この記事は、Elastic stack Advent Calendar 2016の11日目の記事です。

Elasticsearch クラスタを1.7 から 5.0.2まで上げたときに、それなりに変更点が多く、苦労しました。

本記事では、そのときのノウハウを元に、

  • 1.xを使っていて、5.xに上げたいと思っている

人を主な対象に、アップグレードの注意点や、1.xからの追加・変更機能について書きたいと思います。

世の中的にすでに2.xの人が多いと思いますが、数ヶ月前にElasticsearch勉強会に参加した際に、まだ1.xを利用している人がそれなりにいたので、今でもまだ役に立つかなと思います。

とはいえ ver2.xからの変更点も含むので、今2.xを使っている人にも参考になるように書きます。

モチベーション

  • Reindex APIが使いたかった。
  • Kibanaでダッシュボードの共有URL(shorten url)が使いたかった
  • いい加減、上げたかった 技術的な興味

5.xで追加・変更される機能について

Elasticsearch

公式より個人的にうれしかったものから

  • バリデーション強化

IngestNodeなどが注目されるところですが、個人的にはまずいろいろなAPIのバリデーションが強化されており、何か間違っていてもすぐに分かるようになったというのが大きいです。

  • Reindex API
    • 2.xからありますが、クラスタからも取り込めるようになったみたいです。アップグレード時に大活躍してくれます(後述)
  • フィールド名にドットがまた使えるようになった。(後述)
  • Ingest Node
    • 目玉機能かと思いますが、まだプロダクトで使ってません。すでに他の記事があるので割愛
  • Indexing パフォーマンス改良
  • ドキュメントの類似度算出アルゴリズムがTFIDFからBM25に変更
  • Cluster Allocation Explain API
    • これまで運用している中で、度々「なぜかシャードアロケーションが進まない」といった出来事があり、よくよく調べてみるとdisk watermarkに引っかかっていたなど、わかりにくい状況が多かったので、その理由を詳細にレポートしてくれるAPIは便利そうです。
  • 独自のスクリプト言語Painlessの導入
  • search_after
    • ページング処理が楽にかけるようになりそう。そのうち別に記事を書きたいです。

Kibana

  • shorten URL
    • モチベーションの1つ
    • https://github.com/elastic/kibana/issues/1553
    • ログ監視していて、通知にこれをつけておくと超捗る
    • 公開短縮URLサービスを使えない場合も多いはず。
    • (追記 2016/12/12)
      • こちらの機能はすでにKibana4.4から導入されているので、Kibana5の機能ではありません。ES 2.2以上を使っていればKibana4.4も使えるので問題ないですね。 今回ES1.x からの差分として記載しています。ご指摘ありがとうございます。

f:id:soy_msk:20161211021259p:plain

  • Sense ( => Console ) がデフォルトで入ってる。

この他にも_cat/**APIが追加になっていたり、運用で触っていると、ところどころ使いやすくなっているなと感じます。起動時にカーネル設定もみてくれて、推奨値でない場合は警告を出してくれます。

ということで、機能というより、運用のしやすさが上がったと個人的には感じています。

残念だったところ

総じてよかったのですが、残念なところもあります。

  • head, HQと言ったWebUIを持つプラグインがことごとく使えない
    • Elasticsearch側の仕様変更によるものみたいですが、ヘビーユースしていただけに辛いです。Webサーバーとして別個に構築する方法や、そもそもkibanaにx-packいれてmarvelに乗り換えたりと、方法はいろいろありますが、コマンド一発でインストール&どのノードでもアクセス可能な魅力にはかなわず。
    • headに関して、Kibana pluginとして開発し直す話もあるようですが。。

5.xへのアップグレード

続いて、今回1.xからアップグレードする過程で注意する点やtipsをまとめます。

メジャーバージョン間でのアップグレードなので、ローリングアップグレードはできません。


JVM

java8必須になっています

また、JVMオプションの設定については これまで bin/elasticsearch.in.shなどに記述していましたが、conf/jvm.optionsという別ファイル切り出して記述することが推奨されています。

-Xms2g 
-Xmx2g




設定に関する変更

index.*** の設定

これまで config/elasticsearch.yml に書いていたindex.xxxの項目がかけなくなりました。

代わりにindex mappingに全てまとめられたようです。 例えば、今後作成するindexのデフォルト設定を変更したい場合は、index templateを利用すればよいかとおもいます。

PUT /_template/default_template
{
  "order":0,
  "template": "*",
  "settings": {
    "index": {
      "number_of_shards": "4",
      "number_of_replicas" : "2"
    }
  }
}




Index Mappingに関する変更

1.xからだとかなり変更があります

String 型の廃止

これまで文字列データに対してString型があり、analyzed, not_analyzedオプションで検索可能フィールドかどうか設定していましたが、5.xからはtext, keywordという新しい2つの文字列型が導入され、明確に区別しています。

文字列型のdynamic mappingがtextkeywordのマルチフィールドになっているので、何も考えずにデータを入れると、両方のフィールドができ、検索も可能になります。

それはいいのですが、容量もその分増える ことを考えると、データ量の多いフィールドなどはやはり事前にマッピング定義しておいたほうが無難かと思います。


インデックス内で同じ名前を持つフィールドは同じ型にしなければならない制約

これはtypeをまたいだフィールドにも適用されるので、

  • index1.type1.name
  • index1.type2.name

というフィールドは同じ型にしなければならないという制約が入っています。


'ドット'をフィールド名に持つフィールドの扱い

これは紆余曲折がありまして、2.xでドットフィールドが使えなくなりましたが、5.xでサポートが復活しています。

ただし まったく同じというわけではなく、ドットでつながったフィールドは内部的にハッシュオブジェクトとして管理されているため、例えば

A.B.C
A: object type
B: object type
C: *

となりますので、Aを別のフィールド名につかっているとNGです。

user: 'john' # keyword型としてまず登録
user.age: 10 # => userをobject型として使っているのでError

フィールド名に'ドット(.)' をが含まれるフィールドがある場合には注意が必要です。


クエリに関する変更

ver2.xで非推奨になったものも5.xでは廃止になっているので対応が必須です。

ファセットの廃止

これは2.xですでに廃止されているので今更ですが、1.xからの人には念のため。

1.7でもaggregationが使えるので、書き換えておきましょう。 aggregationの方が書きやすいですね。

filteredクエリの廃止

2.xでdeprecatedになっていたものが廃止になっています。 boolクエリに書き換えます

# ver1.x
"query": {
    "filtered": {
        "query": {"should": []},
        "filter": {}
    }
}
 
# ver5.x
"query": {
    "bool": {
        "should": [],
        "filter": {}
    }
}

他にも細々ありますが、問題になったのは上2つでした。

データ移行には Reindex APIを活用する

アップグレードに際し、自分は5.xのクラスタを新たに構築し、順次移行していく手順を取りました。

その際に困るのがデータ移行ですが、5.xになってリモートからの取り込み機能が追加されています。

これが超便利

POST _reindex
{
  "source": {
    "remote": {
      "host": "http://old-cluster-node:9200"
    },
    "index": "logstash-2016.10",
    "size": 1000 # chunk size
  },
  "script": {
    "inline": "ctx._source.put('new_field', ctx._source.remove('old_field'))"
  },
  "size": 100000 # total reindex docs
  "dest": {
    "index": "logstash-2016.10"
  }
}

これだけでデータコピーができてしまいます。簡単ですね。

さらにデータ移行と同時に、

  • script でフィールド名を書き換える
  • 1回あたりのコピーサイズを制限する

も行っています。

ただし、コピー元となるノードを予めコピー先クラスタの設定内に指定しておかないといけません。

# config/elasticsearch.yml
reindex.remote.whitelist: old-cluster-node:9200 

Kibanaのダッシュボード移行

これは元々Kibana4を使っていたので export/import機能を使えば直ぐにできました。 f:id:soy_msk:20161211015027p:plain

migration plugin

アップグレードする前にインストールしておくと、アップグレード後に非推奨、廃止になる機能を使っているインデックスに対してはWebUIで警告を出してくれ、どうすればよいかアドバイスしてくれます。

# install
$ ./bin/plugin -i migration -u https://github.com/elastic/elasticsearch-migration/releases/download/v1.18/elasticsearch-migration-1.18.zip

http://localhost:9200/_plugin/migration/ にアクセスすると診断してくれます。

試しにindex1.type1 にドット付きフィールドを入れてみました。 f:id:soy_msk:20161211015015p:plain

ただし、1.x => 2.x , 2.x => 5.x とプラグインが分かれていて、直接1.x => 5.xのmigrationをみてくれるわけではないので注意。

実際Reindex APIでデータ投入しちゃったほうが確実でした。

まとめ

まだメジャーバージョンが出たばかりというところですが、 プロダクションで使えるかという点においては、少なくともバックエンド的な使い方では十分使えそうという印象でした。

ただこの記事執筆時点ですでに5.1.1までリリースされており、そのリリースサイクルを見ると、今後も頻繁にアップグレードしていく必要はありそうです。