最適なシャードサイジング:クラスターのパフォーマンスと管理のバランス

Elasticsearchのシャードサイジングをマスターして、クラスターパフォーマンスを最適化します。このガイドでは、シャード数とサイズのトレードオフを探り、データ量、インデックス負荷、クエリパターンなどの重要な考慮事項について説明します。最適なシャード割り当ての計算、時間ベースのインデックスの活用、Index Lifecycle Management(ILM)の実装に関するベストプラクティスを学び、スケーラブルで効率的なElasticsearchクラスターを構築します。

最適なシャードサイジング:クラスターのパフォーマンスと管理のバランス

シャードサイジングは、クラスターが数ヶ月稼働するまでは単純に見えるElasticsearchの判断の1つです。シャードは内部的には単なるLuceneインデックスですが、すべてのシャードにはオーバーヘッドがあります。小さなシャードが多すぎると、クラスターはメタデータと小さな検索ターゲットの管理に忙しくなります。大きなシャードが少なすぎると、再配置、リカバリ、および一部の検索が非常に遅くなります。

すべてのクラスターに有効な普遍的なシャードサイズはありません。毎日ロールオーバーするロギングクラスター、製品検索インデックス、セキュリティ分析クラスターはすべて異なる動作をします。有用なアプローチは、ターゲットシャードサイズを選択し、その周りにロールオーバーまたはインデックス作成を設計し、実際のインデックス作成とクエリ動作から調整することです。

Elasticsearchシャードの基礎

サイジング戦略に入る前に、基本的な概念を理解することが不可欠です:

  • インデックス:ドキュメントのコレクション。Elasticsearchでは、インデックスは複数のシャードに分割されます。
  • シャード:分散の単位。各シャードは自己完結型のLuceneインデックスです。インデックスは複数のシャードを含むことができ、クラスター内の異なるノードに分散されます。
  • プライマリシャード:インデックスが作成されると、いくつかのプライマリシャードが割り当てられます。これらのシャードはデータがインデックスされる場所です。既存のインデックスのnumber_of_shardsを単純に編集することはできませんが、Elasticsearchは特定の条件下で分割および縮小操作を提供します。多くのチームは、後で変更するには計画が必要なため、プライマリシャード数を設計時の決定として扱います。
  • レプリカシャード:プライマリシャードのコピー。冗長性を提供し、読み取りスループットを向上させます。プライマリシャードが失敗した場合、レプリカがプライマリに昇格できます。レプリカシャードの数はいつでも変更できます。

シャードがパフォーマンスに与える影響

  • インデックス作成パフォーマンス:各シャードはインデックス作成にリソースを必要とします。シャードが多いほど、リクエストを管理するコーディネーティングノードのオーバーヘッドが大きくなります。ただし、シャードが大きくなりすぎると、単一のシャードへのインデックス作成がボトルネックになる可能性があります。
  • クエリパフォーマンス:検索リクエストは、関連するすべてのプライマリシャードに分散されます。シャードの数が多いと、処理する必要があるリクエストの数が増え、レイテンシが増加する可能性があります。逆に、非常に大きなシャードは、Luceneがそのシャード内でより多くのデータを処理する必要があるため、検索時間が長くなる可能性があります。
  • クラスター管理:シャードの数が多いと、クラスター状態の管理を担当するマスターノードの負荷が増加します。また、シャードの再配置、スナップショット、リカバリなどの操作のオーバーヘッドにも影響します。
  • リソース使用率:各シャードはメモリとディスクI/Oを消費します。シャードが多すぎると、ノードのリソースが枯渇し、パフォーマンスの低下やノードの不安定性につながる可能性があります。

シャードサイジングの重要な考慮事項

「理想的な」シャードサイズは固定された数値ではありません。特定のワークロード、データ特性、ハードウェアによって異なります。ただし、いくつかの要因が決定を導く必要があります:

1. データ量と成長率

  • 現在のデータサイズ:現在インデックスにどれだけのデータがありますか?
  • 成長率:データはどのくらいの速さで成長していますか?これは将来のシャードサイズを予測するのに役立ちます。
  • データ保持ポリシー:古いデータを削除しますか?これはアクティブなデータの実効サイズに影響します。

