本指南介绍了如何部署 AWS 全球加速器实例,以处理多个可用区 Keycloak 部署的 Keycloak 客户端连接故障转移。
为了确保用户请求路由到每个 Keycloak 站点,我们需要使用负载均衡器。为了防止客户端侧 DNS 缓存出现问题,实现应该使用在将客户端路由到两个可用区时保持不变的静态 IP 地址。
在本指南中,我们介绍了如何通过 AWS 全球加速器负载均衡器路由所有 Keycloak 客户端请求。如果 Keycloak 站点发生故障,加速器将确保所有客户端请求都被路由到剩余的健康站点。如果两个站点都被标记为不健康,那么加速器将“故障转移”并将请求转发到随机选择的站点。
在两个 ROSA 集群上都创建了 AWS 网络负载均衡器 (NLB),以便将 Keycloak Pod 作为端点提供给 AWS 全球加速器实例。每个集群端点被分配一个权重为 128(最大权重 255 的一半),以确保当两个集群都处于健康状态时,加速器流量被均匀地路由到两个可用区。
基于 ROSA 的多 AZ Keycloak 部署
创建网络负载均衡器
在每个 Keycloak 集群上执行以下操作
登录 ROSA 集群
创建 Kubernetes 负载均衡器服务
cat <<EOF | kubectl apply -n $NAMESPACE -f - (1)
apiVersion: v1
kind: Service
metadata:
name: accelerator-loadbalancer
annotations:
service.beta.kubernetes.io/aws-load-balancer-additional-resource-tags: accelerator=${ACCELERATOR_NAME},site=${CLUSTER_NAME},namespace=${NAMESPACE} (2)
service.beta.kubernetes.io/aws-load-balancer-type: "nlb"
service.beta.kubernetes.io/aws-load-balancer-healthcheck-path: "/lb-check"
service.beta.kubernetes.io/aws-load-balancer-healthcheck-protocol: "https"
service.beta.kubernetes.io/aws-load-balancer-healthcheck-interval: "10" (3)
service.beta.kubernetes.io/aws-load-balancer-healthcheck-healthy-threshold: "3" (4)
service.beta.kubernetes.io/aws-load-balancer-healthcheck-unhealthy-threshold: "3" (5)
spec:
ports:
- name: https
port: 443
protocol: TCP
targetPort: 8443
selector:
app: keycloak
app.kubernetes.io/instance: keycloak
app.kubernetes.io/managed-by: keycloak-operator
sessionAffinity: None
type: LoadBalancer
EOF
1 | $NAMESPACE 应替换为 Keycloak 部署的命名空间 |
2 | 将额外的标签添加到 AWS 创建的资源中,以便我们稍后检索它们。ACCELERATOR_NAME 应该是后续步骤中创建的全局加速器的名称,CLUSTER_NAME 应该是当前站点的名称。 |
3 | 健康检查探测以秒为单位执行的频率 |
4 | NLB 被视为健康状态所需的健康检查次数 |
5 | NLB 被视为不健康状态所需的健康检查次数 |
记下 DNS 主机名,因为稍后将需要它
kubectl -n $NAMESPACE get svc accelerator-loadbalancer --template="{{range .status.loadBalancer.ingress}}{{.hostname}}{{end}}"
abab80a363ce8479ea9c4349d116bce2-6b65e8b4272fa4b5.elb.eu-west-1.amazonaws.com
创建全局加速器实例
aws globalaccelerator create-accelerator \
--name example-accelerator \ (1)
--ip-address-type DUAL_STACK \ (2)
--region us-west-2 (3)
1 | 要创建的加速器的名称,根据需要更新 |
2 | 可以是“DUAL_STACK”或“IPV4” |
3 | 所有 globalaccelerator 命令都必须使用区域“us-west-2” |
{
"Accelerator": {
"AcceleratorArn": "arn:aws:globalaccelerator::606671647913:accelerator/e35a94dd-391f-4e3e-9a3d-d5ad22a78c71", (1)
"Name": "example-accelerator",
"IpAddressType": "DUAL_STACK",
"Enabled": true,
"IpSets": [
{
"IpFamily": "IPv4",
"IpAddresses": [
"75.2.42.125",
"99.83.132.135"
],
"IpAddressFamily": "IPv4"
},
{
"IpFamily": "IPv6",
"IpAddresses": [
"2600:9000:a400:4092:88f3:82e2:e5b2:e686",
"2600:9000:a516:b4ef:157e:4cbd:7b48:20f1"
],
"IpAddressFamily": "IPv6"
}
],
"DnsName": "a099f799900e5b10d.awsglobalaccelerator.com", (2)
"Status": "IN_PROGRESS",
"CreatedTime": "2023-11-13T15:46:40+00:00",
"LastModifiedTime": "2023-11-13T15:46:42+00:00",
"DualStackDnsName": "ac86191ca5121e885.dualstack.awsglobalaccelerator.com" (3)
}
}
1 | 与创建的加速器实例关联的 ARN,这将在后续命令中使用 |
2 | IPv4 Keycloak 客户端应连接到的 DNS 名称 |
3 | IPv6 Keycloak 客户端应连接到的 DNS 名称 |
为加速器创建侦听器
aws globalaccelerator create-listener \
--accelerator-arn 'arn:aws:globalaccelerator::606671647913:accelerator/e35a94dd-391f-4e3e-9a3d-d5ad22a78c71' \
--port-ranges '[{"FromPort":443,"ToPort":443}]' \
--protocol TCP \
--region us-west-2
{
"Listener": {
"ListenerArn": "arn:aws:globalaccelerator::606671647913:accelerator/e35a94dd-391f-4e3e-9a3d-d5ad22a78c71/listener/1f396d40",
"PortRanges": [
{
"FromPort": 443,
"ToPort": 443
}
],
"Protocol": "TCP",
"ClientAffinity": "NONE"
}
}
为侦听器创建端点组
CLUSTER_1_ENDPOINT_ARN=$(aws elbv2 describe-load-balancers \
--query "LoadBalancers[?DNSName=='abab80a363ce8479ea9c4349d116bce2-6b65e8b4272fa4b5.elb.eu-west-1.amazonaws.com'].LoadBalancerArn" \ (1)
--region eu-west-1 \ (2)
--output text
)
CLUSTER_2_ENDPOINT_ARN=$(aws elbv2 describe-load-balancers \
--query "LoadBalancers[?DNSName=='a1c76566e3c334e4ab7b762d9f8dcbcf-985941f9c8d108d4.elb.eu-west-1.amazonaws.com'].LoadBalancerArn" \ (1)
--region eu-west-1 \ (2)
--output text
)
ENDPOINTS='[
{
"EndpointId": "'${CLUSTER_1_ENDPOINT_ARN}'",
"Weight": 128,
"ClientIPPreservationEnabled": false
},
{
"EndpointId": "'${CLUSTER_2_ENDPOINT_ARN}'",
"Weight": 128,
"ClientIPPreservationEnabled": false
}
]'
aws globalaccelerator create-endpoint-group \
--listener-arn 'arn:aws:globalaccelerator::606671647913:accelerator/e35a94dd-391f-4e3e-9a3d-d5ad22a78c71/listener/1f396d40' \ (2)
--traffic-dial-percentage 100 \
--endpoint-configurations ${ENDPOINTS} \
--endpoint-group-region eu-west-1 \ (3)
--region us-west-2
1 | 集群的 NLB 的 DNS 主机名 |
2 | 在上一步骤中创建的侦听器的 ARN |
3 | 这应该是托管集群的 AWS 区域 |
{
"EndpointGroup": {
"EndpointGroupArn": "arn:aws:globalaccelerator::606671647913:accelerator/e35a94dd-391f-4e3e-9a3d-d5ad22a78c71/listener/1f396d40/endpoint-group/2581af0dc700",
"EndpointGroupRegion": "eu-west-1",
"EndpointDescriptions": [
{
"EndpointId": "arn:aws:elasticloadbalancing:eu-west-1:606671647913:loadbalancer/net/abab80a363ce8479ea9c4349d116bce2/6b65e8b4272fa4b5",
"Weight": 128,
"HealthState": "HEALTHY",
"ClientIPPreservationEnabled": false
},
{
"EndpointId": "arn:aws:elasticloadbalancing:eu-west-1:606671647913:loadbalancer/net/a1c76566e3c334e4ab7b762d9f8dcbcf/985941f9c8d108d4",
"Weight": 128,
"HealthState": "HEALTHY",
"ClientIPPreservationEnabled": false
}
],
"TrafficDialPercentage": 100.0,
"HealthCheckPort": 443,
"HealthCheckProtocol": "TCP",
"HealthCheckPath": "undefined",
"HealthCheckIntervalSeconds": 30,
"ThresholdCount": 3
}
}
可选:配置您的自定义域
如果您使用的是自定义域,请通过在您的自定义域中配置别名或 CNAME 将您的自定义域指向 AWS 全球负载均衡器。
创建或更新 Keycloak 部署
在每个 Keycloak 集群上执行以下操作
登录 ROSA 集群
确保 Keycloak CR 具有以下配置
apiVersion: k8s.keycloak.org/v2alpha1
kind: Keycloak
metadata:
name: keycloak
spec:
hostname:
hostname: $HOSTNAME (1)
ingress:
enabled: false (2)
1 | 客户端用来连接 Keycloak 的主机名 |
2 | 禁用默认入口,因为所有 Keycloak 访问都应通过预配的 NLB 进行 |
为了确保请求转发按预期工作,Keycloak CR 需要指定客户端将通过其访问 Keycloak 实例的主机名。这可以是与全局加速器关联的 DualStackDnsName
或 DnsName
主机名。如果您使用的是自定义域并将您的自定义域指向 AWS 全球负载均衡器,请在此处使用您的自定义域。
要验证全局加速器是否已正确配置以连接到集群,请导航到上面配置的主机名,您应该会看到 Keycloak 管理控制台。