なんかかきたい

プログラミングなどの個人的なメモやサークル「ゆきいろパラソル」の情報を載せてます

elasticsearch 6.7を7.12までアップグレードする

こんにちは、百合好きインフラエンジニアです。最近はわたなれが熱いですね。

今回はelasticsearchのバージョンアップをやっていこうと思います。

本題

連休にやることもないのでelasticsearchをアップグレードすることにした。

elasticsearchは5以降、簡単に無停止でアップグレードできるようになっている。

公式ガイドを見ながらサクサクやっていく https://www.elastic.co/guide/en/elasticsearch/reference/current/setup-upgrade.html

elasticsearch 6.xは一旦6.8までアップグレードして、7.12までアップグレードする。 旧バージョンと新バージョンを混ぜて使うには互換性のあるバージョンを使いながらあげていく必要がある。 ガイドに書いてあるバージョンを選べば問題はない。 互換性のないバージョン間でアップグレードする場合はクラスタの再起動が必要なので一気にあげるのはおすすめしない。

その他、elasticsearchは古いバージョンで作ったインデックスも新しいバージョンで利用できるが、5以前のインデックスを7で利用する場合は、 スナップショットの復元で互換性がないのでインデックスの再構築をしておいた方がいい。 最近のバージョンにはreindex bulk APIがあるので、インデックスの構築は簡単。

まずelasticsearch 6.7を6.8まで上げるのは互換性の問題がほとんどないので気にせずあげていく。 elasticsearch 7にバージョンアップする際の注意は後方互換性のチェック。

https://www.elastic.co/guide/en/elasticsearch/reference/current/breaking-changes.html https://www.elastic.co/guide/en/elasticsearch/reference/current/breaking-changes-7.0.html

変更箇所がやや多めでクエリの実行でも問題が出る変更もある。 もちろん使っていなければ問題はないが、使い込んでいるほどハマるので注意。 Deprecation warningログを見ておけば事前に消える機能についてはわかる。

とりあえず今回ハマったところだけ書いていく

Cluster bootstrapping is required if discovery is configurededit

https://www.elastic.co/guide/en/elasticsearch/reference/current/breaking-changes-7.0.html#cluster_bootstrapping_is_required_if_discovery_is_configured https://www.elastic.co/guide/en/elasticsearch/reference/current/breaking-changes-7.0.html#discovery_configuration_is_required_in_production

これは設定を変えないといけない。discovery.zen.minimum_master_nodes はまだ使えるが、初期ノードの設定方法が変わったので変えておく。

flush and force_merge will no longer refreshedit

https://www.elastic.co/guide/en/elasticsearch/reference/current/breaking-changes-7.0.html#flush-force-merge-no-longer-refresh

まあこれは本運用では問題になることはないと思うけど、テストコードなのではインデックスの更新を _flush で更新しているケースがあるかもしれない。 7から _flush は機能しないので (そもそもドキュメントにないside-effectなのでよくない) 明確に _refresh を呼ぶ必要がある。

The _all metadata field is removededit

https://www.elastic.co/guide/en/elasticsearch/reference/current/breaking-changes-7.0.html#all-meta-field-removed

これはハマった問題ではないけど、ハマる人もいるかも。_allは6から非推奨で7で廃止される。 _allにはインデックスにいれるデータが全部入っていて便利なので以前は使うことがあったが、インデックスも肥大化するし、 そもそもこの動作に頼らず自分でインデックスに入れるものは選ぶべき

The default mapping is no longer allowededit

https://www.elastic.co/guide/en/elasticsearch/reference/current/breaking-changes-7.0.html#default-mapping-not-allowed https://www.elastic.co/jp/blog/moving-from-types-to-typeless-apis-in-elasticsearch-7-0

いまさらな話だが、昔elasticsearchにはtypeというものがあった。 typeはわかりにくいし、メリットもないということで廃止という方向になった。 もし今でもtypeを使っているならtypeを使わないようクエリやマッピングを修正する必要がある。

elasticsearch6.8には include_type_name オプションが追加されているため、とりあえず include_type_name を使えば、互換性を保ちながら7でも使うことはできる。 これは無停止バージョンアップのための一時的な措置なので、バージョンアップ後には include_type_name=false でも動作するようにする。 mappingの変更伴うので、indexの再構築が必要になるのでちょっとだるい。 インデックスの追加APIは代わりに _doc を使えば良い。

まあだいたいこんなところか。互換性のチェックは大変だが頑張って欲しい。xpackとかもあるかもしれない。

アップグレード作業

作業はとても簡単。 インデックスの再配置を止めて、1ノードを停止、アップグレードしてインデックスを再配置できるようにするの繰り返しだけでよい。 マシンを止めるときにインデックスの再配置が行われると面倒なので止めるというだけ。短時間の停止なのでアップグレードに伴う停止は問題はない。 再配置を許可すれば不足したインデックスはシャードからコピーされる。

アップグレードするクラスタのマシンで以下のAPIを叩いて再配置をやめる

curl -X PUT "localhost:9200/_cluster/settings?pretty" -H 'Content-Type: application/json' -d'
{
  "persistent": {
    "cluster.routing.allocation.enable": "primaries"
  }
}
'

elasticsearchを1台止めてアップグレードする。 コマンドは例。環境によって手順は違うがubuntuだと以下のようになる気がする。 pluginの更新が必要なら合わせてやっておく。

sudo systemctl stop elasticsearch.service
sudo apt install elasticsearch
sudo systemctl start elasticsearch.service

起動したらクラスタの仲間になるかチェックする

curl -X GET "localhost:9200/_cat/nodes?pretty"

再配置を許可する

curl -X PUT "localhost:9200/_cluster/settings?pretty" -H 'Content-Type: application/json' -d'
{
  "persistent": {
    "cluster.routing.allocation.enable": null
  }
}
'

データ量によっては再配置に時間がかかる場合もあるが、statusがgreenになるのを待つ。

curl -X GET "localhost:9200/_cat/health?v=true&pretty"

データが新ノードにも配置されたら、次のノードも同じようにアップグレードを繰り返す。 これを6.7->6.8->7.11とやればいい。コードがちゃんとしてればアップグレードは難しくない。