Elasticsearchクラスタのスプリットブレイン問題のトラブルシューティング
Elasticsearchの重大なスプリットブレイン問題を診断・解決する方法を学びます。このガイドでは、ネットワークパーティションや誤ったクォーラム設定などの一般的な原因を解説します。ネットワークチェックやログ分析を含む実践的な診断手順を紹介し、クラスタの安定性を回復するための明確なステップバイステップの解決プロセスを提供します。将来のスプリットブレインインシデントからElasticsearchデプロイメントを保護するための予防戦略を実装します。
Elasticsearchクラスタのスプリットブレイン問題のトラブルシューティング
スプリットブレインは、そのドラマチックな響きからよく話題になるElasticsearchの障害ですが、より実用的な疑問は「クラスタの複数の部分が同時にマスターレベルの決定を行えるか?」です。最新のElasticsearchバージョンは、多数決ベースのクラスタ調整を通じてこれを防ぐように設計されています。特に、discovery.zen.minimum_master_nodesの設定が不適切なpre-7.0のクラスタは、誤設定されやすかったです。
そこで、この記事ではよく混同される2つの状況を区別します。真のスプリットブレインとは、独立したパーティションがそれぞれマスターを選出または維持できる状態を指します。マスター選出障害とは、クラスタが過半数を持たないためにマスターを選出できない状態です。前者はクラスタ状態の競合とデータ不整合のリスクがあります。後者は痛みを伴いますが、通常はより安全な障害モードです。
スプリットブレインの兆候
健全なクラスタでは、選出された1つのマスターがクラスタ状態(インデックス作成、シャード割り当ての決定、マッピング、ノードメンバーシップ、および類似のメタデータ)を管理します。データノードは読み取りと書き込みを処理できますが、クラスタは依然として単一のマスターによる世界観に依存しています。
スプリットブレインシナリオは、ネットワークパーティションや不適切なディスカバリー設定により、2つのノードグループがそれぞれ自分たちが本当のクラスタであるかのように振る舞う場合に発生します。一方の側があるインデックスへの書き込みを受け入れ、もう一方の側が異なる書き込みを受け入れる可能性があります。接続が回復したとき、Elasticsearchはテキストファイルのように2つの競合する履歴を単純にマージすることはできません。
最新のElasticsearchでは、パーティションがマスター候補ノードの過半数を持たない場合、マスターを選出すべきではありません。つまり、一部のノードは競合するクラスタを形成する代わりに利用不可になる可能性があります。これが望ましい動作です。
バージョンの重要性
Elasticsearch 6.x以前の場合、重要な設定は次のとおりです:
discovery.zen.minimum_master_nodes: 2
ルールはマスター候補ノードの過半数:(N / 2) + 1(整数除算で切り捨ててから1を加算)。3つのマスター候補ノードがある場合は2に設定します。5つの場合は3に設定します。3ノードクラスタで1に設定すると、スプリットブレインが発生する可能性があります。
Elasticsearch 7.x以降では、discovery.zen.minimum_master_nodesは廃止されました。クラスタ調整が変更され、Elasticsearchが投票設定を管理します。新しいクラスタでは、cluster.initial_master_nodesを使用した正しいブートストラップが必要ですが、この設定は最初のクラスタ形成時のみ使用します。クラスタが形成されたら、設定から削除します。
古いdiscovery.zen設定を追加して最新のクラスタを「修正」しないでください。それらはもはやコントロールプレーンではありません。
一般的な原因
最も一般的なトリガーは、マスター候補ノード間のネットワークパーティションです。クラウド環境では、セキュリティグループの変更、不正なルートテーブル、ネットワークACL、ゾーンレベルの問題、またはトランスポートポート9300をブロックするファイアウォールルールが原因となる可能性があります。ベアメタル環境では、スイッチ、VLAN、DNS、MTU、またはパケットロスの問題が原因となる可能性があります。
別の原因は、マスター候補ノードが少なすぎることです。2つのマスター候補ノードは、1つが故障した後に明確な過半数が存在しないため、扱いにくいです。本番クラスタでは通常、3つの専用マスター候補ノード、または小規模デプロイメントでは3つの混合ロールノードを使用します。
3つ目の原因は、古いまたは再利用されたデータディレクトリです。VMをクローンしたり、古いクラスタからディスクを再利用したりすると、ノードが意図しないクラスタメタデータを保持する可能性があります。これにより、混乱を招く参加失敗や、最悪の場合、誤った別のクラスタの形成につながる可能性があります。
最後に、プレッシャーのかかる状況での手動リカバリが問題を悪化させる可能性があります。ランダムなノードの再起動、データパスの消去、またはどのパーティションが権威を持つかを確認する前に安全でない割り当てを強制することは、回復可能なインシデントをデータ損失に変える可能性があります。
インシデント発生時の最初のチェック
まず、到達可能な各ノードにその認識を問い合わせます:
curl -s "http://NODE:9200/_cat/master?v"
curl -s "http://NODE:9200/_cat/nodes?v&h=ip,name,roles,master,node.role"
curl -s "http://NODE:9200/_cluster/health?pretty"
可能であれば、複数のノードに対してこれらを実行します。異なるノードが異なるマスターや異なるノードメンバーシップを報告する場合、パーティション化されたクラスタまたは孤立したノードを見ている可能性があります。
マスター候補ノードのログで、選出、参加、切断、公開失敗に関するメッセージを確認します。有用な検索用語には、master not discovered、elected-as-master、node-left、node-join、publication、connect_transport_exception、handshakeなどがあります。
次に、HTTPだけでなくトランスポート接続をテストします:
nc -vz node-1.example.internal 9300
nc -vz node-2.example.internal 9300
nc -vz node-3.example.internal 9300
これらのテストをノード間で実行します。ロードバランサーや踏み台がHTTPポート9200に到達できることは、Elasticsearchノードが9300を介してクラスタを形成できるかどうかについてはほとんど情報を与えません。
ディスカバリーとブートストラップ設定の確認
Elasticsearch 7.x以降では、次の設定を確認します:
cluster.name: my-cluster
discovery.seed_hosts:
- node-1:9300
- node-2:9300
- node-3:9300
新しいクラスタの場合のみ:
cluster.initial_master_nodes:
- node-1
- node-2
- node-3
ブートストラップ名はnode.nameと一致する必要があります。クラスタが形成されたら、すべてのノードからcluster.initial_master_nodesを削除します。
Elasticsearch 6.x以前では、次の設定を確認します:
discovery.zen.minimum_master_nodes: 2
3つのマスター候補ノードを持つクラスタの場合。また、すべてのマスター候補ノードが一貫したディスカバリーホストとクラスタ名を持っていることを確認します。
リカバリの原則
真のスプリットブレインが疑われる場合、どの側が権威を持つかを確認するまで、クラスタAPIを介した変更を停止します。最も安全なリカバリは通常、次の順序に従います:
- 証拠を保存:各パーティションからログ、ノードリスト、マスターのビュー、インデックスヘルスを収集します。
- ネットワーク接続を復元するか、意図的に悪い側を分離します。
- 過半数、最新の有効なデータ、ビジネスへの影響に基づいて権威のあるパーティションを選択します。
- 独立したパーティションとして継続すべきでないノードでElasticsearchを停止します。
- ノードを1つずつ復帰させ、権威のあるクラスタに参加することを確認します。
- プライマリシャードの履歴が失われたり不整合がある場合、スナップショットから不足データを復元します。
トランザクションログディレクトリをルーチンのスプリットブレイン修正として削除しないでください。それは危険なアドバイスです。トランザクションログはElasticsearchリカバリの一部です。データパス下のファイルを手動で削除するとデータ損失を引き起こす可能性があり、Elasticサポートからのバージョン固有のガイダンスがある場合、または損失を受け入れて再構築計画がある場合にのみ行うべきです。
2つのパーティションが独立して書き込みを受け入れた場合、完全な自動マージは存在しない可能性があります。スナップショットからの復元、ソースシステムからの再インデックス、アプリケーションログの再生、または一方の側のデータを権威として選択する必要があるかもしれません。
現実的な例
3つのプライベートサブネットにまたがる3ノードクラスタを想像してください。ファイアウォールの変更により、ノード1とノード2および3の間のトランスポートトラフィックが誤ってブロックされます。ノード2と3は互いに見えるため、マスターを維持または選出します。ノード1は過半数を見ることができません。最新の正しく設定されたクラスタでは、ノード1は単独で競合するマスターを形成すべきではありません。ノード1を使用するクライアントは失敗するかもしれませんが、クラスタは競合するマスターを回避します。
次に、3つのマスター候補ノードとdiscovery.zen.minimum_master_nodes: 1を持つ古い6.xクラスタを想像してください。ノード1は自分自身を選出でき、ノード2と3は別のマスターを選出します。これが古典的なスプリットブレインのリスクです。修正はネットワークの再接続だけではありません。クォーラム設定を修正し、間違った側で受け入れられた書き込みをどう処理するか決定する必要もあります。
予防
小規模および中規模のクラスタには3つのマスター候補ノードを使用します。大規模クラスタの場合は、検索とインデックス作成の負荷がクラスタ調整に干渉しないように、専用のマスターノードにします。
マスター候補ノードを低パケットロスの信頼性の高いネットワーク上に配置します。ゾーン間でノードを分散すると可用性が向上する可能性がありますが、それはゾーン間のネットワークが信頼性が高く、クォーラム設計が依然として意味をなす場合に限ります。
マスター変更を監視します。計画メンテナンス中のマスター選出は正常です。通常のトラフィック中の頻繁な選出は警告サインです。
トランスポート接続を監視し、HTTPアップタイムだけでなく監視します。ノードは9200に応答しても、トランスポートトラフィックがブロックされている場合、クラスタに正しく参加できないことがあります。
定期的にスナップショットを作成し、復元をテストします。レプリカは、深刻なインシデント中の誤った削除、データ破損、または競合する書き込みから保護しません。
ブートストラップ設定に注意してください。最新のクラスタでは、cluster.initial_master_nodesは日常的なディスカバリー設定ではありません。新しいクラスタを作成するために使用し、その後削除します。
最高のスプリットブレインリカバリは、決して必要としないものです:多数決ベースのマスター資格、正しいバージョン固有のディスカバリー設定、退屈なネットワークルール、そしてテスト済みのスナップショット計画。
スプリットブレインと通常の選出の見分け方
マスター選出は自動的にスプリットブレインではありません。ローリング再起動、ネットワークフラップ、またはマスターノード障害の際、Elasticsearchは新しいマスターを選出する可能性があります。クラスタが1つの権威あるマスターを維持し、古いマスターが降りる場合、それは正常な分散システムの動作です。
警告サインは、異なるノードからの異なるビューです。ノードAが自分自身をマスターとして報告し、ノードBがノードCをマスターとして報告する場合、停止して調査します。2つのノードグループが切断中に両方ともクラスタ状態の変更を受け入れる場合、一時的な選出よりもはるかに深刻な状況です。
また、クライアントの動作を監視します。孤立したノードに固定されたクライアントは、過半数側が健全であっても障害を目にする可能性があります。それは過半数クラスタが壊れていることを意味しません。クライアント接続戦略またはロードバランサーが、参加できないノードにまだトラフィックを送信していることを意味するかもしれません。
ロードバランサーとクライアントルーティング
Elasticsearchトランスポートディスカバリーは、クライアントHTTPルーティングと同じではありません。マスターディスカバリーを汎用HTTPロードバランサーの背後に置き、クラスタメンバーシップを解決することを期待しないでください。ノードは互いにトランスポート接続を必要とします。
クライアントには、複数のHTTPエンドポイントまたは異常なノードを迅速に除去するロードバランサーを使用します。マスターを失ったノードは、しばらくの間プロセスがリッスンしているかもしれませんが、書き込みの良いターゲットではありません。ヘルスチェックは「ポート9200が開いている」よりも意味のあるものであるべきです。
実用的なHTTPヘルスチェックは、ローカルでクラスタヘルスをクエリし、発見されたマスターを持たないノードを拒否するかもしれません。正確なアプローチはクライアントとインフラストラクチャに依存しますが、原則は単純です:孤立したノードに書き込みを送り続けないでください。
インシデント後のクリーンアップ
クラスタが安定した後、インデックスヘルス、ドキュメント数、およびアプリケーションレベルの真実のソース数を比較します。異なるパーティションに書き込みが行われた可能性がある場合、Elasticsearchのヘルスだけではデータが意味的に正しいことを証明できません。
タイムラインを確認します。どのノードが最初に接続を失いましたか?イベント前にどのノードがマスターでしたか?クライアントは書き込みを続けましたか?スナップショットは最新でしたか?ユーザーが気付く前にアラートが発報しましたか?これらの詳細は、ネットワーク修正のみが必要か、データ調整計画が必要かを決定します。
古いクラスタの場合、バージョンとディスカバリー設定の作業をスケジュールします。まだdiscovery.zen.minimum_master_nodesに依存するバージョンを実行している場合、今日それが正しいことを確認し、アップグレードパスを計画します。スプリットブレイン防止は一度限りのランブックステップではなく、クラスタライフサイクル管理の一部です。
パニック時に避けるべき設定変更
ノードを参加させるためにcluster.nameを変更しないでください。それは別のクラスタアイデンティティ問題を引き起こします。
ノードのローカルシャードコピーを意図的に破棄し、クラスタが他の場所に有効なコピーまたはスナップショットを持っていることを確認しない限り、データパスを消去しないでください。
一般的な再起動修正として、既存の最新クラスタにcluster.initial_master_nodesを追加し戻さないでください。その設定は初期ブートストラップ用であり、日常的なディスカバリー用ではありません。
可用性を回復するために、古いクラスタのクォーラムスタイルの保護を緩和しないでください。マイノリティパーティションを書き込み可能にすることは進歩のように感じられるかもしれませんが、それはまさに競合するマスターが可能になる方法です。
厄介な障害ドメインへの設計
3つのマスター候補ノードは、単一のインフラストラクタイベントがそのうちの2つを除去できない場合に最適に機能します。3ゾーンクラウドリージョンでは、ゾーンごとに1つのマスター候補ノードが一般的なパターンです。2ゾーン環境では、1つのゾーンが2票を含む可能性があるため、配置はより困難です。その大きなゾーンが故障した場合、残りの1票は安全にマスターを選出できません。それはElasticsearchが脆弱だからではなく、多数決の計算です。
障害モードを考慮せずに偶数の投票ノードを追加することでこれを解決しないでください。4つのマスター候補ノードでも過半数が必要であり、2対2のパーティションは安全に一方を選択できません。専用の投票専用ノードは一部の設計で役立つかもしれませんが、原則は同じです:クラスタはクラスタ状態の決定を行うために信頼性の高い過半数を必要とします。
これをアーキテクチャノートに書き留めてください。障害発生中、人々はなぜ生存ノードまたは生存ゾーンが書き込みを提供し続けられないのかとよく尋ねます。その答えはインシデントの前に明確にしておくべきです:過半数なしで書き込みを受け入れることは、履歴の競合のリスクがあります。