Elasticsearch シャード割り当ての問題:原因と解決策
Elasticsearchクラスタは、ノード間でのシャードの適切な分散と割り当てに大きく依存することで、回復力と高可用性を実現するように設計されています。シャードがUNASSIGNEDまたはINACTIVEの状態からアクティブなプライマリまたはレプリカに移動できない場合、クラスタヘルスインジケータはしばしば黄色または赤色に変わります。シャードがなぜ割り当てられないのかを理解することは、健全で高性能かつ利用可能な検索エンジンを維持するために不可欠です。
このガイドでは、クラスタリソースの不足から設定ミスに至るまで、シャード割り当て失敗の一般的な原因を深く掘り下げ、これらの問題を解決するための実用的かつ具体的なソリューションを提供し、データが適切にインデックス化され検索可能であることを保証します。
シャードの状態と割り当ての理解
トラブルシューティングを行う前に、Elasticsearchが何をしようとしているのかを知ることが不可欠です。シャードはElasticsearchにおける分散の基本単位です。シャードはいくつかの状態を取り得ます:
- STARTED: シャードはアクティブで、リクエストを処理しています(プライマリまたはレプリカ)。
- RELOCATING: シャードはノード間で移動中です(リバランス時またはノードの追加/削除時)。
- INITIALIZING: プライマリから新しいレプリカシャードが作成されています。
- UNASSIGNED: シャードはクラスタ状態のメタデータには存在しますが、どのノードにも割り当てられていません。これは多くの場合、必要なノードが利用できないか、基準が満たされていないためです。
クラスタのヘルスは、未割り当てシャードの存在によって決定されます:
- Green: すべてのプライマリシャードとレプリカシャードが割り当てられています。
- Yellow: すべてのプライマリシャードは割り当てられていますが、1つ以上のレプリカシャードが未割り当てです。
- Red: 1つ以上のプライマリシャードが未割り当てです(プライマリシャードをホストしているノードが故障した場合、データ損失のリスクがあることを示します)。
シャード割り当て失敗の一般的な原因
シャードの割り当ては、クラスタの割り当て決定ロジックによって管理されており、シャードを配置する前に多数の要素をチェックします。失敗は通常、これらの決定点のいずれかの違反に起因します。
1. クラスタリソースの不足
これは、特に動的な環境において、割り当てが停止する最も頻繁な原因かもしれません。
ディスク容量のしきい値
Elasticsearchは、ノードのディスク使用率が事前定義されたしきい値を超えると、新しいシャード(プライマリとレプリカの両方)のノードへの割り当てを自動的に停止します。デフォルトでは、使用率が85%で割り当てを停止し、90%で割り当てを完全にブロックします。
デフォルトのしきい値(elasticsearch.ymlまたはクラスタ設定を確認):
| 設定 | デフォルト値 | 説明 |
|---|---|---|
cluster.routing.allocation.disk.watermark.low |
85% | ノードが比較的満杯と見なされるしきい値。 |
cluster.routing.allocation.disk.watermark.high |
90% | ノードへの割り当てがブロックされるしきい値。 |
cluster.routing.allocation.disk.watermark.flood_stage |
95% | 割り当てが完全に停止し、インデックス作成/書き込み操作が失敗する可能性があります。 |
解決策: すべてのノードのディスク使用量をチェックし、高水位標を超えているノードで空き容量を確保するか、より多くのディスク容量を追加します。
メモリとCPUの負荷
ディスクの問題ほど一般的ではありませんが、ノードでの持続的な高メモリ使用量や高CPU負荷は、割り当て決定者が十分な運用余裕があるノードを優先するため、新しいシャードの割り当てを妨げることがあります。
2. ノードロールと属性の不一致
最新のElasticsearchデプロイメントでは、専用のマスタノード、インジェストノード、またはコーディネーティングノードがよく使用されます。シャードは、必要な基準を満たさないノードには割り当てられません。
不一致な割り当てルール
特定の属性(例:高速SSD)でタグ付けされたノードにシャードを配置するよう、特定のインデックス設定を構成している場合、利用可能なノードにそのタグが一致しないと、シャードは未割り当てのままになります。
例: index.routing.allocation.require.box_type: high_ioで作成されたインデックスは、その設定で明示的に構成されたノードにのみ割り当てられます。
解決策: 影響を受けるインデックスの割り当てルール(allocation.require、allocation.include、allocation.exclude)を確認し、ノードが正しいnode.attr設定を持っていることを確認します。
3. クラスタ状態の安定性とプライマリ割り当て失敗(Redヘルス)
プライマリシャードが未割り当て(クラスタがRED状態)の場合、それは最後のプライマリコピーを保持していたノードが故障したか、クラスタを離れたことを意味し、利用可能なレプリカシャードがプライマリに昇格できません。
一般的なシナリオ:
* 唯一のプライマリコピーを保持しているノードが予期せずクラッシュする。
* プライマリシャードを含むノードが、レプリカが正常にコピーされる前にクラスタから明示的に削除される。
解決策: 障害が発生したノードを迅速に回復できない場合、プライマリブロックを上書きして手動で割り当てを強制する必要があるかもしれませんが、これには当該シャードのデータ損失という高いリスクが伴います。
4. シャードの制限とクォータ
Elasticsearchは、クラスタを不安定にする可能性のある暴走シャードの作成を防ぐために、制限を課しています。
ノードあたりの最大シャード数
ノードが設定された最大シャード数(cluster.routing.allocation.total_shards_per_node)に達している場合、たとえディスク容量が利用可能であっても、それ以上のシャードは割り当てられません。
解決策: total_shards_per_nodeの制限を増やす(ノードあたりのシャード数が多すぎるとパフォーマンスが低下する可能性があるため注意が必要です)か、負荷を分散するためにクラスタにノードを追加します。
割り当て失敗の診断:Allocation Explain API
Allocation Explain APIは、特定のシャードがなぜ割り当てられないのかを診断するための最も強力なツールです。これは、割り当て決定者の意思決定プロセスをシミュレートします。
これを使用するには、インデックス名、シャード番号、およびシャードが存在するはずのノード(既知の場合。またはノードを省略してすべての可能性をチェック)が必要です。
使用例(インデックスmy_dataのシャード0のチェック):
GET /_cluster/allocation/explain?pretty
{
"index": "my_data",
"shard": 0,
"primary": true
}
このレスポンスは、そのシャードに対して行われたすべての割り当て決定を詳細に示し、どのルールに違反したかを明示します(例:「[ノードXのディスクが高水位標を超えています]」)。
出力の読み取り
explanationフィールドとdecidersセクションに細心の注意を払ってください。デサイダがfalseを返した場合、対応するメッセージは違反している制約を説明します(例:ディスク使用量、レプリカ数不一致、またはノード属性除外)。
トラブルシューティングの手順とコマンド
UNASSIGNED状態に直面した場合、次の優先順位付けされたトラブルシューティングシーケンスに従ってください:
ステップ1:クラスタヘルスと未割り当てシャードの確認
まず、全体像を把握します。
GET /_cluster/health?pretty
GET /_cat/shards?h=index,shard,prirep,state,unassigned.reason,node
cat API出力のunassigned.reason列に特に注目してください。これはしばしば、直接的な手がかりを提供します(例:CLUSTER_RECOVERED、NODE_LEFT、INDEX_CREATED)。
ステップ2:ディスク容量の調査
理由がディスク圧力を示している場合、すべてのノードの実際の使用量をチェックします。
GET /_cat/allocation?v&h=node,disk.used_percent,disk.avail,disk.total
アクション: ノードが容量の90%近くに達している場合、直ちにログの消去、インデックス保持期間の短縮、または当該ノードへのディスク容量の追加を開始してください。
ステップ3:複雑なケースにはAllocation Explainを使用する
原因が明らかなリソース圧力でない場合、上記の詳細に従ってAllocation Explain APIを実行し、設定の不一致を特定します。
ステップ4:手動での割り当て強制(注意して使用)
元のノードが永久に失われたためにプライマリシャードがUNASSIGNED(Redヘルス)であり、最後のプライマリシャードが存在して以来書き込まれたデータを失うリスクを受け入れる場合、クラスタにレプリカを昇格させることを強制できます(レプリカが存在する場合)。
警告: このコマンドは未割り当てのプライマリシャードのレコードを永続的に削除します。プライマリをホストしているノードを回復できない場合にのみ使用してください。
POST /_cluster/reroute
{
"commands": [
{
"allocate_stale_primary": {
"index": "index_name",
"shard": 0,
"node": "node_name_with_replica",
"accept_data_loss": true
}
}
]
}
ステップ5:スタックしたレプリカへの対処(Yellowヘルス)
ノード不足またはディスク容量不足が原因でレプリカのみが未割り当て(Yellowヘルス)の場合、基盤となるリソース制約を修正する(ノードを追加するか、ディスク容量を解放する)だけで、デサイダが許可すればレプリカは通常自動的に割り当てられます。
リソースを追加せずに進める必要がある場合は、インデックスのレプリカ割り当てを一時的に無効にすることができます:
PUT /my_index/_settings
{
"index.blocks.write": true,
"index.number_of_replicas": 0
}
この変更後、クラスタヘルスはGreenに変わるはずです(0個のレプリカが正常に割り当てられたため)。後でレプリカを再度有効にすることを忘れないでください("index.number_of_replicas": 1)。
割り当て問題を防止するためのベストプラクティス
- ディスクウォーターマークを厳密に監視する:
highウォーターマーク(90%)に基づいてアラートを設定し、割り当てが完全にブロックされる前に介入します。 - ノードの多様性を維持する: 物理または仮想ノードが十分にあることを確認し、いずれかのノードが故障した場合でも、すべてのプライマリと必要なレプリカをホストするための属性要件を満たす十分なノードが利用できるようにします。
- アロケーションアウェアネスを使用する: マルチゾーンまたはマルチラックのデプロイメントでは、
cluster.routing.allocation.awareness.attributesを設定して、シャードのすべてのコピーが同じ物理ゾーンに配置されるのを防ぎ、ゾーン全体にわたる停止を緩和します。 - 現実的なレプリカ数を設定する: 維持できる物理ノードの数よりも高いレプリカ数を設定することは避けてください。これにより、軽微なメンテナンス中に未割り当てのレプリカが発生することが保証されます。
リソースを積極的に管理し、Allocation Explain APIを活用することで、管理者はElasticsearchシャードが最適な割り当てを達成するのを妨げている要因を迅速に診断し、解決することができます。