Skip to content

Keycloak

You’ll configure Keycloak for production high availability: connecting it to an external PostgreSQL database, enabling horizontal pod autoscaling, and scaling the Istio waypoint proxy.

  • UDS CLI installed
  • Access to a Kubernetes cluster (multi-node, multi-AZ recommended)
  • An external PostgreSQL instance accessible from the cluster
  • Familiarity with UDS bundle overrides

Keycloak is the identity provider for the entire platform — if it becomes unavailable, users cannot authenticate and applications that depend on SSO will reject new sessions.

  1. Connect Keycloak to an external PostgreSQL database

    Choose the credential approach that fits your environment:

    Set known values directly in the bundle and use variables for environment-specific settings (e.g., values from Terraform outputs):

    uds-bundle.yaml
    packages:
    - name: core
    repository: registry.defenseunicorns.com/public/core
    ref: x.x.x-upstream
    overrides:
    keycloak:
    keycloak:
    values:
    # Disable embedded dev database
    - path: devMode
    value: false
    variables:
    # PostgreSQL hostname
    - name: KEYCLOAK_DB_HOST
    path: postgresql.host
    # Database user
    - name: KEYCLOAK_DB_USERNAME
    path: postgresql.username
    # Database name
    - name: KEYCLOAK_DB_DATABASE
    path: postgresql.database
    # Database password
    - name: KEYCLOAK_DB_PASSWORD
    path: postgresql.password
    sensitive: true
    uds-config.yaml
    variables:
    core:
    KEYCLOAK_DB_HOST: "postgres.example.com"
    KEYCLOAK_DB_USERNAME: "keycloak"
    KEYCLOAK_DB_DATABASE: "keycloak"
    KEYCLOAK_DB_PASSWORD: "your-password"
  2. Enable HPA autoscaling

    With an external database connected, enable the HorizontalPodAutoscaler to automatically scale Keycloak between 2 and 5 replicas based on CPU utilization:

    uds-bundle.yaml
    packages:
    - name: core
    repository: registry.defenseunicorns.com/public/core
    ref: x.x.x-upstream
    overrides:
    keycloak:
    keycloak:
    values:
    # Disable embedded dev database
    - path: devMode
    value: false
    # Enable HorizontalPodAutoscaler
    - path: autoscaling.enabled
    value: true

    The default HPA configuration:

    SettingDefaultOverride Path
    Minimum replicas2autoscaling.minReplicas
    Maximum replicas5autoscaling.maxReplicas
    CPU target utilization80%autoscaling.metrics[0].resource.target.averageUtilization
    Scale-up stabilization600 secondsautoscaling.behavior.scaleUp.stabilizationWindowSeconds
    Scale-down stabilization300 secondsautoscaling.behavior.scaleDown.stabilizationWindowSeconds
    Scale-down rate1 pod per 300 secondsautoscaling.behavior.scaleDown.policies[0]
  3. Configure waypoint proxy autoscaling

    Keycloak’s Istio waypoint proxy has an HPA enabled by default. For HA deployments, ensure the minimum replica count prevents downtime during pod rescheduling:

    uds-bundle.yaml
    packages:
    - name: core
    repository: registry.defenseunicorns.com/public/core
    ref: x.x.x-upstream
    overrides:
    keycloak:
    keycloak:
    values:
    # Minimum waypoint replicas
    - path: waypoint.horizontalPodAutoscaler.minReplicas
    value: 2
    # Maximum waypoint replicas
    - path: waypoint.horizontalPodAutoscaler.maxReplicas
    value: 5
    # Scaling metric configuration
    - path: waypoint.horizontalPodAutoscaler.metrics
    value:
    - type: Resource
    resource:
    name: cpu
    target:
    type: Utilization
    averageUtilization: 90
    # Waypoint proxy CPU request (adjust for your environment)
    - path: waypoint.deployment.requests.cpu
    value: 250m
    # Waypoint proxy memory request (adjust for your environment)
    - path: waypoint.deployment.requests.memory
    value: 256Mi

    To distribute waypoint replicas across nodes, add pod anti-affinity:

    uds-bundle.yaml
    packages:
    - name: core
    repository: registry.defenseunicorns.com/public/core
    ref: x.x.x-upstream
    overrides:
    keycloak:
    keycloak:
    values:
    - path: waypoint.deployment.affinity
    value:
    podAntiAffinity:
    preferredDuringSchedulingIgnoredDuringExecution:
    - weight: 100
    podAffinityTerm:
    labelSelector:
    matchLabels:
    gateway.networking.k8s.io/gateway-name: keycloak-waypoint
    topologyKey: kubernetes.io/hostname
  4. Create and deploy your bundle

    Terminal window
    uds create <path-to-bundle-dir>
    uds deploy uds-bundle-<name>-<arch>-<version>.tar.zst

Confirm Keycloak HA is active:

Terminal window
# Check HPA status
uds zarf tools kubectl get hpa -n keycloak
# Confirm multiple replicas are running
uds zarf tools kubectl get pods -n keycloak -l app.kubernetes.io/name=keycloak
# Check waypoint proxy HPA
uds zarf tools kubectl get hpa -n keycloak -l gateway.networking.k8s.io/gateway-name

Success criteria:

  • HPA shows MINPODS: 2 and current replicas >= 2
  • All Keycloak pods are Running and Ready
  • Waypoint HPA shows desired replicas >= configured minimum

Problem: Keycloak pods crash-looping after disabling devMode

Section titled “Problem: Keycloak pods crash-looping after disabling devMode”

Symptoms: Pods in CrashLoopBackOff, logs show database connection errors.

Solution: Verify that the external PostgreSQL is reachable from the cluster and that credentials are correct. Check the pod logs:

Terminal window
uds zarf tools kubectl logs -n keycloak -l app.kubernetes.io/name=keycloak --tail=50

Symptoms: HPA shows <unknown> for current metrics.

Solution: Ensure metrics-server is deployed and healthy. UDS Core includes it as an optional component:

Terminal window
uds zarf tools kubectl get deployment -n kube-system metrics-server

These guides and concepts may be useful to explore next: