Alta disponibilidad en Keycloak: patrones que sobreviven una caída en producción
Patrones de producción para ejecutar Keycloak en modo HA: replicación de base de datos, rebalanceo de Infinispan, configuración del balanceador y qué ocurre cuando un nodo desaparece.
- Keycloak
- Security
- Operations
- Reliability
Keycloak no es «solo otro microservicio». Es la puerta de entrada a toda tu plataforma — el servicio que decide quién entra, cuánto tiempo se queda y qué puede hacer. Cuando Keycloak cae, nadie inicia sesión. Ni tus usuarios, ni tus administradores, ni tu CI. Todo se para.
Así que lo ejecutas en alta disponibilidad. Dos nodos, tres nodos, un cluster detrás de un balanceador. Pero Keycloak no es stateless. Tiene una caché distribuida (Infinispan), sesiones persistentes, tokens offline y procesamiento asíncrono de eventos. La HA aquí es más sutil que «solo añade otro pod».
Este artículo cubre los patrones que he usado para mantener clusters de Keycloak sanos en producción, y qué importa realmente cuando un nodo desaparece.
El verdadero SPOF: la base de datos
Cada nodo de Keycloak se conecta a la misma base de datos. Esa base de datos es tu punto único de fallo. Si la base de datos cae, el cluster está ciego: no hay nuevos logins, no hay refresco de tokens, no hay consultas de usuarios. La caché de Infinispan te compra segundos, no minutos.
La respuesta estándar es Postgres con Patroni o repmgr, o un servicio gestionado como RDS Multi-AZ. Es la respuesta correcta, pero hay que probar el camino de fallo:
- ¿Qué ocurre durante un failover de Patroni? Keycloak usa HikariCP para el pool de conexiones. Por defecto lanza
SQLExceptiony reintenta. El pool debe configurarse con unconnectionTimeoutcorto (3000ms) y una consulta de validación (SELECT 1). Sin eso, un failover de base de datos puede colgar cada petición durante los 30 segundos por defecto. - Las réplicas de solo lectura son tentadoras pero peligrosas. Keycloak escribe sesiones y eventos en cada login y refresco de token. Una réplica obsoleta puede devolver «sesión expirada» para un usuario activo. Si usas réplicas, dirige todas las escrituras y lecturas críticas al primario.
- Tamaño del pool: cada nodo puede usar 50–200 conexiones según la carga. Dos nodos = 400 conexiones en pico. Asegúrate de que
max_connectionsen la base de datos cubra todos los nodos posibles del cluster más margen para conexiones administrativas.
Infinispan y JGroups: la caché distribuida
Keycloak usa Infinispan como caché de segundo nivel, replicada entre nodos vía JGroups. Esta caché contiene sesiones de autenticación, sesiones de usuario, sesiones de cliente y sesiones offline. Es la razón por la que tus usuarios no golpean la base de datos en cada carga de página.
El transporte por defecto es UDP multicast, que funciona bien en una LAN y es un desastre en la mayoría de entornos cloud. En la nube, cambia a TCPPing con una lista estática de hosts iniciales. Para Kubernetes, usa DNS_PING que resuelve un servicio headless para descubrir pares.
Puntos clave a monitorizar en Infinispan:
- Cambios de vista — cada vez que un nodo entra o sale, JGroups emite una nueva vista. Monitoriza los logs de
org.jgroups.protocolsen busca deviewAccepted. Un cambio de vista en medio de una petición puede causar un fallo de autenticación transitorio. Es normal. Varios cambios de vista por minuto no lo son. - Transferencia de estado — cuando un nodo se reúne, Infinispan transfiere el estado en caché desde los miembros existentes. Esto puede causar picos de CPU en todos los nodos. Planifícalo: no reinicies todos los nodos simultáneamente.
- Rebalanceo de caché — si usas modo de caché distribuida (no replicada), las claves se reparten entre nodos. Cuando un nodo se va, se dispara el rebalanceo. Durante el rebalanceo, las búsquedas de claves que vivían en el nodo caerán y golpearán la base de datos.
Balanceador y sesiones pegajosas
Keycloak establece una cookie llamada AUTH_SESSION_ID. Es la clave para su caché local de Infinispan. Si el balanceador envía una petición a un nodo que no tiene esa sesión en su caché local, el nodo tiene que obtenerla de la base de datos o de otro miembro del cluster.
Usar sesiones pegajosas (sticky sessions) es la opción pragmática. Evita la transferencia de estado entre nodos en cada petición y mantiene la latencia predecible.
Pero las sesiones pegajosas introducen un modo de fallo: si la afinidad es demasiado agresiva, un solo nodo puede acumular demasiadas sesiones. Establece un max-age razonable en la cookie (4–8 horas) para que los clientes de larga duración se reequilibren naturalmente.
Los health checks merecen cuidado. No te limites a comprobar un HTTP 200 — verifica que el nodo puede alcanzar la base de datos y sus pares de caché. Un nodo que está «funcionando» pero desconectado del cluster responderá 200 a una comprobación TCP simple y servirá sesiones obsoletas.
Qué ocurre durante una caída de nodo
Cuando un nodo de Keycloak se cae:
- Las sesiones activas que estaban en ese nodo se pierden de la caché local. Los nodos restantes deben obtenerlas de la base de datos. Los usuarios pueden ver una breve re-autenticación (1–3 segundos).
- Los tokens ya emitidos siguen siendo válidos hasta su expiración. Keycloak valida los tokens contra su firma, no contra una caché.
- Los logins en curso durante el fallo fallarán. El cliente debe reintentar con backoff exponencial.
- Los tokens offline se almacenan en la base de datos por defecto, así que sobreviven a fallos de nodo.
El cluster debería estabilizarse en 5–15 segundos tras la pérdida de un solo nodo, asumiendo que la base de datos puede manejar el pico de cache misses.
Despliegues blue-green y reinicios graduales
Keycloak soporta despliegues blue-green, pero la transición debe gestionarse:
- Drena el nodo primero: haz que el health check del balanceador falle. Espera a que las peticiones en curso terminen (30–60s). Luego reinicia o reemplaza.
- No reinicies todos los nodos a la vez. El cluster necesita al menos un nodo superviviente para servir estado de caché a los nuevos miembros.
- Los reinicios graduales son seguros con 3+ nodos. Reinicia uno, deja que se reúna y reequilibre, luego el siguiente.
Prevención de split-brain
Infinispan usa JGroups para la membresía del cluster. Si la red se particiona, JGroups puede formar dos clusters separados. Es raro con TCP, pero posible.
Mitigación:
- TCPPing con un testigo. Añade un tercer nodo «testigo» que participe en el voto del cluster pero no sirva tráfico.
- Monitoriza cambios de membresía. Alerta ante cualquier
viewAcceptedcon menos miembros de los esperados. - Base de datos como fuente de verdad. Si sospechas un split-brain, la base de datos tiene el estado definitivo de las sesiones. Reinicia todos los nodos y deja que recarguen desde la base de datos.
La HA de Keycloak no es difícil, pero tampoco es automática. Los incidentes más comunes que he visto no los causaba Keycloak en sí — los causaba la infraestructura a su alrededor mal configurada.
Entiende su modelo de estado. Prueba tus caminos de fallo. Y ten un runbook de recuperación para cuando el cluster no se forme.