Keycloakの安定運用は、内蔵するInfinispanキャッシュをどこまで理解しているかで決まります。sessionsやauthenticationSessions、loginFailuresといったキャッシュの性格差、owners数の意味、embedded/externalの選択、そしてKeycloak 26で標準化された永続セッションを、現場のチューニング観点で整理します。
Keycloakを本番で運用していて、原因不明のメモリ増加やクラスタ再起動後のセッション消失、ノード障害時の挙動に頭を悩ませた経験は、多くの実務者が共有しているところだと思います。これらの多くは、Keycloakが内蔵するInfinispanキャッシュの性格を正しく理解することで見通しが立ちます。本記事では、キャッシュの種類ごとの役割から、owners数、メモリ、そしてKeycloak 26で大きく変わったセッション保存方式まで、チューニングの勘所を実務目線で掘り下げます。
01Keycloakが持つキャッシュの全体像
Keycloakは内部にInfinispanを組み込んでおり、キャッシュは大きく3系統に分かれます。それぞれ役割と障害時の性格が異なるため、まずはこの区別を押さえることが出発点になります。
- ローカルキャッシュ:
realms/users/authorization/keys/crl。各ノードがDB問い合わせを減らすために持つ、ノードローカルなキャッシュです。既定で1ノードあたり10,000エントリ程度に制限されます(keysは1,000エントリ・1時間有効)。 - レプリケートキャッシュ:
work。全ノードに同じデータを複製し、主にキャッシュ無効化(invalidation)メッセージの伝播に使われます。 - 分散キャッシュ:
sessions/clientSessions/offlineSessions/offlineClientSessions/authenticationSessions/loginFailures/actionTokens。クラスタ全体でデータを分散保持し、どのノードにアクセスしても同じ状態を参照できるようにします。
この分類は公式のConfiguring distributed cachesに整理されています。ローカルキャッシュはDBを裏に持つため失っても再取得できますが、分散キャッシュの一部は「メモリにしか存在しない」ものがあり、ここがチューニングと障害設計の焦点になります。
02キャッシュごとの役割と「揮発性」の違い
分散キャッシュの中でも、認証フロー中の一時状態を持つキャッシュは性格が異なります。実務でトラブルの起点になりやすいので、代表的なものを整理します。
- authenticationSessions:ログイン処理の途中状態(認証フロー中のセッション)を保持します。分散キャッシュに載せることで、ユーザーがクラスタ内のどのノードにリダイレクトされても認証状態を失わずに済みます。
- loginFailures:ブルートフォース検知のための失敗ログイン回数などを保持します(誰が何回パスワードを間違えたか等)。
- actionTokens:メール確認やパスワードリセットなど、単回利用トークンの状態を保持します。
- sessions / clientSessions:ログイン後のユーザーセッション・クライアントセッション本体です。Keycloak 26以降は保存方式が大きく変わりました(後述)。
actionTokens / authenticationSessions / loginFailures / work の4つには上限(max-count)を設定できないと明記されています。これらは「メモリにしか存在しない揮発性データ」であり、エビクション対象にすると認証途中のユーザーが弾かれるためです。上限をかけようとして設定エラーに遭遇したら、この制約を思い出してください。02owners数が決める「何ノードまで落ちても大丈夫か」
分散キャッシュのチューニングで最初に理解すべきはowners(num_owners)です。これは各エントリを何ノードにコピーして持つかを表します。現行Keycloakの分散キャッシュの既定はowners=1(単一オーナー)で、owners "2"は冗長性を高めたいときに明示的に指定する値です。とくにpersistent-user-sessionsが有効なKeycloak 26以降は、セッションの真実の源がDBにあるため単一オーナーでも足り、メモリから失われてもDBから再読込されます。
重要なのは、これがDBに裏付けのない揮発性キャッシュでは「耐えられる同時ノード障害数」を直接左右する点です。単一クラスタHAの概念では、authenticationSessions / loginFailures / actionTokens について「同時に落ちたノード数が num_owners 以上になると、エントリ喪失が起こりうる」と明記されています。既定のowners=1では1ノードの障害でも該当エントリを失いうる一方、owners=2に上げれば2ノード同時障害で初めて両方のレプリカを失う、という関係です。
- owners=1にすると:メモリ消費とレプリケーションのオーバーヘッドは減りますが、1ノードのクラッシュだけで認証途中のユーザーが弾かれます。揮発性キャッシュでこれをやると体感品質に直結します。
- owners=3にすると:2ノード同時障害まで耐えられますが、メモリとネットワークのコストが上がります。ゾーン分散(トポロジー認識)と組み合わせて、可用性要件が厳しい場合の選択肢です。
owners=2のとき、可能な限り2つのオーナーを別ノードに配置しようとします。ただしKubernetesの既定topologySpreadConstraintsはScheduleAnywayのため、条件次第でレプリカが同一障害ドメインに寄ることがあります。可用性ゾーンをまたいだ配置を本気で担保したいなら、スケジューリング制約側も併せて見直してください。03embedded と external(remote)の使い分け
Infinispanの動かし方には2通りあります。どちらを選ぶかは、可用性要件と運用体制で決まります。
- embedded(内蔵):KeycloakプロセスにInfinispanが同居し、Keycloakノード同士がJGroupsでクラスタを組みます。追加コンポーネント不要で、単一クラスタ構成の標準です。設定は
cache-embedded-*系(例:cache-embedded-network-bind-port既定7800、cache-embedded-sessions-max-count)で行います。 - external / remote(外部):独立したInfinispanクラスタを別途立て、KeycloakはRemote Cacheとして利用します。
cache-remote-host/cache-remote-port(既定11222)/cache-remote-username/cache-remote-passwordで接続します。マルチサイト(クロスサイトレプリケーション)構成では各サイトに外部Infinispanを置く形が前提になります。
マルチサイト構成の詳細はDeploying Infinispan for HAにまとまっています。externalを選ぶ場合、外部Infinispanクラスタ自体の運用・監視・容量管理という新たな責務が増える点は、あらかじめ体制に織り込んでおくべきです。
なお、現行はQuarkusベースのディストリビューションが標準で、旧WildFlyベースは非推奨です。本記事の設定名・既定値はQuarkus版・新しめのバージョン基準ですが、バージョン依存の値は必ず自環境の公式ドキュメントで確認してください。認証基盤の移行を検討中の方は、兄弟記事のQuarkusディストリビューションへの移行も参考になります。
04Keycloak 26で変わった「永続セッション」
キャッシュのメモリ挙動を語るうえで避けて通れないのが、Keycloak 26で標準化された永続ユーザーセッション(persistent-user-sessions)です。ここは従来の常識を上書きする変更なので、丁寧に押さえます。
Storing sessions in Keycloak 26によれば、従来はセッションが分散Infinispanのメモリ上にのみ存在し、クラスタ再起動やアップグレードで消える問題がありました。KC26以降は既定で、
- DBが真実の源(source of truth):セッションはデータベースに永続化され、再起動やアップグレードを跨いで生き残ります。
- メモリはルックアップキャッシュ:
sessions/clientSessionsはメモリにも載りますが、あくまで高速参照用のキャッシュに格下げされました。既定で1ノードあたり10,000エントリに制限されます。
この結果、メモリ消費は従来より下がり、代わりにDB利用が増える、というトレードオフになりました。逆に永続セッションを無効化(--features-disabled=persistent-user-sessions)すると従来のインメモリ方式に戻せますが、メモリ消費が増え、クラスタ再起動でセッションが失われます。なお、multi-site機能を有効にした構成では永続セッションの無効化はできません。
05メモリ見積もりとセッション激増時の挙動
「セッションが急増したときメモリはどうなるのか」は、キャパシティ設計で必ず聞かれる問いです。公式のメモリ・CPUサイジングが具体的な数値を出しています。
- ベースライン:Realmデータのキャッシュと10,000セッションをキャッシュしたPod 1つで、約1250MBのRAM。この1250MBには非ヒープ用の約300MBが含まれ(上乗せではなく内数)、ヒープ相当は約950MBです。ヒープ上限を70%に置く前提だと、メモリlimitは約(1250−300)/0.7≒1357MBが目安になります。
- CPU目安:パスワードログインは1 vCPUあたり約15ログイン/秒、クライアントクレデンシャル付与は約120/秒、リフレッシュトークンは約120/秒。スパイク対策としてCPUは150%の余裕を推奨。
- クライアント数の落とし穴:2,500を超える異なるクライアントを同時に扱うと、既定10,000エントリのキャッシュでは不足し、DBがボトルネックになりうるため上限拡大が必要になる、と明記されています。
KC26の永続セッション下では、メモリキャッシュから溢れたセッションは破棄されても消失にはならず、必要時にDBから再ロードされます。つまりセッション激増時は「メモリが青天井に膨らむ」のではなく「DBアクセスとレイテンシが増える」方向に効きます。ここを取り違えると、対策としてメモリを積むべきか、DBを増強すべきか(あるいはキャッシュ上限を上げるべきか)の判断を誤ります。DB側のチューニングは兄弟記事のデータベースのチューニングと併せて設計してください。
cache-embedded-sessions-max-countでsessions/clientSessionsの上限を調整できますが、これは永続セッション有効時の話です。永続セッションを無効化(volatile)した構成では、そもそもsessions/clientSessionsへの上限設定はサポートされません。自環境がどちらのモードで動いているかを先に確認してから上限をいじってください。06チューニングの実務チェックリスト
ここまでを踏まえ、実際に手を動かすときの確認順序を整理します。
- まずモードを確定する:永続セッション(KC26既定)か、揮発(volatile)か。これで上限設定の可否とメモリ挙動が変わります。
- owners数を可用性要件から逆算する:何ノード同時障害まで許容するかを決め、揮発性キャッシュ(authenticationSessions等)の体感影響とメモリコストを天秤にかける。既定は
1で、揮発性キャッシュの可用性を重視する場合に明示的に2以上へ上げます。 - ノード配置を疑う:owners=2でもレプリカが同一ゾーンに寄っていないか。topologySpreadConstraintsやアフィニティを確認。
- キャッシュ上限とクライアント数を突き合わせる:同時クライアントが2,500超なら既定10,000では不足しうる。統計(statistics="true")を有効にしてヒット率を実測する。
- embedded/externalの責務境界:externalを選ぶなら外部Infinispanの監視・容量管理を運用に組み込む。マルチサイトはremoteTimeout(既定5000ms相当)がレスポンスとエラー率のトレードオフになる点を把握しておく。
- セッション激増はDB側に効くと理解する:永続セッション下ではメモリ膨張ではなくDB負荷増として現れる。監視のアラート設計もそこに向ける。
監視設計そのものについては、可観測性(メトリクス/トレース)や当社の導入事例もあわせてご覧ください。Keycloakでの認証基盤構築では、これらのキャッシュ挙動を前提にキャパシティと監視を設計しています。
—まとめ
Keycloakのキャッシュチューニングは、「どのキャッシュがDBに裏付けられ、どれがメモリにしか存在しないか」という性格の違いを理解することから始まります。owners数は耐えられる同時ノード障害数を直接決め、KC26の永続セッションはメモリ挙動の常識を「DBを真実の源とするルックアップキャッシュ」へと書き換えました。セッション激増はメモリ膨張ではなくDB負荷として現れる——この視点を持てば、メモリを積むのか、DBを増強するのか、キャッシュ上限を上げるのかの判断が一段クリアになります。バージョン依存の値は常に公式で確認しつつ、自環境のモードとowners設定を起点に、監視と容量設計を組み立ててください。