Elasticsearch シャードサイジング戦略:最適なバランスを見つける
シャードサイズ、ノード容量、クエリパターン、リカバリ時間、成長を考慮して、Elasticsearch のシャードサイジングを計画します。
Elasticsearch シャードサイジング戦略:最適なバランスを見つける
Elasticsearch は、強力な分散型検索・分析エンジンであり、そのスケーラビリティとパフォーマンスの多くは、基盤となるアーキテクチャ、特に シャード の概念に依存しています。シャードは基本的に、データのサブセットを保持する独立した Lucene インデックスです。そのサイズを理解し最適化することは、単なるベストプラクティスではなく、クラスターのパフォーマンス、安定性、コスト効率に直接影響を与える重要な要素です。
Elasticsearch のシャードサイジング戦略は、一度限りの計算式ではなく、キャパシティプランニングの問題です。メタデータのオーバーヘッドを避けるために十分な大きさでありながら、迅速にリカバリできるほど小さく、かつデータノード全体にインデックス作成と検索の作業を分散できるほど十分な数のシャードを目指す必要があります。
Elasticsearch シャードを理解する
サイジングの詳細に入る前に、シャードとは何か、Elasticsearch クラスター内でどのように機能するかを簡単に復習しましょう。
シャードとは?
Elasticsearch では、インデックスはデータの論理的なグループです。このデータを分散し、並列処理を可能にするために、インデックスは1つ以上の シャード に分割されます。各シャードは自己完結型の Lucene インデックスです。インデックスを作成する際に、そのインデックスが持つ プライマリシャード の数を定義します。
高可用性と読み取りのスケーラビリティのために、Elasticsearch では レプリカシャード を指定することもできます。レプリカシャードは、プライマリシャードの正確なコピーです。プライマリシャードのノードに障害が発生した場合、レプリカが昇格してその役割を引き継ぎ、データの可用性を確保し、データ損失を防ぎます。レプリカは検索リクエストにも応答し、読み取り負荷を分散します。
シャードの仕組み
ドキュメントをインデックスするとき、Elasticsearch はルーティングアルゴリズム(デフォルトではドキュメントのIDに基づく)に基づいて、どのプライマリシャードに属するかを決定します。このドキュメントは、その特定のプライマリシャードと対応するレプリカシャードに保存されます。検索時には、リクエストが関連するすべてのシャードに送信され、各シャードがデータの一部を並列に処理します。結果は集約され、クライアントに返されます。この並列処理が、Elasticsearch に驚異的な速度とスケーラビリティをもたらします。
シャードサイジングが重要な理由
最適なシャードサイジングは、健全な Elasticsearch クラスターの基盤です。不適切なサイジングは、クエリパフォーマンスの低下から、コストのかかるリソースの無駄、不安定なリカバリシナリオまで、さまざまな問題を引き起こす可能性があります。
パフォーマンス
- クエリ速度: 適切なサイズのシャードは、クエリを効率的に処理できます。シャードが小さすぎると、調整のオーバーヘッドが増加します。シャードが大きすぎると、個々のシャードの検索時間が長くなります。
- インデックス作成スループット: 同様に、インデックス作成のパフォーマンスも影響を受けます。シャードが小さすぎると、多数のシャードを管理するオーバーヘッドが書き込みを遅くする可能性があります。シャードが大きすぎると、個々のシャードのパフォーマンスがボトルネックになる可能性があります。
リソース使用率
各シャードは、CPU、メモリ(JVMヒープ)、ディスクI/Oなど、それが存在するノード上のリソースを消費します。適切なサイジングにより、ノードが過負荷になったり、十分に活用されなかったりすることなく、効率的に使用されるようになります。
スケーラビリティ
シャードは、Elasticsearch における分散の単位です。水平方向にスケールするには、ノードを追加し、Elasticsearch はそれらのノード間でシャードを再調整します。シャードが大きすぎると、再調整に時間がかかり、より多くのネットワーク帯域幅が必要になります。シャードが少なすぎると、プライマリシャードの数を超えてワークロードを分散できないため、早期にスケーリングの限界に達する可能性があります。
リカバリと安定性
- ノード障害: ノードに障害が発生すると、Elasticsearch はプライマリシャードを再割り当て(レプリカを昇格)し、失われたレプリカを再作成する必要があります。この処理にかかる時間は、関係するシャードのサイズと数に直接比例します。
- クラスターリカバリ: 大規模なシャードはリカバリとレプリケーションに時間がかかり、ノード障害やクラスター再起動時の脆弱性の期間が長くなります。
シャードサイジングに影響を与える要因
適切なシャードサイズを決定することは、万能の解決策ではありません。それは、ユースケースとインフラストラクチャに固有のいくつかの相互依存する要因に依存します。
- データ量と成長: 現在のデータサイズと予測される成長率は基本です。静的な100GBのインデックスと、毎日1TBずつ増加するローリングインデックスでは、要件が異なります。
- ドキュメントサイズとスキーマの複雑さ: 多くのフィールドや非常に大きなドキュメントを持つインデックスは、各ドキュメントの処理により多くのリソースを必要とするため、より小さなシャードが適している場合があります。
- クエリパターン:
- 検索主体: クラスターが主に検索に使用される場合、並列処理を最大化し、個々のシャードの検索時間を最小化するために、より多く、より小さなシャードを優先するかもしれません。
- 分析主体(集計): 大規模な集計は、多数の小さなシャードからの結果を結合するオーバーヘッドが大きくなる可能性があるため、より大きなシャードの方がパフォーマンスが良い場合があります。
- インデックス作成レート: 高いインデックス作成レートは、書き込み負荷を分散するためにより多くのシャードを必要とするかもしれませんが、多すぎるとオーバーヘッドが発生する可能性があります。
- ノード仕様: データノードのCPU、RAM(JVMヒープサイズ)、ディスクタイプ(SSD vs HDD)は重要です。より強力なノードは、より多くのシャードまたはより大きなシャードを処理できます。
- クラスタートポロジ: シャードを分散できるデータノードの総数は、実現可能なシャード数に直接影響します。
トレードオフ:シャードが多すぎる場合と少なすぎる場合
最適なバランスを見つけるには、両極端の結果を理解する必要があります。
シャードが多すぎる場合の結果
より多くのシャードはより多くの並列処理を提供するように見えますが、収穫逓減のポイントがあります。
- オーバーヘッドの増加: 各シャードは、メタデータ、オープンファイル、セグメントマージなどのためにCPUとメモリ(JVMヒープ)を消費します。ノード上にシャードが多すぎると、シャード自体の管理にかかる全体的なリソース消費が増加し、実際のデータ処理に使えるリソースが減少します。
- ヒント: 古いシャードあたりのヒープルールは大まかな警告として有用でしたが、最新のElasticsearchバージョンではシャードあたりのヒープオーバーヘッドが削減されています。それでも、数千の小さなシャードを持つクラスターはメモリを浪費し、クラスター状態の処理を困難にします。
- リカバリの低速化: ノード障害や再調整時に、多数の小さなシャードを管理および移動するには、少数の大きなシャードよりも時間とネットワークI/Oが必要です。
- リソース競合の増加: 多くのシャードが同じノード上でアクティブに操作(セグメントマージ、クエリ応答など)を実行している場合、CPU、メモリ、ディスクI/Oを競合し、全体的なパフォーマンスの低下につながります。
- 「シャードの肥大化」: 多数の小さく、ほとんど空のシャードを持つクラスターは非効率的です。データの利点に見合わない管理リソースを消費します。
シャードが少なすぎる場合の結果
逆に、シャードが少なすぎる場合も、重大な課題が生じます。
- 並列処理の制限: インデックスに少数の大きなシャードしかない場合、ワークロードを多くのノード/コアに分散できないため、検索クエリはクラスターの処理能力を最大限に活用できません。
- ホットスポット: 単一ノード上の大きなシャードは、読み取りまたは書き込みリクエストの不均衡な割合を受信すると「ホットスポット」になり、その特定のノードのリソースが飽和状態になる可能性があります。
- スケールアウトの困難さ: インデックスに例えば5つのプライマリシャードしかない場合、そのインデックスを最大5つのデータノードにしか効果的に分散できません。すべてのシャードがすでに異なるノードにある場合、ノードを追加してもその特定のインデックスのパフォーマンスには役立ちません。
- 再調整の低速化: 再調整中に単一の非常に大きなシャードをネットワーク経由で移動することは、時間とI/Oを大量に消費する操作であり、クラスターの安定性に影響を与える可能性があります。
- リカバリ時間の長期化: リカバリまたはコピーが必要な単一の大きなシャードは、障害後のクラスターのリカバリ時間を大幅に延長する可能性があります。
一般的な推奨事項とベストプラクティス
すべてのケースに当てはまる単一のルールはありませんが、広く受け入れられているいくつかのガイドラインが良い出発点となります。
目標シャードサイズ
個々のシャードサイズ(インデックス作成と潜在的なマージ後)に対する最も一般的に引用される推奨事項は、10GBから50GB です。特定のシナリオ(例:主に追加書き込みで複雑なクエリが少ない時系列データ)では、最大100GBまで拡張する情報源もあります。この範囲は通常、管理容易性、リカバリ速度、効率的なリソース使用率の間で適切なバランスを提供します。
- なぜこの範囲なのか?:
- リカバリ: この範囲のシャードは、ノード障害後比較的迅速にリカバリできます。
- パフォーマンス: オーバーヘッドを最小限に抑えるのに十分な大きさでありながら、効率的な処理と迅速なマージを可能にするのに十分な小ささです。
- スケーラビリティ: ノード間での柔軟な分散が可能です。
ノードあたりのシャード数
単一ノード上に過剰な数のシャードがあることを避けてください。Elasticsearch は最新バージョンでクラスターシャード制限を強制しており、実際の制限はヒープ、マッピング、クエリ量、ディスク速度によって異なります。シャード数を警告メトリックとして使用し、その後JVMプレッシャー、クラスター状態更新レイテンシ、検索/インデックス作成レイテンシで確認してください。
ホット-ウォーム-コールドアーキテクチャとシャードサイジング
ホット-ウォーム-コールド(HWC)アーキテクチャでは、シャードサイジングは異なる場合があります。
- ホット層: アクティブな書き込みを受け、頻繁にクエリされるデータノード。ここでは、インデックス作成スループットとクエリの並列処理を最大化するために、やや多めのシャードまたは小さめのシャードを選択するかもしれません。
- ウォーム/コールド層: アクセス頻度の低い古いデータを保持するノード。これらのシャードは通常、インデックス作成が停止し、マージが完了しているため、より大きくなります。ここでは、特にコスト最適化されたストレージでは、シャード総数と関連するオーバーヘッドを削減するために、より大きなシャード(最大100GB以上)が許容される場合があります。
レプリカ
常にレプリカを使用してください!高可用性には、プライマリシャードあたり少なくとも1つのレプリカ(データの合計2コピー)が不可欠です。レプリカは検索リクエストを分散することで読み取り容量も増加させます。最適なレプリカ数は、可用性要件とクエリ負荷によって異なります。
シャードサイズを決定するための実践的な戦略
ここでは、初期のシャードサイジング戦略を導き出し、その後反復的に調整するためのステップバイステップのアプローチを示します。
ステップ1:総データ量と成長を推定する
インデックス(またはローリングする日次/月次インデックス)がそのライフサイクル全体で保持するデータ量を見積もります。平均ドキュメントサイズを考慮してください。
- 例: 1日あたり100GBのデータを取り込み、30日間保持するとします。アクティブな総データ量は約3TBになります(
100GB/日 * 30日)。
ステップ2:目標シャードサイズを決定する
一般的な推奨事項であるプライマリシャードあたり30GB~50GBから始めます。ユースケースに基づいて調整します。
より小さなシャード(例:10~20GB): 非常に高いクエリスループット、大きなドキュメントに対する複雑な集計、または非常に頻繁に変更されるデータがある場合。
より大きなシャード(例:50~100GB): 主に時系列データ、追加専用インデックス、または頻度が低く単純なクエリがある場合。
例(ステップ1からの続き): 平均プライマリシャードサイズを50GBと目標とします。
ステップ3:初期プライマリシャード数を計算する
推定総データ量を目標シャードサイズで割ります。
プライマリシャード数 = (総データ量) / (目標シャードサイズ)
- 例:
3000GB / 50GB = 60 プライマリシャード。
ステップ4:ノードリソースとヒープサイズを考慮する
クラスターが快適にホストできるプライマリシャードとレプリカシャードの数を決定し、シャードあたりのGBヒープルールを尊重します。
- ノードあたりのヒープ: 各データノードに30GBのJVMヒープがあるとします。
- ノードあたりの最大シャード数(概算):
10~20シャード/GBヒープルールを使用すると、30GBヒープノードは30 * 10 = 300から30 * 20 = 600のシャードをホストできます。 - レプリカの総数: 1つのレプリカを使用する場合(強く推奨)、
60 プライマリシャード + 60 レプリカシャード = 120 総シャードになります。 - データノードの数: レプリカがそのプライマリと同じノードに配置されないように、これらのシャードを分散できることを確認してください。本番環境の回復力のために、ノードまたはゾーンに障害が発生しても未割り当てのレプリカが残らないように、十分なデータノードとゾーンを使用してください。
シナリオ例
それぞれ30GBヒープを持つ3ノードのデータクラスターを想定します。
- 現在計算された総シャード数:
120 シャード (60 プライマリ + 60 レプリカ) - ノードあたりの平均シャード数:
120 総シャード / 3 ノード = ノードあたり40シャード。 - この数は、負荷がかかった状態でヒーププレッシャー、ディスクI/O、インデックス作成レイテンシ、検索レイテンシが健全である場合にのみ妥当です。
ステップ5:テストと監視
これが最も重要なステップです。理論上の計算は単なる出発点です。
負荷テスト: 予想されるインデックス作成とクエリのパターンをシミュレートします。パフォーマンスメトリクスを観察します。
監視ツール: Kibanaの組み込み監視、Elasticsearchの
_catAPI、または外部監視ツール(例:Prometheus、Grafana)を使用して、以下を監視します。_cat/shards: シャードサイズと分散を確認します。_cluster/stats: 特にJVMヒープ使用量に関するクラスターレベルの統計。- 個々のノードのCPU、メモリ、ディスクI/O。
- インデックス作成と検索のレイテンシ。
- セグメントマージアクティビティ。
# シャードの割り当てとサイズ情報を取得 GET _cat/shards?v=true&h=index,shard,prirep,state,docs,store,node # ヒープ使用量とシャード数のクラスター統計を取得 GET _cluster/stats
ステップ6:反復的な調整
監視に基づいて、シャード数を調整する準備をしてください。これには以下が含まれる可能性があります。
- Shrink API: 書き込みが行われなくなったインデックスに対してプライマリシャードが多すぎる場合、
_shrinkAPIを使用してプライマリシャードの数を減らすことができます。インデックスは読み取り専用である必要があり、シャード配置がシュリンク要件を満たしている必要があります。 - Split API: インデックスのシャードが大きくなりすぎてパフォーマンスが低下している場合、
_splitAPIを使用してプライマリシャードの数を増やすことができます。インデックスは読み取り専用であり、互換性のあるルーティングシャード数で作成されている必要があります。 - Reindex API: マッピングの変更や、アクティブに書き込まれているライブインデックスのシャード数の変更など、より複雑な変更には、データを異なるシャード設定の新しいインデックスに再インデックスする必要がある場合があります。
よくある落とし穴とその回避方法
- 盲目的な過剰シャーディング: 小規模クラスターでデータ1GBあたり1シャードを作成し、過剰なオーバーヘッドを招く。回避策: 妥当な目標から始め、データの成長に応じてシャードをスケールアップする。
- インデックスの過小シャーディング: 非常に大きなインデックスに対してシャードが1~3個しかなく、並列処理とスケーラビリティが制限される。回避策: データ量とノード容量に基づいて計算する。
- 成長予測の無視: 将来の取り込みを考慮せずに現在のデータに合わせてサイジングする。回避策: データのライフタイム全体にわたる予想データ成長を常に考慮する。
- 監視の欠如: 設定したまま放置する。シャードサイズ、ノードリソース、クエリパフォーマンスは時間とともに変化する。回避策: 主要なメトリクスに対して堅牢な監視とアラートを実装する。
- 経験則の盲目的な適用: 10GB~50GBルールはガイドラインであり、厳格な法則ではありません。特定のワークロードによってはバリエーションが必要になる場合があります。回避策: 一般的な推奨事項は、実際のデータと使用パターンで常に検証する。
実践的なポイント
予想データ量と目標シャードサイズから初期シャード数を選択し、負荷テストでそれを証明します。ロールオーバーまたは成長後のリカバリ時間、ヒーププレッシャー、ディスクI/O、レイテンシを監視します。数値がずれた場合は、シャードレイアウトがインシデントになる前に、ロールオーバー、シュリンク、スプリット、または再インデックスを使用します。