高可用性
コアが 1 台だけの構成は単一障害点です。すべてのチェックをスケジュールし、すべてのアラートを 評価し、API を提供するのがその 1 台だからです。高可用性(HA)は、同じストア群に対して複数の コアを動かすことでこれを解消し、どれがアクティブになるかは自動のリーダー選出が決めます。 これはオプトインで既定は無効です — HA を無効にした単一コアのデプロイは、これまでとまったく 同じ挙動になります。
HA がカバーする範囲
Section titled “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-a、core-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 導入前のデプロイと同一の挙動になります。
変数の詳細は設定リファレンスを参照してください。
トラフィックのルーティング
Section titled “トラフィックのルーティング”2 つのプローブエンドポイントがあり、その意味は明確に異なります。
| エンドポイント | 応答 | 意味 |
|---|---|---|
/healthz |
すべてのコアで常に 200 |
プロセスの死活 — 認証なし、ストアへのアクセスなし。再起動の判断に使います。 |
/readyz |
リーダーのみ 200、スタンバイは 503 |
レディネス —「トラフィックはここへ」。HA が無効なら常に 200。 |
ロードバランサのヘルスチェックは /readyz に向け、API と WebUI のトラフィックをこれで
ルーティングしてください。200 を返すコアはちょうど 1 台なのでクライアントは常にリーダーへ
たどり着き、フェイルオーバー時は新しいリーダーが 200 を返し始めることでトラフィックが自動的に
切り替わります。/healthz は死活プローブ用に残してください — スタンバイは健全ですがレディでは
なく、間違ったエンドポイントで 503 を返したからといって再起動してしまっては本末転倒です。
各コアは Prometheus の /metrics に yagra_core_is_leader ゲージも公開します(リーダーは 1、
スタンバイは 0)。フェイルオーバーを推測するものではなく目に見える出来事にするため、自分たちの
監視に組み込んでおく価値があります。オブザーバビリティを参照して
ください。
コアをまたぐセッション
Section titled “コアをまたぐセッション”既定では、ログインセッションはコアのプロセスごとに保持されます — つまりフェイルオーバーは 全員をサインアウトさせ、新しいリーダーはインシデントの最中にチーム全員へ再ログインを求めます。
解決策は共有のセッション署名鍵です。同じ 32 バイトの鍵をすべてのコアにマウントし、
YAGRA_SESSION_KEY_FILE をそこへ向けます。するとセッショントークンはステートレスな署名付きに
なり、どのコアでもログインが受理され、コアの再起動やフェイルオーバーを越えて有効です。
ログアウト、ユーザーの無効化、ロールの変更、パスワードのリセットは、引き続きすべてのコアへ
即座に反映されます。
# 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 を有効にした場合、コアは起動して警告を出すだけです — すべて動作しますが、
フェイルオーバーでユーザーはログアウトされます。
ローカルで試す
Section titled “ローカルで試す”リポジトリには、すぐ使える 2 コア構成のオーバーレイ docker-compose.ha.yml が同梱されています。
単一ノードのスタックに 2 台目のコア(core-b、API は **http://localhost:8081**)を重ね、両方で
HA を有効にします。
docker compose -f docker-compose.yml -f docker-compose.ha.yml up --buildそのうえで、別のシェルから選出の様子を眺めます。
# 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-acurl -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 corecurl -s -o /dev/null -w '%{http_code}\n' http://localhost:8081/readyz # 200 within secondsこのオーバーレイは評価用です。本番の HA デプロイは、同じ材料を実際のロードバランサの背後に
置いたものになります — たとえば Kubernetes の Deployment でコアを動かし、/readyz を
レディネスプローブにすれば、Ready になるのは常にリーダーだけです。デプロイ方法そのものは
インストールガイドで扱います。
- アクティブ/パッシブであり、アクティブ/アクティブではありません。 スケジューリング・受信・ アラートはすべて 1 台のリーダーが行い、スタンバイが足すのは可用性であってスループットでは ありません。監視のキャパシティを水平にスケールさせるのは、コアの増設ではなくポーラーです。
- 書き込みはリーダーに集中します。 スタンバイは読み取りを提供して待機します。
/readyzで ルーティングしておけば、クライアントは常に「すべてを行えるコア」を向いたままになります。 - フェイルオーバーはゼロではなく数秒です。 引き継ぎ中に飛んでいたリクエストは失敗しうるので リトライしてください。共有セッション鍵を設定していれば、誰も再ログインする必要はありません。