组建 Keycloak 分布式缓存集群并核查节点健康

Keycloak 为高可用和多节点部署提供了基于 Infinispan 的分布式缓存。真正组成一个集群,需要同时满足三件事:节点使用一致的数据库与缓存配置,能通过发现机制找到彼此,并且缓存传输和故障检测链路能够互通。启动了多个进程,并不自动证明集群已经健康。

本文根据 Keycloak Team 的 Configuring distributed caches 译写,核对日期为 2026-10-05。指南版本选择器与 下载页 均标示 26.8.0;原文没有明确首次发表日期。本文围绕默认 jdbc-ping/TCP、内嵌 Infinispan 和持久会话展开,不将多站点、stateless、自定义传输栈或服务网格改造拼入常规部署步骤。

启用集群缓存,先分清生产与开发模式

用 start 进入生产模式时,Keycloak 默认启用分布式缓存,使用 jdbc-ping 栈:节点发现通过配置的数据库进行注册,节点间数据传输使用 TCP。要显式写出缓存模式,官方命令为:

bin/kc.[sh|bat] start --cache=ispn

这里 [sh|bat] 是文档对 Unix/Windows 脚本的合并写法,实际应选择 bin/kc.sh 或 bin\kc.bat。它不是一条可以原样交给 shell 的路径。这个命令只展示缓存选项,数据库、主机名和对外 HTTPS 等生产配置仍须按环境提供。

start-dev 隐式采用 --cache=local,完全禁用分布式缓存,仅适合开发与测试。若用它启动多个实例,看不到集群成员并不意外。数据库指南也明确指出默认 dev-file 仅适合开发,生产应明确选择受支持数据库;同一部署的节点需要连接同一数据库,不能各用自己的开发文件库。

Keycloak两个节点共享数据库进行JDBC_PING2发现和持久会话存储,节点间TCP7800承载默认mTLS缓存传输,57800用于FD_SOCK2故障检测,最终用日志和指标核查成员数
原创示意图:默认 jdbc-ping 集群的发现、传输和验证路径;不代表本次已搭建集群。

缓存保存的究竟是什么

默认配置文件位于 conf/cache-ispn.xml,包含 cache-container 与 JGroups transport 的设置。不同缓存用途不同,不能笼统认为“所有 Keycloak 状态都只在内存里”。

缓存 类型 用途
realms 本地 已持久化的 realm,以及客户端、角色、组等关联数据
users 本地 用户及授予角色、组成员关系等关联数据
authorization 本地 资源、权限、策略等授权数据
keys 本地 外部客户端或身份提供方的公钥
crl 本地 X.509 认证器使用的证书吊销列表
work 复制 向所有节点传播缓存失效消息
authenticationSessions 分布式 登录认证过程中创建、完成或过期的认证会话
sessions、clientSessions 分布式 数据库中用户会话与客户端会话的内存缓存
offlineSessions、offlineClientSessions 分布式 离线用户/客户端会话的内存缓存
loginFailures 分布式缓存名称 失败登录计数的特定兼容模式;当前默认存储位置见下文
actionTokens 分布式 异步确认动作令牌的元数据,例如忘记密码邮件流程

realms、users、authorization 的本地缓存默认各容纳 10,000 项。keys 默认最多 1,000 项,默认每小时过期,因此会周期性重新下载公钥。更大的缓存通常减少数据库往返,但也占用更多内存;应按数据库规模评估,不把默认值当成容量保证。

本地缓存之所以能用于多节点,是因为节点更新共享数据库后会通过 work 复制缓存发送失效消息,让其他节点清除旧值。work 中消息寿命很短,正常情况下不应持续累积成一个不断增长的数据集。

认证会话在用户开始登录时创建,认证完成或超时后销毁。分布式 authenticationSessions 让后续请求即使转到其他节点,也能继续访问认证过程的数据。缓存文仍保留“优先会话亲和”的建议,但编者核对发现当前反向代理指南已经更新:26.6 优化之后,粘性会话的收益不足以抵消复杂代理配置,推荐把负载均匀分配给各节点。本文依据 当前 Sticky sessions 说明,不再把旧亲和建议作为优化结论。

失败登录数据在当前默认配置中存入数据库。多站点/clusterless 使用外部 Infinispan,而内嵌 loginFailures 缓存只作为显式启用已弃用 login-failures:v1 的后备模式。切换存储模式后,旧位置可能留下不会自动清理的计数;日后切回时可能重新生效。原文提醒需处理这些旧记录,本篇不执行清理,也不建议未经核对删除安全相关数据。

持久会话、内存容量与关闭缓存的取舍

用户会话跟踪一个用户在一个或多个应用中的登录,客户端会话对应应用侧状态;离线会话是由离线令牌支撑的长寿命会话。默认持久化模式下,这四类会话保存在数据库,按需加载到内嵌缓存。缓存中的条目可以被其他节点访问,从而减少数据库查询。

四种会话缓存默认每节点最多 10,000 项,每条记录使用一个 owner。可以通过对应最大项数选项调整,比如:

--cache-embedded-offline-sessions-max-count=1000

原文的通用表达是 --cache-embedded-${CACHE_NAME}-max-count=,实际 CLI 名称使用连字符。下表列出与本篇有关的缓存上限选项,值类型均为整数:

缓存 CLI 环境变量
realms --cache-embedded-realms-max-count KC_CACHE_EMBEDDED_REALMS_MAX_COUNT
users --cache-embedded-users-max-count KC_CACHE_EMBEDDED_USERS_MAX_COUNT
authorization --cache-embedded-authorization-max-count KC_CACHE_EMBEDDED_AUTHORIZATION_MAX_COUNT
keys --cache-embedded-keys-max-count KC_CACHE_EMBEDDED_KEYS_MAX_COUNT
crl --cache-embedded-crl-max-count KC_CACHE_EMBEDDED_CRL_MAX_COUNT
sessions --cache-embedded-sessions-max-count KC_CACHE_EMBEDDED_SESSIONS_MAX_COUNT
clientSessions --cache-embedded-client-sessions-max-count KC_CACHE_EMBEDDED_CLIENT_SESSIONS_MAX_COUNT
offlineSessions --cache-embedded-offline-sessions-max-count KC_CACHE_EMBEDDED_OFFLINE_SESSIONS_MAX_COUNT
offlineClientSessions --cache-embedded-offline-client-sessions-max-count KC_CACHE_EMBEDDED_OFFLINE_CLIENT_SESSIONS_MAX_COUNT

actionTokens、authenticationSessions、loginFailures、work 不能按这套选项设置上限;原文该句把 actionTokens 拼成单数 actionToken,本文按其缓存总表统一名称。已弃用的 volatile 会话模式也不支持为 sessions/clientSessions 设置最大项数。

只在持久会话启用时,可用下面的 SPI 选项关闭会话内存缓存:

spi-user-sessions--infinispan--use-caches=false

这样可减少节点内存、节点间同步流量以及慢节点对请求的影响,但每次会话读取都转向数据库,尤其可能增加令牌内省和 token exchange 的数据库连接与 CPU 压力。原文预期数据库自身缓存可避免额外 IOPS;这是其设计说明,不是本文的基准测试结果,实际负载仍需测量。

从 26.8 起,只在内存保存普通用户会话的 volatile 模式已经弃用。原文建议移除 --features-disabled=persistent-user-sessions,回到默认持久化模式;旧 volatile 模式在所有节点重启后会丢失全部普通用户会话,活跃会话增多也会持续增加内存需求。本篇保持默认持久会话,不引入该旧分支。

使用受支持选项,避免把 XML 覆盖当作常规调优

Keycloak 会按预期配置创建所需缓存。虽然技术上可以修改 conf/cache-ispn.xml,或通过 --cache-config-file=my-cache-file.xml 选取自定义文件(可用绝对路径或相对 conf/ 的路径),原文明确指出:覆盖默认缓存配置的 XML 做法不受支持,只适合默认配置已证明有问题的高级场景。受支持的默认缓存修改方式是 cache-... 选项。

--cache-config-mutate=true 能抑制检测到默认配置被修改时的警告,但“警告消失”不等于方案获得支持。本文不提供 XML 覆盖步骤。需要查看真正生效的配置时,可临时增加这个日志分类:

--log-level=info,org.keycloak.connections.infinispan.DefaultInfinispanConnectionProviderFactory:debug

调试日志应在受控环境收集,避免长期保留不必要的详细配置日志。本次仅阅读原文,没有生成或读取任何真实集群日志。

默认节点发现与集群标识

