此设置在两个具有低延迟网络连接的站点中部署了两个同步复制的 Infinispan 集群。这种场景的示例可能是同一个 AWS 区域中的两个可用区。
为了简化说明,以下图表已删除 Keycloak、负载均衡器和数据库。
正在运行的 OpenShift 或 Kubernetes 集群
配置访问 Infinispan 集群的凭据。
Keycloak 需要此凭据才能对 Infinispan 集群进行身份验证。以下 identities.yaml
文件设置具有管理员权限的用户名和密码
credentials:
- username: developer
password: strong-password
roles:
- admin
identities.yaml
可以作为以下之一设置在秘密中
作为 Kubernetes 资源
apiVersion: v1
kind: Secret
type: Opaque
metadata:
name: connect-secret
namespace: keycloak
data:
identities.yaml: Y3JlZGVudGlhbHM6CiAgLSB1c2VybmFtZTogZGV2ZWxvcGVyCiAgICBwYXNzd29yZDogc3Ryb25nLXBhc3N3b3JkCiAgICByb2xlczoKICAgICAgLSBhZG1pbgo= (1)
1 | 之前示例中 identities.yaml 的 base64 编码。 |
使用 CLI
kubectl create secret generic connect-secret --from-file=identities.yaml
有关更多详细信息,请查看 配置身份验证 文档。
这些命令必须在两个 OpenShift 集群上执行。
创建一个服务帐户。
需要服务帐户才能在集群之间建立连接。Infinispan Operator 使用它来检查来自远程站点的网络配置,并相应地配置本地 Infinispan 集群。
有关更多详细信息,请参阅 管理跨站点连接 文档。
创建以下类型的 service-account-token
秘密。相同的 YAML 文件可以在两个 OpenShift 集群中使用。
apiVersion: v1
kind: Secret
metadata:
name: ispn-xsite-sa-token (1)
annotations:
kubernetes.io/service-account.name: "xsite-sa" (2)
type: kubernetes.io/service-account-token
1 | 秘密名称。 |
2 | 服务帐户名称。 |
在两个 OpenShift 集群中创建服务帐户并生成访问令牌。
Site-A
中创建服务帐户kubectl create sa -n keycloak xsite-sa
oc policy add-role-to-user view -n keycloak -z xsite-sa
kubectl create -f xsite-sa-secret-token.yaml
kubectl get secrets ispn-xsite-sa-token -o jsonpath="{.data.token}" | base64 -d > Site-A-token.txt
Site-B
中创建服务帐户kubectl create sa -n keycloak xsite-sa
oc policy add-role-to-user view -n keycloak -z xsite-sa
kubectl create -f xsite-sa-secret-token.yaml
kubectl get secrets ispn-xsite-sa-token -o jsonpath="{.data.token}" | base64 -d > Site-B-token.txt
下一步是将 Site-A
中的令牌部署到 Site-B
,反之亦然
Site-B
的令牌部署到 Site-A
kubectl create secret generic -n keycloak xsite-token-secret \
--from-literal=token="$(cat Site-B-token.txt)"
Site-A
的令牌部署到 Site-B
kubectl create secret generic -n keycloak xsite-token-secret \
--from-literal=token="$(cat Site-A-token.txt)"
创建 TLS 秘密
在本指南中,Infinispan 使用 OpenShift 路由进行跨站点通信。它使用 TLS 的 SNI 扩展将流量定向到正确的 Pod。为了实现这一点,JGroups 使用 TLS 套接字,这些套接字需要具有正确证书的密钥库和信任库。
有关更多信息,请参阅 保护跨站点连接 文档或此 Red Hat 开发人员指南。
将密钥库和信任库上传到 OpenShift 秘密中。秘密包含文件内容、访问它的密码以及存储的类型。创建证书和存储的说明超出了本指南的范围。
要将密钥库作为秘密上传,请使用以下命令
kubectl -n keycloak create secret generic xsite-keystore-secret \
--from-file=keystore.p12="./certs/keystore.p12" \ (1)
--from-literal=password=secret \ (2)
--from-literal=type=pkcs12 (3)
1 | 密钥库的文件名和路径。 |
2 | 访问密钥库的密码。 |
3 | 密钥库类型。 |
要将信任库作为秘密上传,请使用以下命令
kubectl -n keycloak create secret generic xsite-truststore-secret \
--from-file=truststore.p12="./certs/truststore.p12" \ (1)
--from-literal=password=caSecret \ (2)
--from-literal=type=pkcs12 (3)
1 | 信任库的文件名和路径。 |
2 | 访问信任库的密码。 |
3 | 信任库类型。 |
密钥库和信任库必须上传到两个 OpenShift 集群中。 |
创建具有跨站点功能的 Infinispan 集群
有关如何创建和配置支持跨站点的 Infinispan 集群(包括前面的步骤)的全部信息,请参阅 设置跨站点 文档。
本指南提供了一个基本示例,使用上一步中的命令创建的凭据、令牌和 TLS 密钥库/信任库。
Site-A
的 Infinispan
CRapiVersion: infinispan.org/v1
kind: Infinispan
metadata:
name: infinispan (1)
namespace: keycloak
annotations:
infinispan.org/monitoring: 'true' (2)
spec:
replicas: 3
jmx:
enabled: true
security:
endpointSecretName: connect-secret (3)
service:
type: DataGrid
sites:
local:
name: site-a (4)
expose:
type: Route (5)
maxRelayNodes: 128
encryption:
transportKeyStore:
secretName: xsite-keystore-secret (6)
alias: xsite (7)
filename: keystore.p12 (8)
routerKeyStore:
secretName: xsite-keystore-secret (6)
alias: xsite (7)
filename: keystore.p12 (8)
trustStore:
secretName: xsite-truststore-secret (9)
filename: truststore.p12 (10)
locations:
- name: site-b (11)
clusterName: infinispan
namespace: keycloak (12)
url: openshift://api.site-b (13)
secretName: xsite-token-secret (14)
1 | 集群名称 |
2 | 允许 Prometheus 监控集群。 |
3 | 如果使用自定义凭据,请在此配置秘密名称。 |
4 | 本地站点的名称,在本例中为 Site-A 。 |
5 | 使用 OpenShift 路由公开跨站点连接。 |
6 | 密钥库所在的秘密名称,如前一步所定义。 |
7 | 密钥库中证书的别名。 |
8 | 密钥库的秘密密钥(文件名),如前一步所定义。 |
9 | 信任库所在的秘密名称,如前一步所定义。 |
10 | 信任库的密钥(文件名),如前一步所定义。 |
11 | 远程站点的名称,在本例中为 Site-B 。 |
12 | 远程站点上 Infinispan 集群的命名空间。 |
13 | 远程站点的 OpenShift API URL。 |
14 | 包含访问令牌以对远程站点进行身份验证的秘密。 |
对于 Site-B
,Infinispan
CR 与上面类似。请注意第 4、11 和 13 点的差异。
Site-B
的 Infinispan
CRapiVersion: infinispan.org/v1
kind: Infinispan
metadata:
name: infinispan (1)
namespace: keycloak
annotations:
infinispan.org/monitoring: 'true' (2)
spec:
replicas: 3
jmx:
enabled: true
security:
endpointSecretName: connect-secret (3)
service:
type: DataGrid
sites:
local:
name: site-b (4)
expose:
type: Route (5)
maxRelayNodes: 128
encryption:
transportKeyStore:
secretName: xsite-keystore-secret (6)
alias: xsite (7)
filename: keystore.p12 (8)
routerKeyStore:
secretName: xsite-keystore-secret (6)
alias: xsite (7)
filename: keystore.p12 (8)
trustStore:
secretName: xsite-truststore-secret (9)
filename: truststore.p12 (10)
locations:
- name: site-a (11)
clusterName: infinispan
namespace: keycloak (12)
url: openshift://api.site-a (13)
secretName: xsite-token-secret (14)
为 Keycloak 创建缓存。
Keycloak 需要以下缓存存在:actionTokens
、authenticationSessions
、loginFailures
和 work
。
Infinispan 的 缓存 CR 允许在 Infinispan 集群中部署缓存。跨站点需要按缓存启用,如 跨站点文档 中所述。该文档包含有关本指南使用的选项的更多详细信息。以下示例显示了 Site-A
的 Cache
CR。
在 Site-A
中为上面提到的每个缓存创建一个 Cache
CR,其内容如下。以下是对 authenticationSessions
缓存的示例
apiVersion: infinispan.org/v2alpha1 kind: Cache metadata: name: authenticationsessions namespace: keycloak spec: clusterName: infinispan name: authenticationSessions template: |- distributedCache: mode: "SYNC" owners: "2" statistics: "true" remoteTimeout: "5000" encoding: media-type: "application/x-protostream" locking: acquireTimeout: "4000" transaction: mode: "NON_XA" (1) locking: "PESSIMISTIC" (2) stateTransfer: chunkSize: "16" backups: site-b: (3) backup: strategy: "SYNC" (4) timeout: "4500" (5) failurePolicy: "FAIL" (6) stateTransfer: chunkSize: "16"
1 | 事务模式。 |
2 | 事务使用的锁定模式。 |
3 | 远程站点名称。 |
4 | 跨站点通信策略,在本例中为 SYNC 。 |
5 | 跨站点复制超时。 |
6 | 跨站点复制失败策略。 |
以上示例是实现最佳数据一致性的推荐配置。
背景信息
在活动-活动设置中可能会发生死锁,因为条目在两个站点中同时修改。
transaction.mode: NON_XA
确保如果发生这种情况,事务将回滚,从而保持数据一致性。在这种情况下,需要设置 backup.failurePolicy: FAIL
。它将抛出一个错误,允许事务安全地回滚。发生这种情况时,Keycloak 将尝试重试。
transaction.locking: PESSIMISTIC
是唯一支持的锁定模式;OPTIMISTIC
不推荐使用,因为它会产生网络成本。相同的设置还可以防止一个站点更新而另一个站点无法访问。
backup.strategy: SYNC
确保在 Keycloak 请求完成时,数据在另一个站点中可见并存储。
可以在死锁场景中减少 locking.acquireTimeout 以快速失败。backup.timeout 必须始终大于 locking.acquireTimeout 。 |
对于 Site-B
,Cache
CR 类似,除了上面图表中第 3 点所概述的 backups.<name>
。
Site-B
中的 authenticationSessions
Cache
CRapiVersion: infinispan.org/v2alpha1
kind: Cache
metadata:
name: authenticationsessions
namespace: keycloak
spec:
clusterName: infinispan
name: authenticationSessions
template: |-
distributedCache:
mode: "SYNC"
owners: "2"
statistics: "true"
remoteTimeout: "5000"
encoding:
media-type: "application/x-protostream"
locking:
acquireTimeout: "4000"
transaction:
mode: "NON_XA" (1)
locking: "PESSIMISTIC" (2)
stateTransfer:
chunkSize: "16"
backups:
site-a: (3)
backup:
strategy: "SYNC" (4)
timeout: "4500" (5)
failurePolicy: "FAIL" (6)
stateTransfer:
chunkSize: "16"
确认 Infinispan 集群已形成,并且在 OpenShift 集群之间建立了跨站点连接。
kubectl wait --for condition=WellFormed --timeout=300s infinispans.infinispan.org -n keycloak infinispan
kubectl wait --for condition=CrossSiteViewFormed --timeout=300s infinispans.infinispan.org -n keycloak infinispan
现在 Infinispan 服务器正在运行,以下是在 使用 Keycloak Operator 部署高可用 Keycloak 指南中连接到 Keycloak 所需的相关 Keycloak CR 更改。
创建一个包含连接到外部 Infinispan 部署的用户名和密码的秘密
apiVersion: v1
kind: Secret
metadata:
name: remote-store-secret
namespace: keycloak
type: Opaque
data:
username: ZGV2ZWxvcGVy # base64 encoding for 'developer'
password: c2VjdXJlX3Bhc3N3b3Jk # base64 encoding for 'secure_password'
使用如下所示的 additionalOptions
扩展 Keycloak 自定义资源。
以下 CR 中省略了所有内存、资源和数据库配置,因为它们已经在 使用 Keycloak Operator 部署高可用 Keycloak 指南中进行了描述。管理员应保持这些配置不变。 |
apiVersion: k8s.keycloak.org/v2alpha1
kind: Keycloak
metadata:
labels:
app: keycloak
name: keycloak
namespace: keycloak
spec:
additionalOptions:
- name: cache-remote-host (1)
value: "infinispan.keycloak.svc"
- name: cache-remote-port (2)
value: "11222"
- name: cache-remote-username (3)
secret:
name: remote-store-secret
key: username
- name: cache-remote-password (4)
secret:
name: remote-store-secret
key: password
- name: spi-connections-infinispan-quarkus-site-name (5)
value: keycloak
1 | 远程 Infinispan 集群的主机名。 |
2 | 远程 Infinispan 集群的端口。这是可选的,默认值为 11222 。 |
3 | 包含 Infinispan 用户名凭据的秘密 name 和 key 。 |
4 | 包含 Infinispan 密码凭据的秘密 name 和 key 。 |
5 | spi-connections-infinispan-quarkus-site-name 是一个任意的 Infinispan 站点名称,Keycloak 在使用远程存储时需要使用它来部署其 Infinispan 缓存。此站点名称仅与 Infinispan 缓存相关,不需要与外部 Infinispan 部署中的任何值匹配。如果您在跨数据中心的设置中为 Keycloak 使用多个站点,例如 使用 Infinispan Operator 部署高可用 Infinispan,则每个站点中的站点名称必须不同。 |
这使用由 TLS 1.3 保护的 TCP 连接将 Keycloak 连接到 Infinispan。它使用 Keycloak 的信任库来验证 Infinispan 的服务器证书。由于 Keycloak 使用其 Operator 在 OpenShift 上部署(如以下先决条件中所列),因此 Operator 已将 service-ca.crt
添加到信任库,该信任库用于签署 Infinispan 的服务器证书。在其他环境中,请将必要的证书添加到 Keycloak 的信任库。
在 Aurora AWS 数据库和 Infinispan 部署并运行后,请使用 使用 Keycloak Operator 部署高可用 Keycloak 指南中的步骤部署 Keycloak 并将其连接到之前创建的所有构建块。
值 | |
---|---|
|
|
仅在设置远程主机时可用 |
|
仅在设置远程主机时可用 |
(默认) |
仅在设置远程主机时可用 |
|
仅在设置远程主机时可用 |