DCSフェイルセーフモード
問題
Patroniは、リーダー選出とネットワーク分断の検出を行うため、分散構成ストア(DCS)に大きく依存しています。つまり、DCS内のリーダーロックを更新できる場合に限り、ノードはPostgresをプライマリーとして実行できます。リーダーロックの更新に失敗すると、Postgresはただちに降格し、読み取り専用として起動します。この「問題」が発生する可能性は、使用するDCSによって異なります。たとえば、Patroni専用のetcdでは発生する可能性はほぼゼロですが、etcdを基盤に持つK8s APIでは、より頻繁に観測される可能性があります。
現在の実装の理由
リーダーロックの更新が失敗する主な理由は、次の二つです。
- ネットワークの分断
- DCSの停止
一般に、単一のノードからこの二つを区別することはできないため、Patroniは最悪のケースであるネットワーク分断を想定します。ネットワークが分断されると、Patroniクラスターの他のノードがリーダーロックを取得し、Postgresをプライマリーに昇格させる可能性があります。スプリットブレインを避けるため、以前のプライマリーはリーダーロックが期限切れになる前に降格します。
DCSフェイルセーフモード
新しい特別なオプション、failsafe_modeを導入しました。これは、DCSの/configキーに保存されたグローバルな動的構成
を通じてのみ有効にできます。フェイルセーフモードが有効で、バージョン、値、インデックスの不一致以外の理由でDCS内のリーダーロックの更新が失敗した場合、Patroni REST APIを通じてクラスターの既知の全メンバーにアクセスできれば、Postgresはプライマリーとして動作を継続できます。
内部実装の詳細
/failsafeという名前の新しい永続キーをDCSに導入しました。/failsafeキーには、ある時点での、そのPatroniクラスターの既知の全メンバーが含まれます。- 現在のリーダーが
/failsafeキーを維持します。 - メンバーは、
/failsafeキーに含まれる場合に限り、リーダー選出に参加して新しいリーダーになれます。 - クラスターが単一ノードで構成されている場合、
/failsafeキーには単一のメンバーが含まれます。 - DCSの「停止」が発生すると、既存のプライマリーは
POST /failsafeREST APIを通じて/failsafeキーに含まれる全メンバーに接続し、すべてのレプリカが承認すればプライマリーとして動作を継続できます。 - メンバーのいずれかが応答しない場合、プライマリーは降格します。
- レプリカは、受信した
POST /failsafeREST APIリクエストを、プライマリーがまだ稼働していることを示す情報として使用します。この情報はttl秒間キャッシュされます。
よくある質問
現在のプライマリーは、なぜ他の全メンバーに到達できなければならないのですか。ここでクォーラムに依存することはできませんか。
よい質問です。問題は、DCSとPatroniではクォーラムの見え方が異なる可能性があることです。DCSノードはアベイラビリティーゾーン間に均等に配置しなければなりませんが、Patroniにはそのような規則はありません。さらに重要なのは、そのような規則を導入して強制する仕組みがないことです。Patroniノードの過半数がプライマリーを含めて、分断されたネットワークの敗者側に入り、少数のノードが勝者側に入った場合、プライマリーを降格させなければなりません。他の全メンバーを確認することでのみ、この状況を検出できます。
DCSが停止している間にノードやPodが終了した場合はどうなりますか。
DCSにアクセスできない場合、ハートビートループの各サイクル(
loop_wait秒ごと)で、「クラスターの他の全メンバーにアクセスできるか」という確認を実行します。Podやノードが終了すると、この確認が失敗し、Postgresは読み取り専用に降格します。DCSが復旧するまで復帰しません。DCSが停止している間にPatroniクラスターの全メンバーが失われた場合はどうなりますか。
Patroniは、クラスターにリーダーがいない場合でもバックアップから新しいレプリカを作成するように構成できます。ただし、新しいメンバーが
/failsafeキーに含まれていなければ、リーダーロックを取得して昇格することはできません。プライマリーがDCSへのアクセスを失い、レプリカはアクセスを維持している場合はどうなりますか。
プライマリーはフェイルセーフのコードを実行し、既知のすべてのレプリカに連絡します。これらのレプリカは、この情報をプライマリーが稼働していることを示す情報として使用し、DCS内のリーダーロックが期限切れになってもリーダー選出を開始しません。
フェイルセーフモードを有効にするにはどうすればよいですか。
failsafe_modeを有効にする前に、全メンバーのPatroniのバージョンが最新であることを確認してください。その後、PATCH /configREST API 、またはpatronictl edit-config -s failsafe_mode=true を使用できます。