チュートリアル: ILMを使用したロールオーバーの自動化

Elasticsearchにタイムスタンプ付きのドキュメントを継続的にインデックスする場合、通常はデータストリームを使用して、新しいインデックスに定期的にロールオーバーします。これにより、最新のデータに対するパフォーマンス要件を満たし、コストを時間とともに管理し、保持ポリシーを強制し、データを最大限に活用するためのホット-ウォーム-コールドアーキテクチャを実装できます。

データストリームは、追加専用のユースケースに最適です。既存の時系列データを更新または削除する必要がある場合は、データストリームのバックインデックスに直接更新または削除操作を実行できます。同じ_idを使用して複数のドキュメントを送信し、最後の書き込みが勝つことを期待する場合は、代わりに書き込みインデックスを持つインデックスエイリアスを使用することをお勧めします。それでも、ILMを使用してエイリアスのインデックスを管理し、ロールオーバーできます。データストリームなしで時系列データを管理するにスキップします。

データストリームを使用した時系列データの管理

ILMを使用してデータストリームのロールオーバーと管理を自動化するには、次の手順を実行します:

BeatsまたはLogstash Elasticsearch出力プラグインのインデックスライフサイクル管理を有効にすると、ライフサイクルポリシーは自動的に設定されます。他のアクションを実行する必要はありません。デフォルトのポリシーはKibana ManagementまたはILM APIを通じて変更できます。

ライフサイクルポリシーの作成

ライフサイクルポリシーは、インデックスライフサイクルのフェーズと各フェーズで実行するアクションを指定します。ライフサイクルには最大5つのフェーズを持つことができます: hot, warm, cold, frozen, および delete

