2023 年 12 月 18 日,作者:Alexander Schwartz, Kamesh Akella
对于客户身份和访问管理 (CIAM) 系统而言,高可用性至关重要,因为它是所有客户登录系统的单点。对于 Keycloak 23,有一个新的和更新的高可用性指南,描述了多站点设置。其中包含针对云基础设施的详细说明和蓝图,这些都已记录、测试并准备好试用。
继续阅读以了解新内容,并深入了解此设置是如何评估、测试和改进的幕后情况。最后,我们将展望何时不再是预览功能。
Keycloak 多站点设置的最新更新标志着一个重要的里程碑。Keycloak 23 包含一个关于在多站点配置中设置 Keycloak 的指导性指南,其中包括云设置的蓝图。
本文档的高级主题包括
在我们发布上述指南之前,我们致力于开发工具,使我们能够进行实验并获得性能、可扩展性和混沌测试我们解决方案的可重现结果。
借助这些工具,我们首先测试了单站点设置,并在其工作良好后,也测试了多站点设置。
所有这些工具都是开源的,我们邀请您查看它们以向我们提供反馈,并在您的环境中使用它们来运行您自己的性能基准测试和回归测试
将其安装到测试环境中的 Keycloak 服务器中,并创建运行性能基准测试所需的尽可能多的用户、客户端、组等。Keycloak 在其内部缓存中缓存了大量信息,数据库也是如此,因此只有当您的数据库中有适量的数据时,您才能发现一些问题。
这包含可用于身份验证流程和 Keycloak 管理 REST 端点的现成场景。如果它还不符合您的需求,请将其用作库,以基于现有和自定义步骤创建您自己的 Gatling 场景。这些测试以 JAR 和 shell 脚本包装器的形式部署,因此您只需在负载运行器上安装 Java 即可开始使用。
使用这些 Ansible playbook 启动一组 EC2 实例,以驱动针对 Keycloak 测试安装的负载,并聚合结果。
基于 Red Hat OpenShift Service on AWS (ROSA),使用脚本配置一个预配置了监控、日志记录和有用的 Operator 的实例,准备部署 Keycloak。
设置不同变体的 Aurora,区域性或全局性,并将其连接到 ROSA 环境。
这会部署 Keycloak 以及额外的监控和调试工具,以便我们可以根据需要查看指标、日志和跟踪
为活动-被动设置设置 Route 53,以将负载分配到不同 OpenShift 集群中的两个 Keycloak 部署
每个工作日,我们都使用 GitHub Actions 从头开始创建一个新的多可用区设置、性能测试套件并记录结果。这样,我们就可以在功能和性能回归发生时及时捕获。
感谢社区中已经试用过这些工具、发现错误并提交改进意见的每个人!
当使用上面列出的工具时,我们能够重现 Keycloak 需要改进的几种情况。以下是 Keycloak 23 中适用于单站点和多站点设置的一些改进
在高负载下运行 Keycloak 时,请求可能会在 Keycloak 实例中排队。排队的请求越多,回复请求所需的时间就越长。在以前的版本中,对活动性探针 (/health/live
) 的请求也会排队,并且探针最终超时,然后 Kubernetes 重新启动 Pod。在最新版本的 Keycloak 中,探针已重新实现为非阻塞,因此它不会排队,因此不会超时,并且 Pod 在高负载下不会重新启动。
当请求如上所述排队时,调用者将无法及时收到响应,并且 Pod 最终可能会耗尽内存或网络连接等资源。推荐的方法是在实例无法及时处理请求时尽早丢弃请求,这称为负载削减。Keycloak 23 现在支持新选项 http-max-queued-requests
,它可以限制并发阻塞请求的数量。当超出此数量时,Keycloak 会立即返回响应 503 服务器不可用
。这有两个好处:调用者收到立即响应并可以在以后重试,并且服务器端立即释放资源。
当新的 Keycloak 实例启动或重新启动时,其缓存是空的。如果在 Keycloak 节点上对同一领域或同一客户端并行到达高负载请求,则以前版本的 Keycloak 会在每个并行请求中从数据库加载数据。这导致数据库连接使用量激增和初始响应延迟。当缓存或缓存中的领域条目被逐出时(例如,因为它被修改了),也会发生同样的情况。最新版本的 Keycloak 防止了这种情况,因此每个 Keycloak 实例将从数据库中获取一次数据,然后所有其他并行请求都将使用此数据,而无需再次查询数据库(请参阅 #21521 和 #22988, #24202)。
在集群中运行的 Keycloak 实例越多,并行处理的请求越多,JGroups 线程池上的负载就越高。JGroups 线程池确保 Keycloak 嵌入式 Infinispan 的平稳通信,如果其容量超出,可能会导致内部 Infinispan 通信超时。高可用性文档现在包含关于如何设置 Quarkus 线程池以不超过 JGroup 线程池的文档。
嵌入式 Infinispan 提供了改进的指标,使您可以监控集群。Keycloak 的指标端点公开的指标现在仅包含当前节点的 Infinispan 指标,因此如果另一个 Pod 当前正在启动或关闭,它们将不会阻塞 (ISPN-15042 和 ISPN-15072)。这样,您可以在关键时刻更好地了解您的集群。指标现在可以将缓存名称作为标签公开,因此可以通过在 Infinispan XML 配置中添加 <metrics names-as-tags="true" />
来更简单地在仪表板中绘制它们。站点之间的延迟提供了额外的指标。
我们彻底测试了 Infinispan 及其通信层 JGroups,并且我们能够修复状态传输停滞 (ISPN-14982) 或初始状态传输失败的情况。即使在负载均衡器具有多个 IP 地址的情况下,多站点设置中使用的 Gossip 路由器现在也可以工作 (JGRP-2722, JGRP-2721, infinispan-operator#1857, 和 infinispan-operator#1856)。
作为我们所做测试的一部分,我们优化了 Keycloak,这些优化已内置到 Keycloak 中。它们无需额外配置即可使用,JGroup 线程池配置除外。虽然 Kubernetes 上 Keycloak 的配置可能与生产环境非常接近,但我们预计每个组织中的数据库、网络、负载均衡器和安全强化都会有所不同,因此您需要根据自己的需求进行调整。
这就是为什么我们选择以文本形式记录蓝图,以便您可以了解我们所做的选择以及为什么在一个设置中配置了不同的方面,而其他方面则处于默认设置。
我们在 Keycloak Benchmark 项目中用于自动化设置的脚本侧重于高可用性,并将此与易于从工程角度调试和分析的配置混合在一起。生产就绪的设置不会具有该功能,因此我们不建议按原样使用脚本。尽管如此,它们仍然可以作为您自己的自动化的起点。
目前,我们正在运行活动/被动设置的最终测试,并致力于自动化更多测试。我们还在这个关于多站点设置的 GitHub 讨论中寻求社区的反馈:您喜欢在这里看到的内容吗?是否缺少什么?您的反馈至关重要!
一旦我们的测试完成,并且我们收到社区的反馈,我们计划使其成为完全支持的功能。对于社区来说,这是一个与此设置互动、在您的环境中试用并分享您的发现的绝佳机会。让我们一起构建一个更强大、更具弹性的 Keycloak!