jdbc-ping 通过 JGroups JDBC_PING2 在数据库中维护节点发现信息,数据通道则是 TCP。启用分布式缓存时它就是默认值,与 26.x 默认行为向后兼容;无需为本篇另行选择旧的 DNS 或组播栈。

源页还列出 kubernetes、jdbc-ping-udp、tcp、udp、ec2、azure、google,但这些值均已弃用。旧 kubernetes 栈使用 DNS_PING 并需要无头服务 FQDN;tcp/udp 旧栈依赖组播,旧文档还列有 239.6.7.8 与 46655 的默认组播地址和端口。这些不是本篇 jdbc-ping/TCP 主线需要开放的组播配置。

默认集群名是 ISPN,同一部署节点应使用相同集群名。默认发现使用共享数据库,因此无意中共享数据库、又使用同名集群的两个部署可能合并。不过,不能简单把它们改成不同 --cache-embedded-cluster-name 就算完成隔离:原文警告,不同集群名之间的缓存失效不会自动传播,普通模式会出现陈旧缓存。不同名称的多集群方案应与 stateless 功能一起设计,超出本文范围。

节点名可以独立设置,例如 --cache-embedded-node-name=node-1,对应环境变量 KC_CACHE_EMBEDDED_NODE_NAME。默认每次启动生成随机名;稳定节点名更便于关联重启前后的日志与指标。它不会代替数据库、传输地址或成员健康检查。

默认 mTLS 的证书与轮换

TCP 缓存传输默认启用 TLS,不需要另改 XML 或增加启用参数。Keycloak 自动生成 RSA 2048 位自签名证书,使用 TLS 1.3 保护节点通信;密钥和证书保存在数据库,让所有节点可取得它们。默认有效期 60 天,运行中每 30 天轮换一次,可通过 --cache-embedded-mtls-rotation-interval-days 调整轮换间隔。

--cache-embedded-mtls-enabled 默认是 true,对应环境变量为 KC_CACHE_EMBEDDED_MTLS_ENABLED。这保护的是集群传输,不是浏览器到 Keycloak 的 HTTP 接口,也不代替网络访问控制。标准部署应保留默认密钥管理;源页同时提供 keystore/truststore 的 file/password 参数,但本文不手工配置或展示任何密钥和密码。

UDP/TCP_NIO2、自定义证书和 Istio 等服务网格有各自加密配置要求。原文提到服务网格拦截可能出现 JGRP000006: failed accepting connection from peer SSLSocket,原因之一是对端呈现了错误证书。不能为消除错误就直接关闭 mTLS;本篇不提供网格 PERMISSIVE 或绕过步骤,也不把远程 Infinispan 的 cache-remote-tls-enabled 与内嵌集群 mTLS 混为一谈。

两个必须核对的 TCP 端口

默认端口 用途 配置
7800 节点间单播缓存数据传输 cache-embedded-network-bind-port / jgroups.bind.port
57800 FD_SOCK2 通过 socket 突然关闭等事件检测节点故障 jgroups.fd.port-offset,默认在绑定端口上加 50000

如果改了 7800,也要重新计算故障检测端口,不要只放行数据通道。没有专用选项的 JGroups 属性,可通过 JAVA_OPTS_APPEND 或命令行中的 -D<property>=<value> 传递。

编者说明:这些端口应在可信集群成员之间互通,不应因为“需要开端口”就暴露到公网。管理和指标端口也与缓存端口不同;当前反向代理指南指出 9000 用于管理/健康/指标,不应作为普通公共反代端口。

绑定地址与跨网络地址通告

传输端口必须绑定到其他所有节点都能访问的接口。默认选择 SITE_LOCAL 地址,例如 192.168.0.0/16 或 10.0.0.0/8 内的地址。多网卡主机上,私有地址并不一定就是正确的集群网卡;必要时用 cache-embedded-network-bind-address=<IP> 明确指定。

值 含义
GLOBAL 优先全局地址,不可用时回退 SITE_LOCAL
SITE_LOCAL 选择站点本地地址,默认值
LINK_LOCAL 169.254.1.0 至 169.254.254.255 的链路本地地址
NON_LOOPBACK 任意非回环地址
LOOPBACK 回环地址,例如 127.0.0.1
match-interface:<regex> 按接口名匹配,例如 match-interface:tun0
match-address:<regex> 按地址匹配,例如文档中的 match-address:192.168.*
match-host:<regex> 按主机名匹配,例如 match-host:linux.*