たとえば、timeseries_policyを定義することができます。これは2つのフェーズを持ちます:

  • hotフェーズは、インデックスが50ギガバイトのmax_primary_shard_sizeまたは30日のmax_ageに達したときにロールオーバーアクションを指定します。
  • deleteフェーズは、ロールオーバー後90日でインデックスを削除するmin_ageを設定します。
  1. Kibanaを通じてポリシーを作成するか、[ポリシーの作成または更新](/read/elasticsearch-8-15/442f4ad969cabca9.md) APIを使用して作成できます。Kibanaからポリシーを作成するには、メニューを開き、**Stack Management
  2. > Index Lifecycle Policies**に移動します。**Create policy**をクリックします。
  3. ![ポリシー作成ページ](https://cdn.hedaai.com/projects/elasticsearch-8-15/df21fadf01c3c28b56b589b07d730399.png_big1500.jpeg)
  4. APIの例
  5. #### Python
  6. ``````python
  7. resp = client.ilm.put_lifecycle(
  8. name="timeseries_policy",
  9. policy={
  10. "phases": {
  11. "hot": {
  12. "actions": {
  13. "rollover": {
  14. "max_primary_shard_size": "50GB",
  15. "max_age": "30d"
  16. }
  17. }
  18. },
  19. "delete": {
  20. "min_age": "90d",
  21. "actions": {
  22. "delete": {}
  23. }
  24. }
  25. }
  26. },
  27. )
  28. print(resp)
  29. `

Ruby

  1. response = client.ilm.put_lifecycle(
  2. policy: 'timeseries_policy',
  3. body: {
  4. policy: {
  5. phases: {
  6. hot: {
  7. actions: {
  8. rollover: {
  9. max_primary_shard_size: '50GB',
  10. max_age: '30d'
  11. }
  12. }
  13. },
  14. delete: {
  15. min_age: '90d',
  16. actions: {
  17. delete: {}
  18. }
  19. }
  20. }
  21. }
  22. }
  23. )
  24. puts response

Js

  1. const response = await client.ilm.putLifecycle({
  2. name: "timeseries_policy",
  3. policy: {
  4. phases: {
  5. hot: {
  6. actions: {
  7. rollover: {
  8. max_primary_shard_size: "50GB",
  9. max_age: "30d",
  10. },
  11. },
  12. },
  13. delete: {
  14. min_age: "90d",
  15. actions: {
  16. delete: {},
  17. },
  18. },
  19. },
  20. },
  21. });
  22. console.log(response);

コンソール

  1. PUT _ilm/policy/timeseries_policy
  2. {
  3. "policy": {
  4. "phases": {
  5. "hot": {
  6. "actions": {
  7. "rollover": {
  8. "max_primary_shard_size": "50GB",
  9. "max_age": "30d"
  10. }
  11. }
  12. },
  13. "delete": {
  14. "min_age": "90d",
  15. "actions": {
  16. "delete": {}
  17. }
  18. }
  19. }
  20. }
  21. }
min_ageのデフォルトは0msであるため、新しいインデックスはhotフェーズにすぐに入ります。
条件のいずれかが満たされたときにrolloverアクションをトリガーします。
ロールオーバー後90日でインデックスをdeleteフェーズに移動します。
インデックスが削除フェーズに入るときにdeleteアクションをトリガーします。

データストリームを作成し、ライフサイクルポリシーを適用するためのインデックステンプレートの作成

データストリームを設定するには、まずライフサイクルポリシーを指定するインデックステンプレートを作成します。テンプレートはデータストリーム用であるため、data_streamの定義も含める必要があります。

たとえば、timeseries_templateを作成して、将来のデータストリームtimeseriesに使用することができます。

ILMがデータストリームを管理できるようにするために、テンプレートは1つのILM設定を構成します:

  • index.lifecycle.nameは、データストリームに適用するライフサイクルポリシーの名前を指定します。

Kibanaのテンプレート作成ウィザードを使用してテンプレートを追加できます。Kibanaからメニューを開き、**Stack Management

Index Managementに移動します。Index Templatesタブで、Create template**をクリックします。

テンプレート作成ページ

このウィザードは、指定したオプションでインデックステンプレートを作成するためにインデックステンプレートの作成または更新APIを呼び出します。

APIの例

Python

  1. resp = client.indices.put_index_template(
  2. name="timeseries_template",
  3. index_patterns=[
  4. "timeseries"
  5. ],
  6. data_stream={},
  7. template={
  8. "settings": {
  9. "number_of_shards": 1,
  10. "number_of_replicas": 1,
  11. "index.lifecycle.name": "timeseries_policy"
  12. }
  13. },
  14. )
  15. print(resp)

Ruby

  1. response = client.indices.put_index_template(
  2. name: 'timeseries_template',
  3. body: {
  4. index_patterns: [
  5. 'timeseries'
  6. ],
  7. data_stream: {},
  8. template: {
  9. settings: {
  10. number_of_shards: 1,
  11. number_of_replicas: 1,
  12. 'index.lifecycle.name' => 'timeseries_policy'
  13. }
  14. }
  15. }
  16. )
  17. puts response

Js

  1. const response = await client.indices.putIndexTemplate({
  2. name: "timeseries_template",
  3. index_patterns: ["timeseries"],
  4. data_stream: {},
  5. template: {
  6. settings: {
  7. number_of_shards: 1,
  8. number_of_replicas: 1,
  9. "index.lifecycle.name": "timeseries_policy",
  10. },
  11. },
  12. });
  13. console.log(response);

コンソール

  1. PUT _index_template/timeseries_template
  2. {
  3. "index_patterns": ["timeseries"],
  4. "data_stream": { },
  5. "template": {
  6. "settings": {
  7. "number_of_shards": 1,
  8. "number_of_replicas": 1,
  9. "index.lifecycle.name": "timeseries_policy"
  10. }
  11. }
  12. }
ドキュメントがtimeseriesターゲットにインデックスされるときにテンプレートを適用します。
データストリームを管理するために使用されるILMポリシーの名前。

データストリームの作成

まず、インデックステンプレートindex_patternsで定義された名前またはワイルドカードパターンにドキュメントをインデックスします。既存のデータストリーム、インデックス、またはインデックスエイリアスがすでにその名前を使用していない限り、インデックスリクエストは自動的に対応するデータストリームを作成し、単一のバックインデックスを持ちます。Elasticsearchは、リクエストのドキュメントをこのバックインデックスに自動的にインデックスし、これもストリームの書き込みインデックスとして機能します。

たとえば、次のリクエストはtimeseriesデータストリームと最初の世代のバックインデックス.ds-timeseries-2099.03.08-000001を作成します。

Python

  1. resp = client.index(
  2. index="timeseries",
  3. document={
  4. "message": "logged the request",
  5. "@timestamp": "1591890611"
  6. },
  7. )
  8. print(resp)

Ruby

  1. response = client.index(
  2. index: 'timeseries',
  3. body: {
  4. message: 'logged the request',
  5. "@timestamp": '1591890611'
  6. }
  7. )
  8. puts response

Js

  1. const response = await client.index({
  2. index: "timeseries",
  3. document: {
  4. message: "logged the request",
  5. "@timestamp": "1591890611",
  6. },
  7. });
  8. console.log(response);

コンソール

  1. POST timeseries/_doc
  2. {
  3. "message": "logged the request",
  4. "@timestamp": "1591890611"
  5. }

ロールオーバー条件がライフサイクルポリシーで満たされると、rolloverアクションは:

  • 2世代目のバックインデックス.ds-timeseries-2099.03.08-000002を作成します。これはtimeseriesデータストリームのバックインデックスであるため、timeseries_templateインデックステンプレートからの設定が新しいインデックスに適用されます。
  • timeseriesデータストリームの最新世代インデックスであるため、新しく作成されたバックインデックス.ds-timeseries-2099.03.08-000002がデータストリームの書き込みインデックスになります。

このプロセスは、ロールオーバー条件が満たされるたびに繰り返されます。timeseries_policyによって管理されるデータストリームのすべてのバックインデックスをtimeseriesデータストリーム名で検索できます。書き込み操作はデータストリーム名に送信され、現在の書き込みインデックスにルーティングされます。データストリームに対する読み取り操作は、すべてのバックインデックスによって処理されます。

ライフサイクルの進行状況を確認

管理されたインデックスのステータス情報を取得するには、ILM説明APIを使用します。これにより、次のような情報を確認できます:

  • インデックスがどのフェーズにあり、そのフェーズに入った時期。
  • 現在のアクションと実行中のステップ。
  • エラーが発生したか、進行がブロックされているか。

たとえば、次のリクエストはtimeseriesデータストリームのバックインデックスに関する情報を取得します:

Python

  1. resp = client.ilm.explain_lifecycle(
  2. index=".ds-timeseries-*",
  3. )
  4. print(resp)

Ruby

  1. response = client.ilm.explain_lifecycle(
  2. index: '.ds-timeseries-*'
  3. )
  4. puts response

Js

  1. const response = await client.ilm.explainLifecycle({
  2. index: ".ds-timeseries-*",
  3. });
  4. console.log(response);

コンソール

  1. GET .ds-timeseries-*/_ilm/explain

次のレスポンスは、データストリームの最初の世代バックインデックスがhotフェーズのrolloverアクションを待機していることを示しています。この状態のままで、ILMはロールオーバー条件が満たされるまでcheck-rollover-readyを呼び出し続けます。

コンソール-結果

  1. {
  2. "indices": {
  3. ".ds-timeseries-2099.03.07-000001": {
  4. "index": ".ds-timeseries-2099.03.07-000001",
  5. "index_creation_date_millis": 1538475653281,
  6. "time_since_index_creation": "30s",
  7. "managed": true,
  8. "policy": "timeseries_policy",
  9. "lifecycle_date_millis": 1538475653281,
  10. "age": "30s",
  11. "phase": "hot",
  12. "phase_time_millis": 1538475653317,
  13. "action": "rollover",
  14. "action_time_millis": 1538475653317,
  15. "step": "check-rollover-ready",
  16. "step_time_millis": 1538475653317,
  17. "phase_execution": {
  18. "policy": "timeseries_policy",
  19. "phase_definition": {
  20. "min_age": "0ms",
  21. "actions": {
  22. "rollover": {
  23. "max_primary_shard_size": "50gb",
  24. "max_age": "30d"
  25. }
  26. }
  27. },
  28. "version": 1,
  29. "modified_date_in_millis": 1539609701576
  30. }
  31. }
  32. }
  33. }
インデックスのロールオーバーを計算するために使用されるインデックスの年齢はmax_age
インデックスを管理するために使用されるポリシー
次のフェーズに移行するためにインデックスされた年齢(この場合、インデックスの年齢と同じです)。
ILMがインデックスで実行しているステップ
現在のフェーズの定義(hotフェーズ)

データストリームなしで時系列データを管理

データストリームは、時系列データをスケールし管理する便利な方法ですが、追加専用に設計されています。データをその場で更新または削除する必要があるユースケースがあることを認識しており、データストリームは削除および更新リクエストを直接サポートしていないため、インデックスAPIをデータストリームのバックインデックスに直接使用する必要があります。これらのケースでも、データストリームの使用をお勧めします。

同じ_idを使用して複数のドキュメントを送信し、最後の書き込みが勝つことを期待する場合は、データストリームの代わりにインデックスエイリアスを使用して、時系列データを含むインデックスを管理し、定期的に新しいインデックスにロールオーバーすることができます。

ILMを使用してインデックスエイリアスで時系列インデックスのロールオーバーと管理を自動化するには、次の手順を実行します:

ライフサイクルポリシーを適用するためのインデックステンプレートの作成

ロールオーバー時に新しい書き込みインデックスにライフサイクルポリシーを自動的に適用するには、新しいインデックスを作成するために使用されるインデックステンプレートでポリシーを指定します。

たとえば、timeseries_templateを作成して、新しいインデックスの名前がtimeseries-*インデックスパターンに一致するように適用します。

自動ロールオーバーを有効にするために、テンプレートは2つのILM設定を構成します:

  • index.lifecycle.nameは、インデックスパターンに一致する新しいインデックスに適用するライフサイクルポリシーの名前を指定します。
  • index.lifecycle.rollover_aliasは、インデックスのロールオーバーアクションがトリガーされたときにロールオーバーされるインデックスエイリアスを指定します。

Kibanaのテンプレート作成ウィザードを使用してテンプレートを追加できます。ウィザードにアクセスするには、メニューを開き、**Stack Management

Index Managementに移動します。Index Templatesタブで、Create template**をクリックします。

テンプレート作成ページ

例のテンプレートの作成テンプレストリクエストは次のようになります:

Python

  1. resp = client.indices.put_index_template(
  2. name="timeseries_template",
  3. index_patterns=[
  4. "timeseries-*"
  5. ],
  6. template={
  7. "settings": {
  8. "number_of_shards": 1,
  9. "number_of_replicas": 1,
  10. "index.lifecycle.name": "timeseries_policy",
  11. "index.lifecycle.rollover_alias": "timeseries"
  12. }
  13. },
  14. )
  15. print(resp)

Js

  1. const response = await client.indices.putIndexTemplate({
  2. name: "timeseries_template",
  3. index_patterns: ["timeseries-*"],
  4. template: {
  5. settings: {
  6. number_of_shards: 1,
  7. number_of_replicas: 1,
  8. "index.lifecycle.name": "timeseries_policy",
  9. "index.lifecycle.rollover_alias": "timeseries",
  10. },
  11. },
  12. });
  13. console.log(response);

コンソール

  1. PUT _index_template/timeseries_template
  2. {
  3. "index_patterns": ["timeseries-*"],
  4. "template": {
  5. "settings": {
  6. "number_of_shards": 1,
  7. "number_of_replicas": 1,
  8. "index.lifecycle.name": "timeseries_policy",
  9. "index.lifecycle.rollover_alias": "timeseries"
  10. }
  11. }
  12. }
インデックスの名前がtimeseries-で始まる場合、新しいインデックスにテンプレートを適用します。
各新しいインデックスに適用するライフサイクルポリシーの名前。
これらのインデックスを参照するために使用されるエイリアスの名前。
必須: ロールオーバーアクションを使用するポリシーに必要です。

書き込みインデックスエイリアスで初期の時系列インデックスをブートストラップ

まず、初期インデックスをブートストラップし、インデックステンプレートで指定されたロールオーバーエイリアスの書き込みインデックスとして指定する必要があります。このインデックスの名前は、テンプレートのインデックスパターンと一致し、数字で終わる必要があります。ロールオーバー時に、この値はインデックスの新しい名前を生成するためにインクリメントされます。

たとえば、次のリクエストはtimeseries-000001というインデックスを作成し、timeseriesエイリアスの書き込みインデックスにします。

Python

  1. resp = client.indices.create(
  2. index="timeseries-000001",
  3. aliases={
  4. "timeseries": {
  5. "is_write_index": True
  6. }
  7. },
  8. )
  9. print(resp)

Js

  1. const response = await client.indices.create({
  2. index: "timeseries-000001",
  3. aliases: {
  4. timeseries: {
  5. is_write_index: true,
  6. },
  7. },
  8. });
  9. console.log(response);

コンソール

  1. PUT timeseries-000001
  2. {
  3. "aliases": {
  4. "timeseries": {
  5. "is_write_index": true
  6. }
  7. }
  8. }

ロールオーバー条件が満たされると、rolloverアクションは:

  • timeseries-000002という新しいインデックスを作成します。これはtimeseries-*パターンに一致するため、timeseries_templateからの設定が新しいインデックスに適用されます。
  • 新しいインデックスを書き込みインデックスとして指定し、ブートストラップインデックスを読み取り専用にします。

このプロセスは、ロールオーバー条件が満たされるたびに繰り返されます。timeseries_policyによって管理されるすべてのインデックスをtimeseriesエイリアスで検索できます。書き込み操作はエイリアスに送信され、現在の書き込みインデックスにルーティングされます。

ライフサイクルの進行状況を確認

管理されたインデックスのステータス情報を取得することは、データストリームの場合と非常に似ています。データストリームの進行状況を確認するセクションを参照してください。唯一の違いはインデックスの名前空間であるため、進行状況を取得するには次のAPI呼び出しが必要です:

Python

  1. resp = client.ilm.explain_lifecycle(
  2. index="timeseries-*",
  3. )
  4. print(resp)

Ruby

  1. response = client.ilm.explain_lifecycle(
  2. index: 'timeseries-*'
  3. )
  4. puts response

Js

  1. const response = await client.ilm.explainLifecycle({
  2. index: "timeseries-*",
  3. });
  4. console.log(response);

コンソール

  1. GET timeseries-*/_ilm/explain