Keycloakの安定運用は、突き詰めるとデータベースとコネクションの設計に行き着きます。PostgreSQL推奨の背景、db-pool-*の設計思想、RDS/Auroraでの落とし穴、Liquibaseによるスキーマ移行と大量ユーザ時のインデックス挙動まで、現場で効く勘所を整理します。
Keycloakは一見するとステートレスなアプリに見えますが、レルム・クライアント・ユーザ・ロール・セッション(の一部)といった構成情報はすべてリレーショナルデータベースに永続化されます。つまりKeycloakの安定性・性能・可用性は、その大部分がデータベースとコネクション設計の品質で決まります。本記事は、Quarkusベースの新しいディストリビューション(現行。WildFly版は非推奨)を前提に、DB選定からコネクションプール、RDS/Aurora運用、Liquibaseによるスキーマ移行までを実務目線で掘り下げます。バージョン依存の挙動は新しめのバージョンを基準にしていますので、導入時は必ず公式ドキュメントで最新値をご確認ください。
01対応データベースとPostgreSQL推奨の理由
Keycloakは複数のRDBMSを公式サポートしています。Supported Configurationsには、PostgreSQL(18.x〜14.x)、MariaDB、MySQL(8.4/8.0 LTS)、Microsoft SQL Server(2022/2019)、Oracle Database(23.x/19c)、そしてマネージド系としてAmazon Aurora PostgreSQL(17.x〜15.x)、Azure SQL Database/Managed Instanceが挙げられています。テスト済みバージョンは版ごとに更新されるため、採用時は当該ページで自分の使うマイナーバージョンが対象内かを確認してください。
コミュニティ・商用(Red Hat build of Keycloak)を問わず、実質的な第一候補はPostgreSQLです。理由は単純で、Keycloak本体とテストがPostgreSQLを中心に回っており、ドキュメント・トラブルシューティング・周辺ツールの情報量が最も厚いためです。マイグレーションのバグ修正やインデックス設計もPostgreSQL基準で検証されることが多く、「枯れた道」を選べる安心感があります。特段の制約(既存資産がOracle/SQL Serverに寄っている等)がなければ、PostgreSQLを推奨します。
02コネクションプールの設計思想(db-pool-*)
Keycloak(Quarkus版)はAgroalベースのコネクションプールを内蔵し、以下のオプションで制御します(Configuring the database)。
db-pool-initial-size— 起動時に確保する初期コネクション数db-pool-min-size— プールが維持する最小コネクション数db-pool-max-size— 最大コネクション数(デフォルト100)
公式の高可用性ガイドは、Concepts for database connection poolsで明快な指針を出しています。「最良の性能のためには、initial・min・maxをすべて同じ値にすべき」というものです。理由は、リクエスト到来時に新規コネクションを張るのがコスト高で応答を遅らせ、さらに短時間に大量のコネクションを作ると悪化を招く「スタンピード」を引き起こすためです。あらかじめ張り切っておけば、リクエストは待たされません。加えて、コネクションを長く開いたままにすることでサーバサイドのステートメントキャッシュが効きます(PostgreSQLでは同一クエリが5回実行されると自動的にサーバサイドprepared statementが有効化される、という挙動が言及されています)。
02b接続数の総量設計とmax-lifetime
コネクション設計で最初に破綻するのは、たいてい総量計算の欠落です。原則はシンプルで、「1インスタンスあたりの最大DBコネクション数 × 稼働Keycloakインスタンス数」がDB側の許可する最大接続数を超えてはならない、という点です。HA構成でスケールアウトするほどこの積は膨らみます。RDS/Auroraでは`max_connections`がインスタンスクラスのメモリに応じて決まるため、小さめのインスタンスだと想像以上に上限が低いことがあります。プール上限×台数に、管理接続・監視・バッチ・移行作業分の余白を足しても収まるかを必ず机上で検算してください。
もう一つ見落とされがちなのが、DB側のアイドル接続タイムアウト(`wait_timeout`等)との整合です。公式ドキュメントは、DB側で`wait_timeout`を明示している場合、db-pool-max-lifetimeを`wait_timeout`より小さく設定する必要があると明記しています。推奨は「`wait_timeout`から数分引いた値」です。これを怠ると、DB側が黙って切ったコネクションをプールが生きていると誤認し、突発的な「connection closed」エラーの温床になります。
03RDS / Auroraでの注意点
マネージドPostgreSQL(Amazon RDS / Aurora PostgreSQL)は運用負荷を大きく下げますが、Keycloak特有の注意点があります。最重要はリーダー(読み取りレプリカ)への誤接続です。Keycloakは書き込みを伴う処理が多く、リードレプリカに書きに行くと壊れます。公式ドキュメントによれば、KeycloakはPostgreSQL JDBCドライバのtargetServerTypeをprimaryに自動設定し、フェイルオーバー/スイッチオーバー時でも常に書き込み可能なプライマリに接続し、リーダーには繋がないようにしています。これはプライマリデータソースにのみ自動適用される点も明記されています。
- 接続はクラスタ(ライター)エンドポイント経由で。Auroraのリーダーエンドポイントを`db-url`に直指定するのは避けます。フェイルオーバー後の追従はライターエンドポイント+ドライバの`targetServerType=primary`に任せるのが安全です。
- フェイルオーバー時のプール挙動を試験する。フェイルオーバー中は既存コネクションが切れ、一時的にエラーが出ます。ヘルスチェックとリトライ、`db-pool-max-lifetime`の設定で、切れた接続をプールが引きずらないようにします。
- 接続上限に注意。前述の総量設計はマネージドで特に効きます。小さいインスタンスクラスは`max_connections`が低く、スケールアウト時に破綻しやすいです。
04Liquibaseによるスキーマ移行
KeycloakのスキーマはLiquibaseで管理されており、新しいバージョンでスキーマ変更があると、サーバ起動時に自動的にマイグレーションが走ります。開発・小規模環境ではこの自動移行が非常に便利ですが、本番・大規模環境では「起動=スキーマ変更が走る」という挙動そのものがリスクになります。以下の運用原則を推奨します。
- アップグレードは一度に1インスタンスで。複数インスタンスが同時に同じ移行をかけると競合します。移行時はローリングではなく、まず1台で移行を完了させてから残りを上げる手順が安全です。
- 移行のトランザクションタイムアウトを理解する。スキーマ移行・import・exportで使われるトランザクションのタイムアウトは
transaction-setup-timeoutで制御され、デフォルト30分です。大規模データセットでは完了に時間がかかるため、この値の存在を知っておく必要があります。 - 本番移行前に必ずステージングで同容量リハーサル。本番相当のデータ量でマイグレーション時間を実測し、ダウンタイム見積りと切り戻し手順を固めます。
Liquibase自体もKeycloakのバージョンによって更新されており(例として3.5.5系から4.6.2系への更新や、ServiceLoaderベースのカスタム拡張登録方式の導入などがリリースノートに記録されています)、カスタムchangelogを差し込んでいる場合はアップグレード時に互換性を確認してください。
05大量ユーザ時のインデックスと移行閾値
ここが大規模環境で最も刺さるポイントです。Keycloakは新バージョンでインデックス追加を伴う移行があるとき、対象テーブルの行数が閾値を超えていると自動でのインデックス作成をスキップします。公式には、テーブルのエントリ数が300,000件を超える場合、既定では索引作成をスキップし、移行時にコンソールへ該当SQLをログ出力すると説明されています。管理者はKeycloak起動後の適切なタイミングで、そのSQLを手動適用することになります。この閾値はUpgrading Guideの手順に従って変更可能です。
なぜこうなっているかというと、数百万行規模のテーブルへの索引作成は非常に時間がかかり、起動をブロックしてサービス断を招きかねないためです。「勝手に作らずログに出す」ことで、起動失敗や長時間ロックを避ける設計になっています。実務的には次の対応が要ります。
- 移行後のログを必ず確認し、出力されたインデックス作成SQLを回収する。見落とすと索引が無いまま運用が続き、後日の性能劣化として顕在化します。
- 手動適用は低負荷帯に、可能なら
CREATE INDEX CONCURRENTLYで。PostgreSQLでは通常の`CREATE INDEX`が書き込みロックを取るため、大量ユーザ基盤ではオンライン索引作成を検討します。 - ユーザ数の増加を監視指標に入れる。閾値付近でのアップグレードは挙動が変わるため、テーブル行数を把握しておきます。監視設計はマルチアカウント統制や既存の監視基盤と統合しておくと運用が回ります。
06バックアップと復旧設計
Keycloakの「状態」はほぼすべてDBにあります(オフラインセッション等も含む)。したがってバックアップ戦略はDBのバックアップ戦略そのものです。
- PITR(ポイントインタイムリカバリ)を前提に。RDS/Auroraなら自動バックアップ+スナップショット、オンプレなら`pg_dump`/`pg_basebackup`+WALアーカイブでRPOを定義します。認証基盤は止まると全システムが止まるため、RPO/RTOは厳しめに設定するのが妥当です。
- バージョンとスキーマを揃えて復元テストする。DBだけ戻してもKeycloakのバージョンとスキーマが不整合だと起動しません。バックアップ時点のKeycloakバージョンを記録し、復元手順に組み込みます。
- 設定のコード化も忘れずに。レルム・クライアント設定は`kc.sh export`やAdmin REST API経由でエクスポートし、IaCとして版管理しておくと、DB全損時の再構築が早くなります。RPO/RTOの考え方はマルチリージョンDRとRPO/RTOも参考にしてください。
なお`kc.sh export`のような一括エクスポートも前述のtransaction-setup-timeout(既定30分)の影響を受けます。ユーザ数が多い環境では分割エクスポートやタイムアウト調整を検討してください。
—まとめ
Keycloakのデータベース設計は、派手さはありませんが、認証基盤の可用性と性能を静かに支える背骨です。要点を再掲します。
- 特段の理由がなければPostgreSQLを選ぶ。マネージドならRDS/Aurora PostgreSQL。
- コネクションプールは`init=min=max`で固定し、「プール上限×台数+余白 < DB最大接続数」を検算する。
- Aurora/RDSではライターエンドポイント+`targetServerType=primary`でリーダー誤接続を防ぎ、`db-pool-max-lifetime`をDBの`wait_timeout`より短くする。
- Liquibase移行は1台で完了させてからローリング。300,000件超テーブルの索引は手動適用になる前提でログを回収する。
- バックアップはDBのPITR+設定のコード化で二重化する。
EMWはKeycloakでエンタープライズの認証基盤を実構築してきました。DB選定・コネクション設計・大規模移行の勘所は、導入事例でも触れています。関連してKeycloakのAWS上でのHA構成やInfinispanキャッシュチューニングも併せてご覧ください。
—参考(一次情報)
- Configuring the database - Keycloak
- Supported Configurations - Keycloak
- Concepts for database connection pools - Keycloak
- Upgrading Guide - Keycloak