KeycloakをAWSに載せる構成は、ALBでTLSを終端し、ECS FargateでKeycloakのコンテナを動かし、RDS for PostgreSQLにデータを置く3層が基本形です。構成図だけなら単純ですが、ALBのヘルスチェックの宛先、Secrets Managerのパスワードのローテーション、2台目を足したときのクラスタ通信で、Docker Composeでは起きなかった止まり方をします。本記事では、2026年11月6日時点の最新版Keycloak 26.8.1を前提に、ECSのタスク定義、ALBのターゲットグループ、セキュリティグループの設定例をコピーして使える形で示し、最後にAmazon Cognitoとどちらを選ぶかを料金と要件で判断します。
まとめ:KeycloakのAWS構成はALB配下のECSとRDSで組みCognitoと要件で分ける
AWSでKeycloakを本番運用するなら、ビルド済みのイメージをECRに置き、ECS Fargateでstart --optimizedを実行します。ALBのターゲットグループは通常の転送先を8080番、ヘルスチェックを管理ポート9000番の/health/readyに分けて設定してください。ALBはX-Forwarded-Hostを付けないため、KC_HOSTNAMEにはスキーム付きの公開URLを書きます。
DBのパスワードはSecrets Managerから注入しますが、RDSが管理するマスターパスワードは既定で7日ごとに変わり、ECSは起動時にしか値を読みません。Keycloak専用のDBユーザーを作って渡してください。2台以上に増やすときは、タスク同士でTCPの7800番と57800番を通します。
認証フローの作り込み、SAMLでのSSO配布、AWS以外への移行のいずれかが要件ならKeycloakを選び、どれも無ければCognitoで足ります。
AWSでKeycloakを動かす3層構成とECS・EKS・EC2を選ぶ基準
最初に、どのサービスをどのサブネットに置くかと、コンテナの実行基盤を何にするかを決めます。Keycloakそのものの機能やOkta・Auth0との違いはKeycloakとは?Oktaとの違いと連携手順で扱っているので、本記事はAWS上の組み方に絞ります。
ALB・ECS Fargate・RDS PostgreSQLの3層とサブネットの配置
インターネットから届くのはALBだけにします。ALBはパブリックサブネットに置き、KeycloakのタスクとRDSはプライベートサブネットに閉じます。通信の向きは次の4本だけです。
- 利用者からALBへ:443番(ACMの証明書でTLSを終端)
- ALBからKeycloakへ:8080番(アプリ)と9000番(ヘルスチェック)
- KeycloakからRDSへ:5432番
- Keycloakのタスク同士:7800番と57800番(2台以上のときだけ)
この4本をそのままセキュリティグループのルールに写します(コマンドは後の章)。プライベートサブネットのタスクがECRやSecrets Managerに届くよう、NATゲートウェイかVPCエンドポイントも用意してください。
ECS・EKS・EC2のどれに載せるかを運用する人数で決める基準
実行基盤の選び方は、Keycloakの性能ではなく、運用する側の体制で決まります。
| 実行基盤 | 向いている体制 | 更新のやり方 |
|---|---|---|
| ECS Fargate | Kubernetesの担当者がいない | タスク定義のイメージを差し替える |
| EKS+Operator | すでにEKSを運用している | Keycloakのカスタムリソースを更新 |
| EC2に直接 | コンテナを使えない事情がある | サーバーごとに手作業で入れ替え |
EKSを既に持っているなら、Keycloak Operatorを入れる構成が自然です(EKS自体はAmazon EKSとは?ECSとの使い分けを参照)。Keycloakのためだけに新しくEKSを立てるのは過剰なので、本記事はECS Fargateを前提に進めます。
RDSとAuroraをKeycloakのデータベースにする対応版と接続設定
Keycloakはレルム・ユーザー・セッション以外の設定をすべてDBに保存します。AWSではRDS for PostgreSQLかAurora PostgreSQLのどちらかを選びます。
RDSとAurora PostgreSQLの対応版とTLS接続・接続プールの条件
Keycloakのデータベースのガイドによると、対応版は次のとおりです。どちらもKC_DBの値はpostgresで共通です。
| DB | 対応する系列 | Keycloakの検証版 |
|---|---|---|
| PostgreSQL(RDSを含む) | 18・17・16・15・14 | 18 |
| Aurora PostgreSQL | 17・16・15 | 17.5 |
ガイドは、表に無い版での利用を対象外と明記しています。Aurora PostgreSQL 17系は既定でTLS接続を求めるため、リージョンごとの証明書バンドルで証明書を検証する設定まで含めて準備します。接続プールの上限db-pool-max-sizeの既定は100です。タスク数を増やすとDBへの接続数も比例して増えるので、RDSのインスタンスクラスの最大接続数と掛け算で確かめてください。プールの細かな設定値はKeycloakのデータベース設定と使い方にまとめています。
Auroraのフェイルオーバーに追従するAWS JDBC Wrapperの組み込み
Auroraを選ぶ理由がフェイルオーバーの速さなら、AWS Advanced JDBC Wrapperを入れます。このドライバーはKeycloakの配布物に含まれていないため、イメージへ自分で追加する作業が必要です。DBのガイドの例を、ビルド済みイメージを作る2段階のDockerfileに組み込むと次のようになります。
# Dockerfile:Aurora 向けにドライバーを足したビルド済みイメージ
FROM quay.io/keycloak/keycloak:26.8.1 AS builder
ENV KC_DB=postgres
ENV KC_DB_DRIVER=software.amazon.jdbc.Driver
ENV KC_HEALTH_ENABLED=true
ENV KC_METRICS_ENABLED=true
# ガイドの例と同じ 4.0.1 を providers に置く(build より前)
ADD --chmod=0666 https://github.com/awslabs/aws-advanced-jdbc-wrapper/releases/download/4.0.1/aws-advanced-jdbc-wrapper-4.0.1.jar /opt/keycloak/providers/aws-advanced-jdbc-wrapper.jar
RUN /opt/keycloak/bin/kc.sh build
FROM quay.io/keycloak/keycloak:26.8.1
COPY --from=builder /opt/keycloak/ /opt/keycloak/
ENTRYPOINT ["/opt/keycloak/bin/kc.sh"]
接続先のURLは、通常のPostgreSQLのURLにaws-wrapperを挟んでjdbc:aws-wrapper:postgresql://で始めます。ガイドは、使うプラグインをwrapperPluginsで上書きする場合もfailoverかfailover2を必ず含めるよう求めています。2026年11月3日にドライバーの4.6.0が出ていますが、版を上げる前に検証環境で組み合わせを確かめてください。2段階ビルドと--optimizedの関係はKeycloak Dockerの本番構成、RDSとの違いはAmazon Auroraとは?RDSとの違いで説明しています。
ECSタスク定義でKeycloakを本番モード起動する環境変数とシークレット
イメージをECRに置いたら、ECSのタスク定義を書きます。ここで決めるのは、起動コマンド、開けるポート、環境変数、Secrets Managerから注入する値の4つです。
タスク定義JSONの全体とSecrets ManagerからのDB認証情報の注入
次のタスク定義は、CPU 1 vCPU・メモリ2GBのFargateタスクでKeycloakを1コンテナ動かす例です。アカウントID・リージョン・ARNの末尾は自分の環境に置き換えてください。
{
"family": "keycloak",
"requiresCompatibilities": ["FARGATE"],
"networkMode": "awsvpc",
"cpu": "1024",
"memory": "2048",
"executionRoleArn": "arn:aws:iam::123456789012:role/ecsTaskExecutionRole",
"containerDefinitions": [{
"name": "keycloak",
"image": "123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/keycloak:26.8.1",
"command": ["start", "--optimized"],
"portMappings": [
{ "containerPort": 8080 },
{ "containerPort": 9000 },
{ "containerPort": 7800 },
{ "containerPort": 57800 }
],
"environment": [
{ "name": "KC_DB_URL", "value": "jdbc:postgresql://keycloak-db.xxxx.ap-northeast-1.rds.amazonaws.com:5432/keycloak" },
{ "name": "KC_HOSTNAME", "value": "https://auth.example.com" },
{ "name": "KC_HTTP_ENABLED", "value": "true" },
{ "name": "KC_PROXY_HEADERS", "value": "xforwarded" },
{ "name": "KC_PROXY_TRUSTED_ADDRESSES", "value": "10.0.0.0/24,10.0.1.0/24" }
],
"secrets": [
{ "name": "KC_DB_USERNAME", "valueFrom": "arn:aws:secretsmanager:ap-northeast-1:123456789012:secret:keycloak/db-AbCdEf:username::" },
{ "name": "KC_DB_PASSWORD", "valueFrom": "arn:aws:secretsmanager:ap-northeast-1:123456789012:secret:keycloak/db-AbCdEf:password::" },
{ "name": "KC_BOOTSTRAP_ADMIN_USERNAME", "valueFrom": "arn:aws:secretsmanager:ap-northeast-1:123456789012:secret:keycloak/admin-GhIjKl:username::" },
{ "name": "KC_BOOTSTRAP_ADMIN_PASSWORD", "valueFrom": "arn:aws:secretsmanager:ap-northeast-1:123456789012:secret:keycloak/admin-GhIjKl:password::" }
],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/keycloak",
"awslogs-region": "ap-northeast-1",
"awslogs-stream-prefix": "kc"
}
}
}]
}
valueFromの末尾の:username::は、ECSのシークレット注入のドキュメントにある書式で、JSONのシークレットから1つのキーだけを取り出し、版の指定を省いてAWSCURRENTを使う指定です。Fargateでキー単位の取り出しを使うには、プラットフォームバージョン1.4.0以降が必要です。タスク実行ロールには、対象のシークレットに対するsecretsmanager:GetSecretValueの権限を付けてください。
メモリの2GBは、コンテナのガイドが小規模な本番構成の目安とする値で、ヒープは既定でその70%までです。
RDSのパスワード自動ローテーションでKeycloakが接続できなくなる理由
RDSを作るときに「Secrets Managerでマスター認証情報を管理」を選ぶと、RDSが作ったそのシークレットをKeycloakにも渡したくなります。2つの公式ドキュメントを並べると、この組み合わせには時限式の落とし穴があります。
- RDSとSecrets Managerの連携:RDSが管理するマスターパスワードは、既定で7日ごとに自動でローテーションされる
- ECSのシークレット注入:値が入るのはコンテナの起動時だけで、後からシークレットが更新されても実行中のコンテナには反映されない
ローテーションが走った時点で、実行中のKeycloakが持つパスワードはDB側と食い違います。既存の接続が生きている間は動き続け、接続プールが新しい接続を張った瞬間に認証エラーになるため、起動から数日後に前触れなく障害として表に出ます。
対策は、マスターユーザーをKeycloakに使わないことです。DBにKeycloak専用のユーザーを作り、そのパスワードを別のシークレットに保存して渡します。専用ユーザーのパスワードを定期的に変えるなら、変えた直後にECSサービスを「新しいデプロイの強制」で入れ替える手順までを1つの作業としてまとめてください。ローテーションの仕組みと料金はAWS Secrets Managerとは?ローテーション設定と採用判断で解説しています。
ALB配下でKeycloakを動かすプロキシ設定とヘルスチェックのポート9000
ALBの設定で間違えやすいのは、Keycloakが受け取るヘッダーと、ヘルスチェックの宛先の2点です。
X-Forwarded-Hostを送らないALBに合わせたKC_HOSTNAMEの書き方
ALBのHTTPヘッダーのドキュメントが挙げるX-Forwarded系のヘッダーは、X-Forwarded-For・X-Forwarded-Proto・X-Forwarded-Portの3つです。nginxの設定でよく足すX-Forwarded-Hostは含まれません。
このため、ホスト名のガイドにある書き方のうち、KC_HOSTNAMEにhttps://auth.example.comのようなURL全体を書く方法を選び、ヘッダーに左右されずに公開URLを固定します。KC_PROXY_HEADERSはxforwardedです。古い構築記事にあるKC_PROXY=edgeは、リバースプロキシのガイドで非推奨のオプションと扱われています。
ALBは既定で、届いたX-Forwarded-Forに利用者のアドレスを後ろへ追記します。ガイドのとおりKC_PROXY_TRUSTED_ADDRESSESを指定しないと全アドレスのヘッダーを信頼する既定になるため、タスク定義の例ではALBを置いたパブリックサブネットの範囲に限っています。
ターゲットグループのヘルスチェック先を管理ポート9000にする設定
Keycloak 26系では、ヘルスチェックのエンドポイントはアプリ用の8080番ではなく、管理インターフェースの9000番に出ます。競合の英語記事には8080番の/health/readyを見に行く例がありますが、26系ではそこに応答はありません。ALBのヘルスチェックの設定は、既定ではトラフィックと同じポートを見るので、ポートを明示して上書きします。
# 転送先は 8080、ヘルスチェックは 9000 の /health/ready
aws elbv2 create-target-group \
--name keycloak-tg \
--protocol HTTP --port 8080 \
--target-type ip \
--vpc-id vpc-0123456789abcdef0 \
--health-check-protocol HTTP \
--health-check-port 9000 \
--health-check-path /health/ready \
--health-check-interval-seconds 10 \
--healthy-threshold-count 2 \
--unhealthy-threshold-count 2 \
--matcher HttpCode=200
Fargateのタスクはawsvpcで動くため、ターゲットの種類はipにします。ALBの既定値は間隔30秒・正常判定に連続5回で、そのままだと転送開始まで2分半かかるため、上の例では10秒・2回に縮めています。
readyを見るのは、本番構成のガイドが、初期化の途中でもliveとstartedはUPを返すとしてロードバランサーにはreadyを使うよう求めているためです。KC_HEALTH_ENABLEDをビルド時に有効にしていないと応答しません。初回起動はDBのスキーマを作るので、ECSサービスのhealthCheckGracePeriodSecondsには数分の余裕を持たせます。
ALBのリスナールールで/admin/を社内のIPアドレスに限る方法
リバースプロキシのガイドは、/realms/・/resources/・/.well-known/を公開し、/admin/と/realms/master/は内部に限るよう求めています。ALBではリスナールールの条件で同じことができます。
# 優先度10:管理用のパスは社内のアドレスからだけ転送
aws elbv2 create-rule --listener-arn "$LISTENER_ARN" --priority 10 \
--conditions '[{"Field":"path-pattern","Values":["/admin/*","/realms/master/*"]},
{"Field":"source-ip","SourceIpConfig":{"Values":["203.0.113.0/24"]}}]' \
--actions Type=forward,TargetGroupArn="$TG_ARN"
# 優先度20:それ以外のアドレスからの管理用パスは 403
aws elbv2 create-rule --listener-arn "$LISTENER_ARN" --priority 20 \
--conditions '[{"Field":"path-pattern","Values":["/admin/*","/realms/master/*"]}]' \
--actions '[{"Type":"fixed-response","FixedResponseConfig":{"StatusCode":"403","ContentType":"text/plain"}}]'
203.0.113.0/24は社内やVPNの出口のアドレスに置き換えます。ルールは優先度の小さい順に評価されるため、既定のアクションが全パスを転送していても管理用のパスを止めるのは上の2本のルールです。既存のWebアプリの前でALBに認証させたいだけなら、Keycloakを立てずにALBとCognitoで認証を後付けする手順で済む場合もあります。
ECSでKeycloakを2台以上に増やすクラスタ通信とセキュリティグループ
1タスクのままでは、更新やFargateの基盤側の入れ替えのたびにログインが止まります。ECSサービスの希望数を2以上にするときの設定です。
jdbc-pingによるノード発見とポート7800・57800の許可
分散キャッシュのガイドによると、本番モードの既定のキャッシュはjdbc-pingという仕組みでノード同士を見つけます。参加したノードを設定済みのDBに記録するため、マルチキャストを使えないAWSのVPCでも追加の設定なしに動きます。データの送受信は7800番、ノードの異常終了の検知は7800番に50000を足した57800番です。
タスク同士がこの2つのポートで話せないと、各タスクが自分だけのクラスタとして動き、ログアウトしたセッションが別のタスクで生きている不整合の原因になります。セキュリティグループは次のように組みます。
# $ALB_SG・$KC_SG・$DB_SG は作成済みのセキュリティグループID
# ALB から Keycloak へ:アプリ 8080 とヘルスチェック 9000
aws ec2 authorize-security-group-ingress --group-id "$KC_SG" \
--ip-permissions IpProtocol=tcp,FromPort=8080,ToPort=8080,UserIdGroupPairs=[{GroupId=$ALB_SG}] \
IpProtocol=tcp,FromPort=9000,ToPort=9000,UserIdGroupPairs=[{GroupId=$ALB_SG}]
# Keycloak のタスク同士:クラスタ通信 7800 と障害検知 57800
aws ec2 authorize-security-group-ingress --group-id "$KC_SG" \
--ip-permissions IpProtocol=tcp,FromPort=7800,ToPort=7800,UserIdGroupPairs=[{GroupId=$KC_SG}] \
IpProtocol=tcp,FromPort=57800,ToPort=57800,UserIdGroupPairs=[{GroupId=$KC_SG}]
# Keycloak から RDS へ:5432
aws ec2 authorize-security-group-ingress --group-id "$DB_SG" \
--ip-permissions IpProtocol=tcp,FromPort=5432,ToPort=5432,UserIdGroupPairs=[{GroupId=$KC_SG}]
2台目を起動したら、CloudWatch Logsの起動ログでクラスタの参加者が2になったかを確かめ、1のままなら7800番と57800番の許可を疑います。
Keycloak 26.6以降でALBのスティッキーセッションを有効にしない理由
以前のKeycloakは、認証セッションを持つノードの情報をAUTH_SESSION_IDのCookieに付け、ロードバランサーに同じノードへ振り分けさせる設計でした。そのため古い記事には、ALBのターゲットグループでスティッキーセッションを有効にする手順が載っています。
リバースプロキシのガイドは、26.6の改善以降はスティッキーセッションの利点が小さくなったとし、ノード間に負荷を均等に配るよう勧めています。ルートをCookieに付けるオプションも26.8で非推奨になりました。ALBのターゲットグループでもスティッキーセッションは有効にせず、既定のままにします。
KeycloakとCognitoをAWS上で使い分ける料金と要件の判断基準
AWSで認証基盤を用意するとき、Keycloakを自前で動かす代わりにAmazon Cognitoを使う選択肢があります。製品としての比較はKeycloakとはで行っているので、ここでは本記事の構成を運用する手間と天秤にかけます。
Cognito Essentialsの月額とKeycloakの固定費の利用者数での比較
Cognitoの料金ページによると、2026年11月6日時点の料金は月間アクティブユーザー(MAU)単位です。
| 区分 | 無料枠 | 無料枠を超えた分の単価 |
|---|---|---|
| Essentials(新規の既定) | 月10,000 MAU | 1 MAUあたり0.015ドル |
| Plus | なし | 1 MAUあたり0.020ドル |
| SAML・OIDCでの連携ログイン | 月50 MAU | 1 MAUあたり0.015ドル |
Essentialsで月5万人がログインするアプリなら、(50,000−10,000)×0.015ドルで月600ドルです。社内のEntra IDとSAMLで連携する従業員1,000人の社内SSOなら、(1,000−50)×0.015ドルで月14.25ドルになります。
Keycloakの側は、利用者数に関係なくFargateのタスク2つ・RDS・ALBの料金が毎月かかり、2週間前後で出る修正版への追従という人の作業も続きます。MAUが増えるほどKeycloakが割安になりますが、分かれ目はインフラ費より、更新作業を誰が担うかで大きく動きます。
Keycloakを選ぶ4つの要件とCognitoで足りる場面の切り分け
次のどれかに当たるなら、運用の手間を払ってでもKeycloakを選びます。
- ログイン画面や認証フロー(条件付きのMFA、独自の確認手順など)を自由に作り込みたい
- SAMLのIdPとして、複数の業務システムへSSOを配りたい
- AWS以外のクラウドやオンプレミスへ移す可能性がある
- LDAPやActive Directoryの利用者をそのまま取り込みたい
反対に、自社のWebアプリ1つにサインアップとログインを付けたいだけなら、Keycloakは見送ってCognitoを使います。Cognitoでの実装手順はCognitoで認証基盤を実装する手順にまとめているので確認してください。4つの要件のうち2の具体例はKeycloak SAML設定:Entra IDを外部IdPにする手順で確認できます。
Keycloakを選んでも、本記事の構成を自社だけで回せないなら、長期サポートのあるRed Hat build of Keycloakを検討する段階です。AWS上のKeycloakの構成設計から、Cognitoとの比較検討、移行までを任せたい場合は、一創の認証基盤・ID管理システム開発で支援しています。
KeycloakをAWSで構築する担当者からよく受ける質問と回答
AWSでKeycloakを組むときに出やすい疑問をまとめました。
AWSにKeycloakのマネージドサービスはありますか?
AWSのサービス一覧にKeycloakのマネージドサービスは無く、AWSが提供する認証のマネージドサービスはAmazon Cognitoです。Keycloakを使う場合は、本記事のようにECSやEKSで自分で動かすか、第三者が提供するホスティングを選びます。後者は、Keycloakの修正版がどれくらいの間隔で反映されるかを契約前に確かめてください。
RDSのインスタンスはどのくらいの大きさが必要ですか?
Keycloakの負荷はログインとトークン発行の回数で決まり、利用者の総数だけでは決まりません。小さめのインスタンスで始め、CloudWatchでCPUとDBの接続数を見て調整するのが現実的です。接続プールの上限は1タスクあたり既定100なので、タスク数との掛け算がRDSの最大接続数に収まるかも確かめます。止められない用途なら、大きさより先にマルチAZ配置を有効にしてください。
Keycloakの更新はECSでどのように行いますか?
新しい版でイメージをビルドしてECRに登録し、タスク定義のイメージを差し替えてECSサービスを更新します。ECSのローリング更新で新旧のタスクが同時に動くため、同じ系列の修正版の範囲で行ってください。系列をまたぐ更新ではDBのスキーマが変わることがあり、全タスクを止めてから入れ替える手順が必要になります。修正版の公開状況と更新の判定方法はKeycloakの脆弱性対応の手順で扱っています。
管理コンソールへのログインにもCognitoやMFAを使えますか?
Keycloakの管理コンソールは、Keycloakのmasterレルムで認証します。masterレルムにもOTPなどのMFAを設定できるので、まずそこで必須となるよう設定してください。そのうえで、本記事のリスナールールで/admin/と/realms/master/を社内のアドレスに限れば、外部からの総当たりの入口を閉じられます。管理者が少ないなら、Cognitoを挟むよりこの2つの組み合わせが単純です。
ECSのタスクにKeycloak自身のTLS証明書を持たせるべきですか?
ALBとタスクの間はVPCの中の通信なので、ALBでTLSを終端し、タスクはHTTPで受ける構成から始めるのが一般的です。証明書の更新をACMに任せられ、9000番のヘルスチェックもHTTPのまま書けます。規程でVPC内の通信も暗号化する必要があるときだけ、Keycloakに証明書を持たせ、ターゲットグループとヘルスチェックをHTTPSに変えます。
関連記事
- Keycloakとは?Oktaとの違いと連携手順|Auth0・Cognito比較で導入を判断【2026年10月】:Keycloakの機能とCognito・Oktaとの製品比較を確認できます。
- Keycloak Dockerの本番構成:Composeでの起動とリバースプロキシ・ヘルスチェックの設定:ECRに置くビルド済みイメージの作り方を詳しく扱っています。
- Keycloakのデータベース設定と使い方|PostgreSQL接続・対応DB・バックアップから権限モデルまで:RDSにつなぐときの接続プールとバックアップの設定値です。
- Cognitoで認証基盤を実装する手順:ユーザープール作成からaws-jwt-verifyでのJWT検証まで:Cognitoで足りると判断したときの実装手順です。
- 認証・ID管理とは?MFA・SSO・OIDC・IDaaSの違いと選定を解説【2026年版】:自前運用とIDaaSを比べる前提知識をまとめています。