Keycloak クラスタ構成

2019年5月10日 张立强 (liqiang@fit2cloud.com) 著

この記事では、様々なシナリオ(例:クロスDC、Dockerクロスホスト、Kubernetes)でKeycloakクラスタをセットアップするためのソリューションをいくつか紹介します。

Keycloakクラスタのセットアップに関心がある場合、このブログが参考になるかもしれません。

2つのCLIスクリプトファイルが、Keycloakイメージに、ガイドに従って追加されています。

Dockerfileは以下の通りです。そして、これらの2つのファイルがこのブログで最も重要な内容です。これらのファイルは、TCPPING.cli および JDBC_PING.cli から入手できます。

FROM jboss/keycloak:latest

ADD cli/TCPPING.cli /opt/jboss/tools/cli/jgroups/discovery/
ADD cli/JDBC_PING.cli /opt/jboss/tools/cli/jgroups/discovery/

まず、Keycloakクラスタでは、すべてのKeycloakインスタンスが同じデータベースを使用する必要があることを知っておくべきです。これは非常に単純です。もう1つの点はキャッシュについてです(一般的にKeycloakには2種類のキャッシュがあります。1つ目は、realm/client/userのようなパフォーマンスを向上させるためにデータベースから読み込まれる永続データキャッシュ、2つ目は、sessions/clientSessionsのような非永続データキャッシュです。2つ目のキャッシュはクラスタにとって非常に重要です)。キャッシュの設定は少し複雑で、クラスタビューでのキャッシュの一貫性を確保する必要があります。

クラスタリングには合計3つのソリューションがあり、すべてのソリューションはJGroupsのディスカバリプロトコルに基づいています(KeycloakはInfinispanキャッシュを使用し、Infinispanはノードを検出するためにJGroupsを使用します)。

1. PING

PINGは、Keycloakのデフォルトで有効になっているクラスタリングソリューションで、UDPプロトコルを使用します。これに関する設定は不要です。

ただし、PINGはマルチキャストネットワークが有効で、ポート55200が公開されている場合にのみ利用可能です。例えば、ベアメタル、VM、同じホスト内のDockerコンテナなどです。

同じホスト内の2つのKeycloakコンテナでこれをテストしました。

ログから、2つのKeycloakインスタンスが互いを検出し、クラスタ化されたことがわかります。

2. TCPPING

TCPPINGは、TCPプロトコルと7600ポートを使用します。これは、マルチキャストが利用できない場合、例えば、クロスDCのデプロイメントやクロスホストのコンテナなどで使用できます。

クロスホストの2つのKeycloakコンテナでこれをテストしました。

このソリューションでは、コンテナに対して以下の3つの環境変数を設定する必要があります。

#IP address of this host, please make sure this IP can be accessed by the other Keycloak instances
JGROUPS_DISCOVERY_EXTERNAL_IP=172.21.48.39
#protocol
JGROUPS_DISCOVERY_PROTOCOL=TCPPING
#IP and Port of all host
JGROUPS_DISCOVERY_PROPERTIES=initial_hosts="172.21.48.4[7600],172.21.48.39[7600]"

ログから、2つのKeycloakインスタンスが互いを検出し、クラスタ化されたことがわかります。

3. JDBC_PING

JDBC_PINGは、TCPプロトコルと7600ポートを使用し、TCPPINGと似ていますが、違いは、TCPPINGはすべてのインスタンスのIPとポートを設定する必要があるのに対し、JDBC_PINGは現在のインスタンスのIPとポートを設定するだけでよい点です。これは、JDBC_PINGソリューションでは、各インスタンスが自身の情報をデータベースに挿入し、インスタンスがデータベースから読み取ったpingデータによってピアを検出するためです。

クロスホストの2つのKeycloakコンテナでこれをテストしました。

このソリューションでは、コンテナに対して以下の2つの環境変数を設定する必要があります。

#IP address of this host, please make sure this IP can be accessed by the other Keycloak instances
JGROUPS_DISCOVERY_EXTERNAL_IP=172.21.48.39
#protocol
JGROUPS_DISCOVERY_PROTOCOL=JDBC_PING

すべてのインスタンスのpingデータは、インスタンス開始後にデータベースに保存されています。

ログから、2つのKeycloakインスタンスが互いを検出し、クラスタ化されたことがわかります。

もう一つ

上記のソリューションはほとんどのシナリオで利用できますが、Kubernetesなどの一部のシナリオではまだ十分ではありません。

Kubernetesでの一般的なデプロイメントは、1つのDeployment/ReplicateSet/StatefulSetが複数のKeycloak Podを含む構成です。Podはスケールアップ/ダウンしたり、別のノードにフェイルオーバーしたりする可能性があるため、動的であり、クラスタはこれらの動的なメンバーを検出および削除する必要があります。

Kubernetesでは、DNS_PINGまたはKUBE_PINGを使用できます。これらは実環境で非常にうまく機能します。

DNS_PINGとKUBE_PINGに加えて、JDBC_PINGもKubernetesの別のオプションです。

Kubernetesでは、マルチキャストは同じノード内のコンテナに対してのみ利用可能であり、PodにはTCPPINGまたはJDBC_PINGを設定するために使用できる静的IPがありません。しかし、上記のJDBC_PING.cliではこれに対処しており、JGROUPS_DISCOVERY_EXTERNAL_IP環境変数を設定しない場合、Pod IPが使用されます。つまり、Kubernetesでは、JGROUPS_DISCOVERY_PROTOCOL=JDBC_PINGを設定するだけで、Keycloakクラスタは正常に動作します。

議論

提案やコメントは、Keycloak User Mail List または このGitHubリポジトリ を通じて議論できます。