Keycloak
What you’ll accomplish
Section titled “What you’ll accomplish”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.
Prerequisites
Section titled “Prerequisites”- 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
Before you begin
Section titled “Before you begin”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.
-
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: corerepository: registry.defenseunicorns.com/public/coreref: x.x.x-upstreamoverrides:keycloak:keycloak:values:# Disable embedded dev database- path: devModevalue: falsevariables:# PostgreSQL hostname- name: KEYCLOAK_DB_HOSTpath: postgresql.host# Database user- name: KEYCLOAK_DB_USERNAMEpath: postgresql.username# Database name- name: KEYCLOAK_DB_DATABASEpath: postgresql.database# Database password- name: KEYCLOAK_DB_PASSWORDpath: postgresql.passwordsensitive: trueuds-config.yaml variables:core:KEYCLOAK_DB_HOST: "postgres.example.com"KEYCLOAK_DB_USERNAME: "keycloak"KEYCLOAK_DB_DATABASE: "keycloak"KEYCLOAK_DB_PASSWORD: "your-password"Reference pre-existing Kubernetes secrets — useful for external secret managers or shared credential stores. Set non-secret values directly in the bundle:
uds-bundle.yaml packages:- name: corerepository: registry.defenseunicorns.com/public/coreref: x.x.x-upstreamoverrides:keycloak:keycloak:values:- path: devModevalue: false# Database name to connect to- path: postgresql.databasevalue: "keycloak"# Name of the K8s Secret containing the DB host- path: postgresql.secretRef.host.namevalue: "keycloak-db-creds"# Key within that Secret holding the host value- path: postgresql.secretRef.host.keyvalue: "host"# Name of the K8s Secret containing the DB username- path: postgresql.secretRef.username.namevalue: "keycloak-db-creds"# Key within that Secret holding the username value- path: postgresql.secretRef.username.keyvalue: "username"# Name of the K8s Secret containing the DB password- path: postgresql.secretRef.password.namevalue: "keycloak-db-creds"# Key within that Secret holding the password value- path: postgresql.secretRef.password.keyvalue: "password" -
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: corerepository: registry.defenseunicorns.com/public/coreref: x.x.x-upstreamoverrides:keycloak:keycloak:values:# Disable embedded dev database- path: devModevalue: false# Enable HorizontalPodAutoscaler- path: autoscaling.enabledvalue: trueThe default HPA configuration:
Setting Default Override Path Minimum replicas 2 autoscaling.minReplicasMaximum replicas 5 autoscaling.maxReplicasCPU target utilization 80% autoscaling.metrics[0].resource.target.averageUtilizationScale-up stabilization 600 seconds autoscaling.behavior.scaleUp.stabilizationWindowSecondsScale-down stabilization 300 seconds autoscaling.behavior.scaleDown.stabilizationWindowSecondsScale-down rate 1 pod per 300 seconds autoscaling.behavior.scaleDown.policies[0] -
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: corerepository: registry.defenseunicorns.com/public/coreref: x.x.x-upstreamoverrides:keycloak:keycloak:values:# Minimum waypoint replicas- path: waypoint.horizontalPodAutoscaler.minReplicasvalue: 2# Maximum waypoint replicas- path: waypoint.horizontalPodAutoscaler.maxReplicasvalue: 5# Scaling metric configuration- path: waypoint.horizontalPodAutoscaler.metricsvalue:- type: Resourceresource:name: cputarget:type: UtilizationaverageUtilization: 90# Waypoint proxy CPU request (adjust for your environment)- path: waypoint.deployment.requests.cpuvalue: 250m# Waypoint proxy memory request (adjust for your environment)- path: waypoint.deployment.requests.memoryvalue: 256MiTo distribute waypoint replicas across nodes, add pod anti-affinity:
uds-bundle.yaml packages:- name: corerepository: registry.defenseunicorns.com/public/coreref: x.x.x-upstreamoverrides:keycloak:keycloak:values:- path: waypoint.deployment.affinityvalue:podAntiAffinity:preferredDuringSchedulingIgnoredDuringExecution:- weight: 100podAffinityTerm:labelSelector:matchLabels:gateway.networking.k8s.io/gateway-name: keycloak-waypointtopologyKey: kubernetes.io/hostname -
Create and deploy your bundle
Terminal window uds create <path-to-bundle-dir>uds deploy uds-bundle-<name>-<arch>-<version>.tar.zst
Verification
Section titled “Verification”Confirm Keycloak HA is active:
# Check HPA statusuds zarf tools kubectl get hpa -n keycloak
# Confirm multiple replicas are runninguds zarf tools kubectl get pods -n keycloak -l app.kubernetes.io/name=keycloak
# Check waypoint proxy HPAuds zarf tools kubectl get hpa -n keycloak -l gateway.networking.k8s.io/gateway-nameSuccess criteria:
- HPA shows
MINPODS: 2and current replicas >= 2 - All Keycloak pods are
RunningandReady - Waypoint HPA shows desired replicas >= configured minimum
Troubleshooting
Section titled “Troubleshooting”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:
uds zarf tools kubectl logs -n keycloak -l app.kubernetes.io/name=keycloak --tail=50Problem: HPA not scaling up under load
Section titled “Problem: HPA not scaling up under load”Symptoms: HPA shows <unknown> for current metrics.
Solution: Ensure metrics-server is deployed and healthy. UDS Core includes it as an optional component:
uds zarf tools kubectl get deployment -n kube-system metrics-serverRelated Documentation
Section titled “Related Documentation”- Keycloak: Horizontal Scaling — upstream guidance on scaling Keycloak instances
- Keycloak: Configuring the Database — database connection options and tuning
- Keycloak: Caching and Cache Configuration — distributed cache behavior across replicas
- PostgreSQL: High Availability — HA patterns for the backing database
Next steps
Section titled “Next steps”These guides and concepts may be useful to explore next: