Recovering a failed node#

PGDは、再起動や一時的なネットワークブリップなどの短期間の停止から障害が発生したノードを自動的に復旧します。障害が発生したノードは再接続し、見逃した変更を追いつき、介入なしでクラスターに再参加します。 pgd nodes list を実行することにより、ノードがCATCHUP を介してACTIVE に戻ることを確認できます。

自動復旧が成功しない場合、ノードを手動で復旧する必要があります。これは通常、次の場合に発生します。

  • ノードのデータディレクトリが破損しており、Postgresが起動しません。

  • ノードがオフラインになっている時間が長いため、正常なノードのレプリケーションスロットが無効になっているか、ログ先行書き込みWALが危険なほど蓄積されています。

  • 基になるハードウェアに障害が発生したため、ノードを再構築する必要があります。

  • ノードはJOINING など、自分自身で進行することができない状態にあります。

障害が発生したノードを分離し、新しいメンバーとして戻すことにより、リカバリを実行します。このプロシージャは、 コミットスコープへの移行 を使用するPGDクラスターに適用されます。以下をカバーします。

  1. クラスターの状態の評価

  2. 障害が発生したノードのクラスターからの削除

  3. 障害が発生したノードの復旧

  4. 復旧したノードの検証

  5. クラスターの状態の検証

警告

障害が発生したノードを長期間無人のまま放置しないでください。正常な各ノードは、オフラインピアのWALとレプリケーションデータを保持します。これにより、ディスク領域が枯渇し、カタログのバキュームがブロックされる可能性があります。ノードが完全に失われるか、ダウンしている時間が長すぎる場合は、ノードを分割し、その場所に新しいノードに再参加します。代替品は、元のノードの名前を再利用できます。

クラスターに損傷を与える可能性があるため、PGDによって作成されたレプリケーションスロットを手動で削除しないでください。

開始する前に、次のことを確認します。

  • Configuring PGD CLI へのアクセス。

  • 正常なノードの接続文字列DSN。

  • bdr_superuser または同等のクラスターでpgd およびSQLコマンドを実行します。

クラスターの状態の評価#

アクションを実行する前に、すべてのノードとレプリケーションの現在の状態を確認してください。

  1. どのノードがACTIVE で、どのノードがダウンまたは遅延しているかを確認します。

pgd nodes list

出力を使用して、障害の種類を判断します。ダウンしているノードの半分未満がダウンしている場合、 マイノリティ障害クォーラム維持 があり、クラスターはクォーラムを保持します。半分以上がダウンしている場合、 マジョリティ障害クォーラムの損失 があり、クラスターはクォーラムを失います。これにより、次の手順でどの復旧アプローチを使用するかが決まります。

  1. 非アクティブまたは遅延しているレプリケーションスロットを確認します。

pgd replication show --slots

正常な各ノードは、オフラインピアのレプリケーションスロットを保持するため、WALが蓄積されます。スロットの遅延は、ディスクの圧力を示します。無効なスロットは、WALが破棄され、ノードがきれいに再参加できない可能性があることを意味します。

  1. 現在の書き込みリーダーを特定します。

pgd group <group_name> show

障害が発生したノードのクラスターからの削除#

このアプローチは、障害が発生したノードの数によって異なります。

マイノリティ障害クォーラム維持#

マイノリティ障害とは、半分未満のノードに障害が発生した場合です。残りのノードはまだマジョリティを形成しているため、クラスターはクォーラムを保持します。つまり、書き込みに関して合意に達し、通常の動作を継続できます。

PGD CLIを使用して、障害が発生した各ノードを分離します。これは、少数の障害に推奨される方法です。 <healthy_node_dsn> は正常なノードの接続文字列に置き換え、 <failed_node_name> は削除するノードの名前に置き換えます。複数のノードに障害が発生している場合は、各ノードに対してコマンドを繰り返します。

pgd --dsn "<healthy_node_dsn>" node <failed_node_name> part

例

pgd --dsn "host=node2.example.com dbname=bdrdb user=enterprisedb" node node1 part

または、正常なノードからbdr.part_node ファンクションを使用し、 <failed_node_name> を削除するノードの名前に置き換えます。複数のノードに障害が発生している場合は、各ノードに対してコマンドを繰り返します。

SELECT bdr.part_node(<failed_node_name>,
                     wait_for_completion => true,
                     force => false,
                     concurrent => true);

分離操作が開始され、ノードが安全になると自動的に削除されます。ノードは次の状態を遷移します。

ACTIVE → PART_START → PARTING → PART_CATCHUP → PART_TX_RESOLVE → PART_CLEANUP → PARTED → 自動的にドロップされます。

PART_CATCHUP フェーズでは、残りのノードは、操作が完了する前に、分割されたノードからの欠落データを同期します。これにより、データの損失が保証され、クラスターの一貫性が維持されます。

自動ドロップは、残りのすべてのノードが分割されたノードからのすべての変更を消費すると、発生します。手動でカタログのクリーンアップを実行する必要はありません。

マジョリティ障害クォーラムの損失#

マジョリティ障害とは、ノードの半分以上に障害が発生した場合です。残りのノードはマジョリティを形成できなくなるため、クラスターはクォーラムを失います。これは、書き込みに関する合意に達できなくなり、障害が発生したノードが削除されるまで書き込み操作がブロックされることを意味します。

ノードの大部分に障害が発生している場合、クラスターコンセンサスが必要なためpgd node part は使用できません。代わりに、 bdr.drop_node() とforce => true を使用し、ローカルコミットスコープのトランザクションでラップします。残りのすべての正常なノードでこれを実行します。

BEGIN;
SET LOCAL bdr.commit_scope = local;
SELECT bdr.drop_node(<failed_node_1>, force => true);
SELECT bdr.drop_node(<failed_node_2>, force => true);
COMMIT;

標準の分割プロセスとは異なり、強制ドロップは即時です。つまり、コンセンサスを待たずにノードが削除されます。

注釈

強制ドロップに相当するPGD CLIはありません。 SQLを使用する必要があります。 bdr.part_node(force => true) はPGD 6で非推奨であり、bdr.drop_node(force => true) のエイリアスです。

ノードがクラスターから削除されたことの確認#

<healthy_node_dsn> を正常なノードの接続文字列に置き換えます。

pgd --dsn "<healthy_node_dsn>" nodes list

マイノリティ障害の場合、ノードがなくなったことを確認する前に、自動クリーンアップが完了するのを待ってください。強制ドロップを使用するマジョリティ障害の場合、ノードはすぐに削除されます。

障害が発生したノードの復旧#

クラスターに再参加する必要がある障害が発生したノードごとに、次のプロセスを繰り返します。 PGDでは部分化またはドロップされたノード名を再利用できるため、復旧したノードは元の名前を再利用できます。

データベースの停止とデータディレクトリの準備#

障害が発生したノードで

  1. Postgresサービスを停止し、停止していることを確認します。

sudo systemctl stop postgresql.service
sudo systemctl status postgresql.service
  1. 既存のデータディレクトリをクリアする前に、バックアップまたは移動します。

cd /path/to/postgres/
mv data data_old
  1. テーブルスペースディレクトリを含むデータディレクトリをクリーンアップします。

rm -rf <pgdata>/*
rm -rf /path/to/tablespace/*

pgdノードセットアップの実行#

pgd node <new_node_name> setup \
  --pgdata <pgdata> \
  --dsn "host=localhost port=<port> dbname=<dbname> user=<username>" \
  --cluster-dsn "host=<healthy_node_host> port=5432 dbname=<dbname> user=<username>" \
  --log-file <log_file> \
  --group-name <group_name> \
  --initial-node-count <initial_node_count>

そこで

  • <new_node_name> 復旧したノードの名前。 PGDでは、ノードがPARTED 状態にある場合、元のノード名を再利用できます。

  • --pgdata 復旧したノードのデータディレクトリ。

  • --dsn 復旧するノードの接続文字列。

  • --cluster-dsn クラスター内の正常なノードへの接続文字列。

  • --log-file Postgresログファイルへのパス。

  • --group-name ノードグループ名。グループの最初のノードに必須。指定しない場合、ノードはアクティブノードのグループに参加します。

  • --initial-node-count クラスターまたは計画中のノードの数。リソース設定を計算するために使用されます。

このコマンドは、データディレクトリを自動的に初期化し、クラスターに参加し、Postgresサーバーを起動します。出力でNode <new_node_name> added to the cluster successfully を探して、完了を確認します。

注釈

ベースバックアップからWALの再生に時間がかかる大規模なデータベースの場合、最初にベースバックアップを個別に取得し、永続的なレプリケーションスロットでWALを保護するプロシージャについては、

Joining large PGD nodes with 2 steps を参照してください。

復旧したノードの検証#

復旧したノードがクラスターに完全に再参加したことを確認します。ノードの参加状態がACTIVE であることを確認します。

pgd --output-format psql --dsn "<recovered_node_dsn>" node <new_node_name> show

Raftコンセンサスが確立されていることを確認します。すべてのノードはRAFT_LEADER またはRAFT_FOLLOWER を表示する必要があります。

pgd --output-format psql --dsn "<recovered_node_dsn>" raft show

予想されるすべてのレプリケーションスロットが存在し、アクティブであることを確認します。

pgd --output-format psql --dsn "<recovered_node_dsn>" replication show --slots

復旧したノードと他の正常なノードの両方からクラスターの可視性を確認します。すべてのノードはACTIVE またはCATCHUP として表示される必要があります。

pgd --output-format psql --dsn "<node_dsn>" nodes list

クラスターの状態の検証#

ノードがクラスターに追いつきながら、レプリケーション遅延をモニタします。

pgd --output-format psql --dsn "<node_dsn>" replication show --slots

ルーティングが有効になっている場合は、復旧したノードでルーティング情報が利用可能で正しいことを確認します。

pgd --output-format psql --dsn "<node_dsn>" node <new_node_name> show

リカバリが完了すると、コミットスコープの動作が自動的に再開され、手動での再構成は必要ありません。

ノードが追いついている間、レプリケーション遅延、ディスク領域、Postgresログ、およびノード間のネットワーク接続に注意してください。

障害対応#

以下は、ノードの復旧中に発生する可能性のある一般的な問題とその解決方法です。

リカバリーはタイムアウトで失敗します

ノード間のネットワーク接続を確認し、ソースノードが応答していて正常であることを確認します。

復旧したノードは``ACTIVE`` ではなく``JOINING`` として表示されます

復旧したノードのPostgresログでエラー、特に復元フェーズに関する問題を確認します。正常なノードからpgd replication show --slots を実行して、他のノードにレプリケーションスロットが存在することを確認します。

復旧後にレプリケーションラグが増加します

リソース制約CPU、ディスクI/O、メモリを確認し、ノード間のネットワーク帯域幅を確認し、Postgres構成で十分なワーカーとレプリケーションスロットが許可されていることを確認します Postgres構成パラメーター を参照してください。

リカバリー後のチェックリスト#

通常の操作に戻る前に、次のチェックリストを使用して、クラスターが完全に正常な状態であることを確認します。

  • [ ]復旧したすべてのノードは、join_state をACTIVE として表示します。

  • ☐ Raftコンセンサスが確立される — すべてのノードがRAFT_LEADER またはRAFT_FOLLOWER を表示します。

  • [ ]レプリケーションスロットはすべてのノードでアクティブです。

  • ☐ すべてのノードはpgd nodes list でお互いを認識します。

  • [ ]どのノードのPostgresログにもエラーはありません。

  • ☐ レプリケーション遅延は許容範囲内です。