2. インデックス負荷

  • インデックスレート:1秒あたり何ドキュメントをインデックスしていますか?
  • ドキュメントサイズ:個々のドキュメントの平均サイズはどれくらいですか?
  • インデックススループット:ノードは現在のシャード構成でインデックス負荷を処理できますか?

3. クエリパターン

  • クエリの複雑さ:クエリは単純なキーワード検索ですか、それとも複雑な集計ですか?
  • クエリ頻度:データに対してどのくらいの頻度でクエリが実行されますか?
  • クエリレイテンシ要件:許容される応答時間はどれくらいですか?

4. クラスタートポロジとリソース

  • ノード数:クラスターにはいくつのノードがありますか?
  • ノードハードウェア:CPU、RAM、ディスク(ElasticsearchにはSSDを強く推奨)。
  • シャード制限:Elasticsearchには、ノードが過剰な数のオープンシャードを保持するのを防ぐ安全制限が含まれています。最近のバージョンでは、通常のオープンインデックスに対するクラスター全体のガードレールとしてcluster.max_shards_per_nodeが一般的に使用されています。cluster.routing.allocation.total_shards_per_nodeは異なります。これは、単一のインデックスまたは一致する割り当てスコープからのシャードが1つのノードに割り当てられる数を制限します。これらの設定を変更する前に、Elasticsearchのバージョンを確認してください。

シャード割り当てのベストプラクティス

1. ターゲットシャードサイズを目指す

魔法の数はありませんが、多くの本番クラスターは、一般的なログおよび検索ワークロードに対して、約10GBから50GBのシャードを目指しています。その範囲は出発点であり、ルールではありません。非常に高スループットまたは長期保持のシステムは、テスト後に大きなシャードを選択する場合があります。小規模なビジネス検索インデックスは、単一の小さなシャードで最適に機能する場合があります。

  • 小さすぎる(< 10GB):過剰なオーバーヘッドにつながる可能性があります。各シャードにはメモリフットプリントがあり、マスターノードの負荷に貢献します。数千の小さなシャードを管理することは、重要な運用上の負担になります。
  • 大きすぎる(> 50GB):パフォーマンスの問題を引き起こす可能性があります。セグメントのマージ、リカバリ、リバランス操作に時間がかかります。大きなシャードが失敗した場合、リカバリにかなりの時間がかかる可能性があります。

2. 時間ベースのインデックスを検討する

時系列データ(ログ、メトリクス、イベント)の場合、時間ベースのインデックスを使用することは、標準的で非常に効果的な方法です。これには、特定の期間(例:日次、週次、月次)ごとに新しいインデックスを作成することが含まれます。

  • :1つの巨大なインデックスの代わりに、logs-2023.10.26logs-2023.10.27などがあります。
  • 利点:データ管理が容易(Index Lifecycle Management - ILMによる古いインデックスの削除)、クエリが多くの場合最近のデータを対象とするためパフォーマンスが向上、シャードサイズを制御可能。

3. Index Lifecycle Management(ILM)を実装する

ILMポリシーを使用すると、経過時間、サイズ、またはドキュメント数に基づいてインデックス管理を自動化できます。インデックスのフェーズ(hot、warm、cold、delete)を定義し、レプリカ数の変更、インデックスの縮小、削除などの各フェーズのアクションを指定できます。

  • Hotフェーズ:インデックスはアクティブに書き込みとクエリが行われています。パフォーマンスを最大化します。
  • Warmフェーズ:インデックスは書き込まれなくなりましたが、まだクエリされています。パフォーマンスの低いハードウェアに移動でき、レプリカを減らしたり縮小したりできます。
  • Coldフェーズ:クエリの頻度が低い。Elasticsearchのライセンス、バージョン、アーキテクチャに応じて、データをより安価なストレージまたは低パフォーマンスのノードに移動できます。
  • Deleteフェーズ:データは不要になり、削除されます。

4. 過剰シャーディングを避ける

