コンテンツにスキップ

高可用性

コアが 1 台だけの構成は単一障害点です。すべてのチェックをスケジュールし、すべてのアラートを 評価し、API を提供するのがその 1 台だからです。高可用性(HA)は、同じストア群に対して複数の コアを動かすことでこれを解消し、どれがアクティブになるかは自動のリーダー選出が決めます。 これはオプトインで既定は無効です — HA を無効にした単一コアのデプロイは、これまでとまったく 同じ挙動になります。

Yagra の HA は、自動で選出されるアクティブ/パッシブのコアペア(スタンバイをさらに増やす ことも可能)です。

  • コア — 複数の yagra-core インスタンスが同じ PostgreSQL・NATS・VictoriaMetrics(および 任意の Redis やその他)を共有します。1 台がリーダーに選出されて処理を担い、残りはスタンバイ として待機して、リーダーが落ちれば数秒以内に引き継ぎます。二重ポーリングも通知の重複も ありません。
  • ポーラー — このページから必要とするものはありません。ポーラーはステートレスで本質的に冗長です。 プールごとに複数のポーラーを動かしておけば、失われたポーラーのノードは自動的に残りへフェイル オーバーします。分散ポーリングを参照してください。
  • ストア — これは Yagra ではなくプラットフォーム側の仕事です。PostgreSQL のレプリケーション、 VictoriaMetrics の冗長化、NATS のクラスタリングは、それぞれの製品のツールで設定するもので ここでは扱いません。Yagra は与えられたアドレスに接続するだけです。なお Redis の喪失はいずれに せよ致命的ではありません — 再構築可能なミラーだからです。

言い換えると、HA が落ちないようにするのはオーケストレーターの部分です。その下にあるデータの 永続性は、バックエンドサービスをどうデプロイしたかで決まります。

すべてのコアインスタンスに YAGRA_ENABLE_HA=true を設定し、同じストア群を指すようにします。 リーダー選出は PostgreSQL の advisory lock で動きます。ロックを保持しているコアがリーダーで、 それが停止すると — クラッシュ、再起動、アップグレード — スタンバイがロックを取得して数秒以内に 引き継ぎます。追加でデプロイする選出サービスはありません。すでに動かしているデータベースが 調停役です。

リーダーは状態を持つ側の処理をすべて担います。スケジューリングとポーラー割当、パッシブイベントの 受信、そしてアラート評価と通知です。スタンバイは API を上げたまま読み取りを提供しつつ、 (後述のとおり)レディネスを拒否するため、トラフィックはリーダーへ向かいます。

実務上の注意が 2 点あります。

  • HA のログ行や診断がどのインスタンス由来かわかるよう、各コアに YAGRA_CORE_ID(例: core-acore-b)を与えてください。
  • リーダーの advisory lock 用接続は、通常のプール(YAGRA_PG_MAX_CONNECTIONS、既定はコアあたり 20)に加えて保持されます — PostgreSQL の max_connections は全コア分の合計にプラス 1 を 見込んでサイジングしてください。

関係する変数は次のとおりで、いずれもコアごとに読まれます。

変数 既定 用途
YAGRA_ENABLE_HA false リーダー選出へのオプトイン。未設定ならロックの取得すら行いません
YAGRA_CORE_ID unset(汎用ラベル) HA のログと診断でこのインスタンスを識別する名前
YAGRA_SESSION_KEY_FILE unset(コアごとのセッション) 共有のセッション署名鍵 — 後述

YAGRA_ENABLE_HA が未設定であれば、単一コアは HA 導入前のデプロイと同一の挙動になります。 変数の詳細は設定リファレンスを参照してください。

2 つのプローブエンドポイントがあり、その意味は明確に異なります。

エンドポイント 応答 意味
/healthz すべてのコアで常に 200 プロセスの死活 — 認証なし、ストアへのアクセスなし。再起動の判断に使います。
/readyz リーダーのみ 200、スタンバイは 503 レディネス —「トラフィックはここへ」。HA が無効なら常に 200