纯 IPv6 且让 Keycloak 自动选择绑定地址时,原文给出的 JVM 设置为:

export JAVA_OPTS_APPEND="-Djava.net.preferIPv4Stack=false -Djava.net.preferIPv6Addresses=true"

它会为该 shell 设置变量;如果已有其他 JVM 参数,应合并评估,避免不小心替换原值。本文没有实际修改任何环境变量。

若实例位于容器或不同网络,其他节点不能直接访问其本地 IP,需要由部署环境提供适当的转发路径。配置 cache-embedded-network-external-address 和 cache-embedded-network-external-port,让节点通告其他成员真正可达的地址与端口;仅在其不同于 bind 地址/端口时设置。写了通告值并不会自动创建网络转发规则,也不会自动解决防火墙或故障检测链路。

让副本分布认识故障域

Infinispan 可按拓扑分散数据副本。例如某缓存配置了 num_owners=2,会尽可能把两份数据放在不同节点或故障域。默认已持久化的用户/客户端会话有数据库保障,其他分布式缓存仍会受这些分布策略影响。

原文提供 site、rack、machine 三层标识。本文不展开多站点部署,但保留它们的用途:site 区分数据中心,rack 区分机架,machine 区分承载多个容器/虚拟机的物理机。同一故障域应一致,不同故障域的值应不同。对应选项是 spi-cache-embedded--default--site-name、--rack-name、--machine-name(后两项沿用相同 SPI 前缀)。例如:

--spi-cache-embedded--default--rack-name=rack-1
--spi-cache-embedded--default--machine-name=machine-1

Keycloak Operator 会依据 Kubernetes 节点自动设置 machine 名称。原文还建议通过反亲和或 topology spread constraints 减少多个 Pod 落在同一节点的情况。这些说明帮助理解故障域,不意味着本文已经配置了多副本数量、跨机架调度或跨站点高可用。

用三个视角确认集群真正形成

部署之后,需要把“预期节点数”与实际成员列表对照。官方提供以下三个观察入口。

  1. 管理界面:进入通常形如 https://<your-host>/admin/master/console/#/master/providers 的页面,在 Provider Info 找到 connectionsInfinispan,展开 Show more,检查集群状态和各缓存健康信息。管理界面应按环境限制访问。
  2. 日志:每当节点加入或离开,Infinispan 会记录新的 cluster view。搜索 ISPN000094,核对成员列表是否齐全。
  3. 指标:启用指标后,从 Prometheus 端点读取 vendor_cluster_size,确认值等于当前期望运行的实例数。

原文给出下面的两节点日志:

ISPN000094: Received new cluster view for channel ISPN: [node1-26186|1] (2) [node1-26186, node2-37007]

这里集群名为 ISPN,成员为 node1-26186 和 node2-37007,(2) 表示两名成员。这是官方示例,不是本次生成的日志。若预期三个实例,看到两名成员就仍需排查发现数据库、绑定/通告地址、两个 TCP 端口和 TLS 连接,不能仅凭页面可登录就认定高可用完整。

缓存指标与本篇的完成边界

启用 Keycloak 指标时,会自动暴露缓存指标。若需要延迟分布直方图,原文使用:

bin/kc.[sh|bat] start --metrics-enabled=true --cache-metrics-histograms-enabled=true

cache-metrics-histograms-enabled 默认 false,只在指标已启用时有效。采集直方图本身可能有性能代价,不宜在已经饱和的系统上未经评估直接启用。有关指标端点和集群指标的后续配置,应按官方 指标指南 继续核对。

本篇已核对缓存指南全文、版本和反代/数据库的相关边界,保留从启用到成员验证的完整主线。未安装 Keycloak、建立数据库、修改安全组、启动节点或采集指标;默认 mTLS 的介绍不是安全审计通过声明,图示也不是测试截图。原文另述远程 Infinispan、多站点、stateless、旧传输栈和自定义 XML 分支,本文按既定范围只说明它们的边界,不声称已完成这些部署。

来源归属:Keycloak Team;原页页脚标示 © Keycloak Authors 2026 / © 2026 The Linux Foundation,All rights reserved。保留来源与版本,不以项目软件开源许可替代文章许可。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容