過剰シャーディングは、クラスターのサイズとデータ量に対してシャードが多すぎる場合に発生します。これは、パフォーマンスの低下と管理の問題につながる一般的な落とし穴です。

  • 症状:マスターノードのCPU使用率が高い、クラスター状態の更新が遅い、リカバリ時間が長い、全体的な動作が遅い。
  • 緩和策:最初からプライマリシャード数を計画します。時間ベースのインデックスの場合、インデックスごとに妥当な数のプライマリシャード(例:1または3)から始めます。後でレプリカを追加することはいつでもできます。

5. 過剰インデックスを作成しない

同様に、必要でない場合に過剰な数のインデックスを作成しないでください。各インデックスはオーバーヘッドを追加します。自然な分割メカニズムがない非時系列データの場合は、適切なシャード数を持つ単一のインデックスで十分かどうかを検討してください。

6. number_of_shards設定を考慮する

インデックスを作成するとき、number_of_shardsパラメータはプライマリシャードの数を定義します。この設定はインデックス作成後は変更できません。

PUT my-index
{
  "settings": {
    "index": {
      "number_of_shards": 3,  // 例:3つのプライマリシャード
      "number_of_replicas": 1   // 例:1つのレプリカシャード
    }
  }
}
  • ヒント:小さなインデックスやインデックス/クエリ負荷が非常に低いものには、単一のプライマリシャードで十分な場合があります。より大きく、よりアクティブなインデックスには、3または5つのプライマリシャードが、特に後でインデックスを分割する予定がある場合(分割は複雑ですが)、より良い分散と回復力を提供できます。

7. リバランスと再配置

Elasticsearchは、ノード間で均等に分散されるようにシャードを自動的にリバランスします。ただし、シャードが大きすぎると、これらの操作はリソースを大量に消費し、遅くなる可能性があります。より小さく、より多くのシャードは、より速くリバランスできる場合がありますが、これはより多くのシャードを管理するオーバーヘッドによって相殺されます。

8. クエリパフォーマンスのチューニング

クエリパフォーマンスが低下している場合は、シャード戦略を評価してください。以下を検討してください:

  • シャード数:シャードが多すぎると、調整オーバーヘッドが増加する可能性があります。
  • シャードサイズ:非常に大きなシャードは、セグメントのマージとシャード内の検索を遅くする可能性があります。
  • インデックス設計:適切なマッピングとアナライザを使用していますか?

最適なシャード数の計算

単一の公式はありませんが、ここに一般的なアプローチがあります:

  1. ライフサイクル全体のインデックスあたりの総データ量を見積もります。
  2. ターゲットシャードサイズを決定します(例:30GB)。
  3. 必要なプライマリシャードの数を計算します総データ量 / ターゲットシャードサイズ
  4. 切り上げて最も近い整数にします。これがインデックスのnumber_of_shardsになります。
    • :90GBのデータを見込んでいて、30GBのシャードを目指す場合、90GB / 30GB = 3つのプライマリシャードが必要です。
  5. 回復力と分散を考慮する:重要なインデックスの場合、初期データ量が厳密に必要としなくても、より良い分散とリカバリオプションを可能にするために、3または5つのプライマリシャードの使用を検討してください。トレードオフはオーバーヘッドの増加です。
  6. 控えめに始める:一般的に、プライマリシャードの数を変更する(通常は再インデックスまたは複雑な回避策が必要)よりも、レプリカを追加する方が簡単です。不明な場合は、少ないプライマリシャードから始めて、パフォーマンスを監視してください。

シナリオ例:ログ分析

アプリケーションログをインデックスしているとします:

  • データ量:月に1TBのログを見込んでいます。

  • データ保持:ログを30日間保持します。

  • ターゲットシャードサイズ:20GBを目指します。

  • 日次インデックス:日次インデックスを作成します(logstash-YYYY.MM.DD)。各日次インデックスは約1TB / 30日 ≈ 33GBのデータを保持します。

  • インデックスあたりのプライマリシャード:20GBのターゲットと33GBの日次ボリュームを考慮すると、インデックスあたり2つのプライマリシャードを選択する場合があります(33GB / 20GB ≈ 1.65、切り上げて2)。これにより、個々のシャードがターゲットサイズ内に収まります。

  • レプリカ:高可用性のために1つのレプリカを決定します。

  • 総シャード数:30日間の保持期間中、30のインデックスがあり、それぞれに2つのプライマリと2つのレプリカシャードがあり、常に合計60のプライマリと60のレプリカシャードがアクティブになります。

このアプローチにより、個々のシャードを管理しやすくし、古いインデックスを削除するだけで効率的なデータ削除が可能になります。

通常何が問題になるか

最も一般的な問題は、習慣による過剰シャーディングです。誰かが古いチュートリアルでその設定を使用していたため、5つのプライマリと1つのレプリカで日次インデックスを作成します。最初は無害に見えます。その後、クラスターには数百の小さなインデックス、数千の小さなシャードがあり、マスターノードはクラスター状態の更新に多くの時間を費やします。検索も多くのシャードにまたがってファンアウトし、実際のクエリ作業が始まる前に調整オーバーヘッドが追加されます。

反対の問題はリカバリ中に現れます。通常の日には、いくつかの巨大なシャードが許容できるクエリを実行するかもしれませんが、ノードが失敗したり、ローリング再起動が始まると、再配置に長い時間がかかります。スナップショットと復元も、各シャードが大きな作業単位であるため、遅くなる可能性があります。リカバリ目標が厳しい場合、クエリレイテンシが問題なくても、シャードサイズが重要になります。

ホットシャードも別の実際的な問題です。すべての新しい書き込みが1つのプライマリシャードに送られる場合、ノードを追加してもその書き込み負荷は自動的に分散されません。時間ベースのロールオーバーは、新しいインデックスを現在のトラフィックパターンに合わせてサイズ設定できるため、役立ちます。ルーティングの選択も重要です。カスタムルーティングは強力ですが、不適切なルーティングキーは1つのシャードに過剰なデータを送る可能性があります。

より良いロールオーバーパターン

時系列データの場合、サイズに基づくロールオーバーは、固定の日次インデックスよりも管理が容易なことがよくあります。何があっても1日1つのインデックスを作成する代わりに、書き込みエイリアスを作成し、ILMがインデックスがターゲットサイズ、経過時間、またはドキュメント数に達したときにロールオーバーするようにします。

PUT _ilm/policy/logs-policy
{
  "policy": {
    "phases": {
      "hot": {
        "actions": {
          "rollover": {
            "max_primary_shard_size": "30gb",
            "max_age": "1d"
          }
        }
      },
      "delete": {
        "min_age": "30d",
        "actions": {
          "delete": {}
        }
      }
    }
  }
}

このパターンでは、静かな週末はより少ないインデックスを生成するかもしれませんが、忙しいインシデントの日はより早くロールオーバーできます。それでも初期のプライマリ数を選択する必要がありますが、ロールオーバーによりシャードの成長がターゲットから大きく逸脱するのを防ぎます。

現在のシャードを検査する方法

何かを変更する前に、現在のクラスターを確認してください:

GET _cat/shards?v&h=index,shard,prirep,state,docs,store,node&s=store:desc
GET _cat/indices?v&h=index,pri,rep,docs.count,store.size,pri.store.size&s=pri.store.size:desc
GET _cluster/health

探しているパターンは、多数の小さなシャード、いくつかの巨大なシャード、未割り当てのシャード、不均一なノード配置、またはプライマリストアサイズが意図したターゲットから大きく離れているインデックスです。1つのインデックスに100GBのプライマリデータと5つのプライマリシャードがある場合、各プライマリはレプリカの前に約20GBです。同じインデックスに100GBと50のプライマリがある場合、おそらく不必要なオーバーヘッドを作成しています。

最後に

適切なシャードサイジングは、完璧な数値を追い求めることよりも、クラスターを運用しやすく保つことです。妥当なターゲットから始め、データパターンに合う場所でILMまたはロールオーバーを使用し、シャードサイズ、クエリファンアウト、リカバリ時間、ノードプレッシャーに実際に何が起こるかを監視します。クラスターがすでに過剰シャーディングされている場合は、すべての古いインデックスを一度に新しい形状に強制しようとするのではなく、新しいインデックステンプレート、ロールオーバー、縮小、または再インデックスを使用して徐々に修正します。