Deploy Keycloak for HA with the Keycloak Operator

Building block for a Keycloak deployment

This guide describes advanced Keycloak configurations for Kubernetes which are load tested and will recover from single Pod failures.

These instructions are intended for use with the setup described in the Concepts for active-passive deployments guide. Use it together with the other building blocks outlined in the Building blocks active-passive deployments guide.

Prerequisites

  • OpenShift or Kubernetes cluster running.

  • Understanding of a Basic Keycloak deployment of Keycloak with the Keycloak Operator.

Procedure

  1. Determine the sizing of the deployment using the Concepts for sizing CPU and memory resources guide.

  2. Install the Keycloak Operator as described in the Keycloak Operator Installation guide.

  3. Deploy Aurora AWS as described in the Deploy AWS Aurora in multiple availability zones guide.

  4. Build a custom Keycloak image which is prepared for usage with the Amazon Aurora PostgreSQL database.

  5. Deploy the Keycloak CR with the following values with the resource requests and limits calculated in the first step:

    apiVersion: k8s.keycloak.org/v2alpha1
    kind: Keycloak
    metadata:
      labels:
        app: keycloak
      name: keycloak
      namespace: keycloak
    spec:
      hostname:
        hostname: <KEYCLOAK_URL_HERE>
      resources:
        requests:
          cpu: "2"
          memory: "1250M"
        limits:
          cpu: "6"
          memory: "2250M"
      db:
        vendor: postgres
        url: jdbc:aws-wrapper:postgresql://<AWS_AURORA_URL_HERE>:5432/keycloak
        poolMinSize: 30 (1)
        poolInitialSize: 30
        poolMaxSize: 30
        usernameSecret:
          name: keycloak-db-secret
          key: username
        passwordSecret:
          name: keycloak-db-secret
          key: password
      image: <KEYCLOAK_IMAGE_HERE> (2)
      startOptimized: false (2)
      features:
        enabled:
          - multi-site (3)
      transaction:
        xaEnabled: false (4)
      additionalOptions:
        - name: http-max-queued-requests
          value: "1000"
        - name: log-console-output
          value: json
        - name: metrics-enabled (5)
          value: 'true'
        - name: http-pool-max-threads (6)
          value: "66"
        - name: db-driver
          value: software.amazon.jdbc.Driver
      http:
        tlsSecret: keycloak-tls-secret
      instances: 3
    1 The database connection pool initial, max and min size should be identical to allow statement caching for the database. Adjust this number to meet the needs of your system. As most requests will not touch the database due to the Keycloak embedded cache, this change can server several hundreds of requests per second. See the Concepts for database connection pools guide for details.
    2 Specify the URL to your custom Keycloak image. If your image is optimized, set the startOptimized flag to true.
    3 Enable additional features for multi-site support like the loadbalancer probe /lb-check.
    4 XA transactions are not supported by the Amazon Web Services JDBC Driver.
    5 To be able to analyze the system under load, enable the metrics endpoint. The disadvantage of the setting is that the metrics will be available at the external Keycloak endpoint, so you must add a filter so that the endpoint is not available from the outside. Use a reverse proxy in front of Keycloak to filter out those URLs.
    6 The default setting for the internal JGroup thread pools is 200 threads maximum. The number of all Keycloak threads in the StatefulSet should not exceed the number of JGroup threads to avoid a JGroup thread pool exhaustion which could stall Keycloak request processing. You might consider limiting the number of Keycloak threads further because multiple concurrent threads will lead to throttling by Kubernetes once the requested CPU limit is reached. See the Concepts for configuring thread pools guide for details.

Verifying the deployment

Confirm that the Keycloak deployment is ready.

kubectl wait --for=condition=Ready keycloaks.k8s.keycloak.org/keycloak
kubectl wait --for=condition=RollingUpdate=False keycloaks.k8s.keycloak.org/keycloak

Optional: Load shedding

To enable load shedding, limit the number of queued requests.

Load shedding with max queued http requests
spec:
  additionalOptions:
    - name: http-max-queued-requests
      value: "1000"

All exceeding requests are served with an HTTP 503. See the Concepts for configuring thread pools guide about load shedding for details.

Optional: Disable sticky sessions

When running on OpenShift and the default passthrough Ingress setup as provided by the Keycloak Operator, the load balancing done by HAProxy is done by using sticky sessions based on the IP address of the source. When running load tests, or when having a reverse proxy in front of HAProxy, you might want to disable this setup to avoid receiving all requests on a single Keycloak Pod.

Add the following supplementary configuration under the spec in the Keycloak Custom Resource to disable sticky sessions.

spec:
  ingress:
    enabled: true
    annotations:
      # When running load tests, disable sticky sessions on the OpenShift HAProxy router
      # to avoid receiving all requests on a single Keycloak Pod.
      haproxy.router.openshift.io/balance: roundrobin
      haproxy.router.openshift.io/disable_cookies: 'true'
On this page