ロードバランサのヘルスチェックは /readyz に向け、API と WebUI のトラフィックをこれで ルーティングしてください。200 を返すコアはちょうど 1 台なのでクライアントは常にリーダーへ たどり着き、フェイルオーバー時は新しいリーダーが 200 を返し始めることでトラフィックが自動的に 切り替わります。/healthz は死活プローブ用に残してください — スタンバイは健全ですがレディでは なく、間違ったエンドポイントで 503 を返したからといって再起動してしまっては本末転倒です。

各コアは Prometheus の /metricsyagra_core_is_leader ゲージも公開します(リーダーは 1、 スタンバイは 0)。フェイルオーバーを推測するものではなく目に見える出来事にするため、自分たちの 監視に組み込んでおく価値があります。オブザーバビリティを参照して ください。

既定では、ログインセッションはコアのプロセスごとに保持されます — つまりフェイルオーバーは 全員をサインアウトさせ、新しいリーダーはインシデントの最中にチーム全員へ再ログインを求めます。

解決策は共有のセッション署名鍵です。同じ 32 バイトの鍵をすべてのコアにマウントし、 YAGRA_SESSION_KEY_FILE をそこへ向けます。するとセッショントークンはステートレスな署名付きに なり、どのコアでもログインが受理され、コアの再起動やフェイルオーバーを越えて有効です。 ログアウト、ユーザーの無効化、ロールの変更、パスワードのリセットは、引き続きすべてのコアへ 即座に反映されます。

Terminal window
# generate once, then distribute the same file to every core (mounted read-only)
head -c 32 /dev/urandom > session.key

鍵ファイルはちょうど 32 バイトの生データ(または 16 進 64 文字)でなければなりません。扱いは フェイルクローズです。YAGRA_SESSION_KEY_FILE が設定されているのにファイルが存在しない・読めない・ サイズが違う場合、コアは壊れた鍵で黙ってセッションを発行するのではなく起動を拒否します。 セッション鍵なしで HA を有効にした場合、コアは起動して警告を出すだけです — すべて動作しますが、 フェイルオーバーでユーザーはログアウトされます。

リポジトリには、すぐ使える 2 コア構成のオーバーレイ docker-compose.ha.yml が同梱されています。 単一ノードのスタックに 2 台目のコア(core-b、API は **http://localhost:8081**)を重ね、両方で HA を有効にします。

Terminal window
docker compose -f docker-compose.yml -f docker-compose.ha.yml up --build

そのうえで、別のシェルから選出の様子を眺めます。

Terminal window
# exactly one core is ready (200), the other is a standby (503):
curl -s -o /dev/null -w '%{http_code}\n' http://localhost:8080/readyz # core-a
curl -s -o /dev/null -w '%{http_code}\n' http://localhost:8081/readyz # core-b
# see who won the election ("acquired leadership" in the winner's log):
docker compose logs core core-b | grep -i leader
# stop whichever core holds leadership and watch the standby take over:
docker compose stop core
curl -s -o /dev/null -w '%{http_code}\n' http://localhost:8081/readyz # 200 within seconds

このオーバーレイは評価用です。本番の HA デプロイは、同じ材料を実際のロードバランサの背後に 置いたものになります — たとえば Kubernetes の Deployment でコアを動かし、/readyz を レディネスプローブにすれば、Ready になるのは常にリーダーだけです。デプロイ方法そのものは インストールガイドで扱います。

  • アクティブ/パッシブであり、アクティブ/アクティブではありません。 スケジューリング・受信・ アラートはすべて 1 台のリーダーが行い、スタンバイが足すのは可用性であってスループットでは ありません。監視のキャパシティを水平にスケールさせるのは、コアの増設ではなくポーラーです。
  • 書き込みはリーダーに集中します。 スタンバイは読み取りを提供して待機します。/readyz で ルーティングしておけば、クライアントは常に「すべてを行えるコア」を向いたままになります。
  • フェイルオーバーはゼロではなく数秒です。 引き継ぎ中に飛んでいたリクエストは失敗しうるので リトライしてください。共有セッション鍵を設定していれば、誰も再ログインする必要はありません。