これは、なにをしたくて書いたもの?
Elasticsearch 6.6.0から、Index Lifecycle Management(ILM)というものが入っているようなので、こちらを試してみようかなと。
Release Notes / Elasticsearch 6.6.0 / New features
Index Lifecycle Management
・ Adds Index lifecycle feature #35193
以前は、Curatorというものがこの役割を行っていたみたいです。
Curator Reference [5.8] | Elastic
Index Lifecycle Management(ILM)とは?
Index Lifecycle Management(略してILM)について。
Managing the index lifecycle | Elasticsearch Reference [7.5] | Elastic
インデックスの管理の自動化の仕組みのようです。インデックステンプレートに、ILMを使って定義したライフサイクルポリシーを
紐付けることで、インデックステンプレートを元に作成されるインデックスにポリシーを紐付けます。この結果、指定されたスケジュールで
特定のアクションを実行したりすることができるようになったりします。
ILMでは、インデックスのライフサイクルを以下の4つのフェーズで管理します。
- Hot … このフェーズのインデックスは、よく更新、検索される
- Warm … インデックスはもう更新されなくなっているが、検索は行われる
- Cold … インデックスは更新もされないし、ほとんど検索もされない。検索自体は可能であるが、速度が遅くなっていてもかまわない
- Delete … このフェーズのインデックスは、もはや不要になっていて、削除しても大丈夫なもの
最初は、Hotフェーズで、上から下に向かって遷移します。
これらのフェーズの役割は目安のようなものみたいですが、各フェーズにいつ移行するかはライフサイクルポリシーで定めます。
各フェーズにはアクションを紐付けることができ、どのフェーズでどのようなアクションが実行可能かは決まっています。
Actions | Elasticsearch Reference [7.5] | Elastic
特定のフェーズでしか、実行できないアクションもあります。
たとえばHotフェーズではRolloverを行う、Warmフェーズではインデックスのシュリンクを行う、Deleteフェーズではインデックスの
削除を行ったりします。
クラスタ内で、各フェーズに対するノードを割り当てることで、同一クラスタ内でもHotフェーズのインデックスを持つノードは
スペックを高めに、WarmやColdフェーズのインデックスを持つノードは、Hotフェーズを持つノードと比べて低めのスペックで
構成する、といったことも可能なようです。
Elasticsearchでインデックスライフサイクル管理を使用してHot-Warm-Coldアーキテクチャーを実装 | Elastic Blog
ILMかCuratorか?
Curatorについて調べていくと、ILMと用途が被っているようにも思います。
Curator and Index Lifecycle Management | Curator Reference [5.8] | Elastic
そのあたりは、ドキュメントにも記載があります。
ILM or Curator? | Curator Reference [5.8] | Elastic
Basicライセンス以上を使う場合は、CuratorよりもILMを使った方がよいみたいです。
If ILM provides the functionality to manage your index lifecycle, and you have at least a Basic license, consider using ILM in place of Curator.
Filebeat 7.0以降は、デフォルトでILMを使用するようですし
Starting with version 7.0, Filebeat uses index lifecycle management by default when it connects to a cluster that supports lifecycle management.
LogstashもILMを使用するようです。
Logstash can use Index Lifecycle Management to automate the management of indices over time.
デフォルトで、ILMが利用可能かどうかの検出もするみたいですしね。
The use of Index Lifecycle Management is controlled by the ilm_enabled setting. By default, this will automatically detect whether the Elasticsearch instance supports ILM, and will use it if it is available.
CuratorとILMの併用も可能なようです。
ILM and Curator! | Curator Reference [5.8] | Elastic
併用する場合、allow_ilm_indicesオプションを指定しない限りは、CuratorはILMポリシーに関連付けられたインデックスにはなにもしない
ようです。
ILMとCuratorの大きな違いは、ILMがElasticsearch内で動作する仕組みなのに対して、CuratorはElasticsearchの外で動作する仕組み
ということでしょうか。Curatorを使う場合は、別途実行のためのジョブ(たとえばcronなど)を設定することになります。
試してみる
と、ここまでつらつら書いてきましたが、動かしてみないとよくわからないので、実際に試してみたいと思います。
環境
今回の環境は、こちら。
$ lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 18.04.3 LTS Release: 18.04 Codename: bionic $ java --version openjdk 11.0.5 2019-10-15 OpenJDK Runtime Environment (build 11.0.5+10-post-Ubuntu-0ubuntu1.118.04) OpenJDK 64-Bit Server VM (build 11.0.5+10-post-Ubuntu-0ubuntu1.118.04, mixed mode, sharing)
Elasticsearchは、7.5.1を使います。
$ curl localhost:9200 { "name" : "ubuntu1804.localdomain", "cluster_name" : "elasticsearch", "cluster_uuid" : "SZLLMXCmRjCZlo1SfMd7KA", "version" : { "number" : "7.5.1", "build_flavor" : "default", "build_type" : "deb", "build_hash" : "3ae9ac9a93c95bd0cdc054951cf95d88e1e18d96", "build_date" : "2019-12-16T22:57:37.835892Z", "build_snapshot" : false, "lucene_version" : "8.3.0", "minimum_wire_compatibility_version" : "6.8.0", "minimum_index_compatibility_version" : "6.0.0-beta1" }, "tagline" : "You Know, for Search" }
また、Elasticsearchが動作しているサーバーのIPアドレスは、192.168.33.12とします。
このIPアドレスは、あとで作成する、データ投入用のプログラムを動作させる時のみ使用します。
お題
Hotフェーズの例だとすぐRolloverとか出てきますが、ここはシンプルに指定の期間がすぎたらインデックスを削除する、というケースで
試します。
まずは、インデックスポリシーを登録します。
Set up index lifecycle management policy | Elasticsearch Reference [7.5] | Elastic
登録するインデックスポリシーは、こんな感じで作成。インデックスポリシーの名前は、「my_index_policy」とします。
$ curl -XPUT -H 'Content-Type: application/json' localhost:9200/_ilm/policy/my_index_policy -d ' { "policy": { "phases": { "hot": { "min_age": "1m", "actions": {} }, "warm": { "min_age": "3m", "actions": {} }, "delete": { "min_age": "7m", "actions": { "delete": {} } } } } } '
今回は、Hot、Warm、Deleteの3つのフェーズを使うことにします。Coldフェーズは書かないので、使われません(遷移もしません)。
min_ageは、デフォルトでは「インデックスを作成してからの時間」を指します。
Timing | Elasticsearch Reference [7.5] | Elastic
min_age is usually the time elapsed from the time the index is created, unless the index.lifecycle.origination_date index setting is configured, in which case the min_age will be the time elapsed since that specified date. If the index is rolled over, then min_age is the time elapsed from the time the index is rolled over. The intention here is to execute following phases and actions relative to when data was written last to a rolled over index.
なので、インデックスを作成してから1分後にHotフェーズへ、3分後にWarmフェーズへ、7分後にDeleteフェーズへと移っていきます。
※ちなみに、Hotになる前は「New」というフェーズになります
Deleteフェーズでは、アクションとしてインデックスの削除を行います。それ以外のフェーズでは、なにもアクションを行いません。
ドキュメントではWarmフェーズでインデックスをシュリンクするアクションを設定したり、
Timing | Elasticsearch Reference [7.5] | Elastic
HotフェーズでRolloverを行ったりするような設定例が記載されています。
Full Policy | Elasticsearch Reference [7.5] | Elastic
続いて、インデックステンプレートを登録し、この時にインデックスポリシーを紐付けます。
Applying a policy to an index template | Elasticsearch Reference [7.5] | Elastic
「index.lifecycle.name」で、今回作成したインデックスポリシーを指定しています。
$ curl -XPUT -H 'Content-Type: application/json' localhost:9200/_template/my_index_template -d ' { "index_patterns": ["my_index-*"], "settings": { "number_of_shards": 1, "number_of_replicas": 0, "index.lifecycle.name": "my_index_policy" } } '
インデックスを作る時に、インデックスポリシーを紐付けることもできるようです。
Apply a policy to a create index request | Elasticsearch Reference [7.5] | Elastic
ちなみに、ILMはKibanaで管理することができます。
作成も、Kibana上で行うことができます。
なのですが、指定できる時間の単位が日、時間と待ち時間が大きくなるので、今回は直接ElasticsearchにJSONで放り込むことにしました。
フェーズの遷移の管理を、分単位で設定していますからね。
次に、用意したインデックステンプレートを使って、インデックスを作り続けるサンプルプログラムを作りましょう。
$ pip3 install elasticsearch
インストールしたElasticsearchライブラリのバージョンと、Pythonのバージョン。
$ pip3 freeze elasticsearch==7.1.0 pkg-resources==0.0.0 urllib3==1.25.7 $ python3 -V Python 3.6.9
用意したプログラムはこちら。 ilm_example.py
from datetime import datetime from elasticsearch import Elasticsearch import time index_name_prefix = "my_index" index_alias = index_name_prefix sleep_sec = 10 elasticsearch_url = "http://192.168.33.12:9200" es = Elasticsearch([elasticsearch_url]) while True: now = datetime.now() now_str = now.strftime('%Y-%m-%d-%H.%M') index_name = f"{index_name_prefix}-{now_str}" id = int(now.timestamp()) doc = {"message": f"Hello!! {now_str}"} es.index(index = index_name, id = id, body = doc) print(f"write {now_str}...") time.sleep(sleep_sec)
10秒に1回データを投入しつつ、1分ごとに異なるインデックスを作成するプログラムになります。
実行。
$ python3 ilm_example.py
インデックスにデータが書き込まれていきます。
write 2020-01-09-01.21... write 2020-01-09-01.21... write 2020-01-09-01.22... write 2020-01-09-01.22...
cat APIで、見てみると
$ watch curl -s localhost:9200/_cat/indices?v
インデックスが増えていく様子が確認できます。
Every 2.0s: curl -s localhost:9200/_cat/indices?v ubuntu1804.localdomain: Wed Jan 8 16:22:58 2020 health status index uuid pri rep docs.count docs.deleted store.size pri.store.size green open .kibana_task_manager_1 HEDAc98pTYiPDjh1yJWbyg 1 0 2 1 51.7kb 51.7kb green open .apm-agent-configuration bpB7peSqRXmV4lDTDIwzxw 1 0 0 0 283b 283b green open my_index-2020-01-09-01.21 gGs-aFvVQjOtQngIhgdCIw 1 0 2 0 6.9kb 6.9kb green open .kibana_1 Oyyp7IHlRaKvitTwCYI-_A 1 0 5 0 13.3kb 13.3kb green open my_index-2020-01-09-01.22 eaSRXIwFSYqv11UppfWWsg 1 0 3 0 10.3kb 10.3kb
Kibanaの「Index Management」で見ると、できたばかりのインデックスは「New」と表示されます。
ドキュメントと違って、フェーズではなくフェーズになってますが…。
1分経過すると「Hot」になります。
3分経ったインデックスは「Warm」になり
7分経過したインデックスは「Delete」になります。
この情報は、Kibanaでなくとも、APIで確認できます。
Explain lifecycle API | Elasticsearch Reference [7.5] | Elastic
$ curl localhost:9200/my_index-2020-01-09-01.23/_ilm/explain?pretty { "indices" : { "my_index-2020-01-09-01.23" : { "index" : "my_index-2020-01-09-01.23", "managed" : true, "policy" : "my_index_policy", "lifecycle_date_millis" : 1578500580240, "age" : "3.8m", "phase" : "warm", "phase_time_millis" : 1578500763864, "action" : "complete", "action_time_millis" : 1578500580566, "step" : "complete", "step_time_millis" : 1578500763864, "phase_execution" : { "policy" : "my_index_policy", "phase_definition" : { "min_age" : "3m", "actions" : { } }, "version" : 1, "modified_date_in_millis" : 1578500401430 } } } }
今、どのフェーズにいるか(phase)、min_ageの計算に使われるタイムスタンプ(lifecycle_date_millis)、インデックスを作成してから
どれくらい経過したか(age)、今のフェーズに入った時の時間(phase_time_millis)などを確認することができます。
ところで、「Delete」フェーズに入ったインデックスですが、今回の設定ではすぐに消えるわけではありません。
Every 2.0s: curl -s localhost:9200/_cat/indices?v ubuntu1804.localdomain: Wed Jan 8 16:33:47 2020 health status index uuid pri rep docs.count docs.deleted store.size pri.store.size green open my_index-2020-01-09-01.30 Iz9JH9ifTtOPzG39WRgYLQ 1 0 3 0 10.3kb 10.3kb green open .apm-agent-configuration bpB7peSqRXmV4lDTDIwzxw 1 0 0 0 283b 283b green open .kibana_1 Oyyp7IHlRaKvitTwCYI-_A 1 0 6 11 11.2kb 11.2kb green open my_index-2020-01-09-01.29 6OkP64XRRCmun8Ge4WyPTQ 1 0 3 0 10.3kb 10.3kb green open my_index-2020-01-09-01.28 MhhcLFEtQgW8m_QcBat76Q 1 0 3 0 10.3kb 10.3kb green open .kibana_task_manager_1 HEDAc98pTYiPDjh1yJWbyg 1 0 2 1 51.7kb 51.7kb green open my_index-2020-01-09-01.25 rW-_yzWcSD2Vgb6pSVjCVA 1 0 6 0 14kb 14kb green open my_index-2020-01-09-01.24 ErkpWv7bSuO1M2moNrYMtw 1 0 6 0 14kb 14kb green open my_index-2020-01-09-01.27 najDdeJYTTKCb--X2g0qLA 1 0 6 0 14kb 14kb green open my_index-2020-01-09-01.26 0SICmJlPQX2JNFv5oDA5Dw 1 0 6 0 14kb 14kb green open my_index-2020-01-09-01.32 tP1lQEyHT0aEw8YQ6vCPWQ 1 0 3 0 10.3kb 10.3kb green open my_index-2020-01-09-01.21 gGs-aFvVQjOtQngIhgdCIw 1 0 2 0 7.1kb 7.1kb green open my_index-2020-01-09-01.31 yw7Idha-RECTZnF9Ztu7uA 1 0 3 0 10.3kb 10.3kb green open my_index-2020-01-09-01.23 mTwSYlBARqqf5zrsVCN4Mg 1 0 6 0 14kb 14kb green open my_index-2020-01-09-01.22 eaSRXIwFSYqv11UppfWWsg 1 0 5 0 14kb 14kb green open my_index-2020-01-09-01.33 6Chi4ylkTm2DGL39IKmP_w 1 0 3 0 10.3kb 10.3kb
「Delete」フェーズに入った、つまり作成してから7分経過したインデックスも、残っています。
これは、ILMがポリシーに対してインデックスを確認するタイミングが、デフォルトで10分間隔だからです。
Index lifecycle management settings | Elasticsearch Reference [7.5] | Elastic
「indices.lifecycle.poll_interval」という設定です。
今回は、分刻みでmin_ageを設定しているので、しばらく残るように見えてしまいます。
この間隔をたとえば1分間隔にして、すぐにElasticsearchに確認してもらうには、elasticsearch.ymlに以下のように設定して
Elasticsearchを再起動します。
indices.lifecycle.poll_interval: "1m"
こうすると、今回の設定では7分を超えて「Delete」フェーズになったインデックスは割とすぐに消えていきます。
とはいえ、今回のように分単位でフェーズを切り替えるなんてことはほぼないと思うので、こんなに短くすることはないと思いますが。
ちょっと設定方法、感覚がわかった気がします。
その他
Elasticsearchに対して、ILM自体の有効無効を切り替える場合は、こちらに記載のある「xpack.ilm.enabled」を設定します。
Index lifecycle management settings | Elasticsearch Reference [7.5] | Elastic
ILMをメンテナンスなどの理由で一時停止したり、停止したILMを再開する場合はこちら。
Start and stop index lifecycle management | Elasticsearch Reference [7.5] | Elastic