Мега-руководство: Как развернуть Keycloak в кластере с Nginx за 10 минут!
Поднимите высокодоступный Keycloak с Nginx в качестве балансировщика — быстро для старта и безопасно для масштабирования. В этом руководстве вы соберёте рабочий кластер за минуты, а затем укрепите его для продакшена.
Быстрый старт: кластер за 10 минут
Хотите быстро попробовать в Docker? Поднимите две ноды Keycloak и Nginx спереди. Такой сетап идеален для локальной проверки перед переносом в Kubernetes.
docker-compose.yml (минимальный стенд)
1version: '3.9'
2services:
3 keycloak-1:
4 image: quay.io/keycloak/keycloak:latest
5 command: >
6 start --http-enabled=true
7 --hostname-strict=false
8 --proxy-headers=xforwarded
9 --metrics-enabled=true
10 environment:
11 KC_DB: postgres
12 KC_DB_URL: jdbc:postgresql://postgres:5432/keycloak
13 KC_DB_USERNAME: keycloak
14 KC_DB_PASSWORD: keycloak
15 KEYCLOAK_ADMIN: admin
16 KEYCLOAK_ADMIN_PASSWORD: admin
17 depends_on: [postgres]
18 keycloak-2:
19 image: quay.io/keycloak/keycloak:latest
20 command: >
21 start --http-enabled=true
22 --hostname-strict=false
23 --proxy-headers=xforwarded
24 --metrics-enabled=true
25 environment:
26 KC_DB: postgres
27 KC_DB_URL: jdbc:postgresql://postgres:5432/keycloak
28 KC_DB_USERNAME: keycloak
29 KC_DB_PASSWORD: keycloak
30 KEYCLOAK_ADMIN: admin
31 KEYCLOAK_ADMIN_PASSWORD: admin
32 depends_on: [postgres]
33
34 postgres:
35 image: postgres:16
36 environment:
37 POSTGRES_DB: keycloak
38 POSTGRES_USER: keycloak
39 POSTGRES_PASSWORD: keycloak
40
41 nginx:
42 image: nginx:1.27
43 volumes:
44 - ./nginx.conf:/etc/nginx/nginx.conf:ro
45 - ./certs:/etc/nginx/certs:ro
46 ports: ["80:80", "443:443"]
47 depends_on: [keycloak-1, keycloak-2]
48
Создайте nginx.conf
с конфигом из раздела про Nginx, затем выполните:
1docker compose up -d && open https://localhost
Современные флаги Keycloak (Quarkus)
Для работы за реверс‑прокси используйте --proxy-headers=xforwarded
, --http-enabled=true
и --hostname-strict=false
. Наследуемая переменная PROXY_ADDRESS_FORWARDING
не нужна на актуальных версиях.
Кластеризация Keycloak: что и зачем
Keycloak даёт SSO по OpenID Connect, OAuth 2.0 и SAML. Одной ноды хватает, пока не понадобятся целевые SLA по аптайму, бесшовные обновления и работа под пиками. Кластер добавляет отказоустойчивость и масштаб; Infinispan обеспечивает распределённые кэши сессий и токенов.
Два популярных пути
VM/бэр‑метал: JGroups (TCP/DNS_PING/JDBC_PING). Облака/Kubernetes: KUBE_PING через API Kubernetes. Оба варианта рабочие — выбирайте под вашу платформу и операционную модель.
Почему Nginx перед Keycloak
Производительность
- Эффективное завершение TLS
- Низкое потребление памяти под высокой конкуррентностью
- Умное буферизование, защищающее бэкенды
Надёжность и безопасность
- Скрывает внутреннюю топологию
- Пассивные health‑checks (фейловер) в OSS
- Тонкий контроль заголовков в прокси‑схемах
В Kubernetes ту же роль выполняет Ingress‑контроллер (например, NGINX Ingress). Остальные рекомендации остаются: важно корректно завершать TLS, передавать заголовки и выбрать стратегию сессий.
Режимы кластеризации (JGroups vs Kubernetes)
JGroups
Отлично подходит для статичных или VM‑кластеров. Дискавери через TCP, UDP, TCPPING или DNS_PING. JDBC_PING удобен в контейнерных стендах с общей БД.
Важно
JGroups требователен к сети (порты/фаерволы) и консистентности настроек discovery. Задержки между нодами влияют на репликацию кэша и опыт сессий.
Kubernetes
Используйте KUBE_PING. Предпочтительны StatefulSet (стабильные идентичности) и headless‑Service для DNS. Масштабирование проще; живучесть нод контролирует платформа.
Основы сервис‑дискавери
Новые ноды должны быстро находить пиров, реплицировать состояние кэша и принимать трафик. Discovery — это автоматизация этого рукопожатия.
Динамическое масштабирование
- Ноды приходят/уходят без ручных списков IP
- Быстрые релизы и blue/green
- Менее хрупко, чем статические конфиги
Отказоустойчивость
- Нездоровые ноды исключаются автоматически
- Непрерывность сессий между нодами
- Меньше алертов во время обслуживания
Опции discovery на практике
Частые выборы
- TCPPING: статические списки IP (малые, стабильные кластера)
- UDP: широковещание в подсети (лабы)
- JDBC_PING: реестр в БД (контейнерные стенды)
- KUBE_PING: API Service в Kubernetes (облако)
- DNS_PING: DNS‑записи облачных провайдеров (AWS/GCP/Azure)
Конфиг Nginx (TLS, proxy, sticky‑сессии)
Ниже — безопасный дефолт для OSS Nginx. Он завершает TLS, проксирует исходные заголовки клиента и использует пассивные проверки здоровья (max_fails
, fail_timeout
). Для аффинности сессий можно начать с ip_hash
— просто и эффективно.
1events { worker_connections 1024; }
2
3http {
4 # Если вы в Docker, 127.0.0.11 — встроенный DNS. Иначе укажите свой resolver.
5 resolver 127.0.0.11 valid=30s ipv6=off;
6
7 upstream keycloak_http {
8 zone keycloak_http 64k;
9 ip_hash; # Простая sticky‑аффинность
10 server keycloak-1:8080 max_fails=3 fail_timeout=10s;
11 server keycloak-2:8080 max_fails=3 fail_timeout=10s;
12 }
13
14 server {
15 listen 80;
16 server_name _;
17 return 301 https://$host$request_uri;
18 }
19
20 server {
21 listen 443 ssl http2;
22 server_name _;
23
24 ssl_certificate /etc/nginx/certs/tls.crt;
25 ssl_certificate_key /etc/nginx/certs/tls.key;
26 ssl_protocols TLSv1.2 TLSv1.3;
27 ssl_ciphers HIGH:!aNULL:!MD5;
28
29 # Health‑проба (пассивная): Nginx пометит peer как failed при ошибках/таймаутах.
30 location = /health {
31 proxy_pass http://keycloak_http/realms/master/health;
32 proxy_set_header Host $host;
33 }
34
35 location / {
36 proxy_pass http://keycloak_http;
37 proxy_http_version 1.1;
38
39 # Проброс заголовков для современного Keycloak
40 proxy_set_header Host $host;
41 proxy_set_header X-Real-IP $remote_addr;
42 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
43 proxy_set_header X-Forwarded-Proto $scheme;
44 proxy_set_header X-Forwarded-Host $host;
45 proxy_set_header X-Forwarded-Port $server_port;
46
47 # Поддержка Upgrade (WebSocket, live‑фичи админки)
48 proxy_set_header Upgrade $http_upgrade;
49 proxy_set_header Connection $connection_upgrade;
50
51 # Буферы и таймауты — подстройте под свой профиль трафика
52 proxy_connect_timeout 5s;
53 proxy_read_timeout 60s;
54 proxy_send_timeout 60s;
55 proxy_buffering on;
56 }
57 }
58}
Почему это работает
- ip_hash даёт базовую аффинность сессий без дополнительных модулей.
- Проброшенные заголовки согласованы с флагами Keycloak (
--proxy-headers=xforwarded
). - Пассивные проверки здоровья исключают проблемные ноды после нескольких сбоев. (Активные проверки — функция NGINX Plus или внешних тулов.)
Чеклист продакшен‑закалки
- Корректно задайте
--hostname
и (при необходимости)--hostname-strict
; добейтесь консистентности внешнего URL. - Включите
--metrics-enabled=true
и скрейпинг Prometheus; добавьте алерты (скачки сессий, 5xx, ошибки логина). - Используйте отказоустойчивую БД (HA Postgres), настройте пулы и TLS к БД.
- Ротуйте админские креды, ограничьте доступ в админ‑консоль по IP/VPN и включите 2FA для админов.
- Нужна более сильная аффинность? Рассмотрите сервис‑mesh (sticky‑маршрутизация) или NGINX Plus с куки‑персистенсом.
- В Kubernetes: используйте
StatefulSet
+ headless‑Service; предпочитайте NGINX Ingress с аннотациями таймаутов/заголовков.
FAQ
Нужен ли ещё PROXY_ADDRESS_FORWARDING?
Для современного Keycloak (Quarkus) — нет. Используйте --proxy-headers=xforwarded
и держите заголовки в Nginx консистентными.
Обязательны ли sticky‑сессии?
Полезны, но не обязательны. Infinispan реплицирует сессии, а аффинность снижает «шумные» хопы. Начните с ip_hash
; переходите на персистентность по куки, если действительно нужно.
Есть ли активные health‑checks в OSS Nginx?
Нативные активные проверки — это фича NGINX Plus. В OSS полагайтесь на пассивные проверки или внешние пробы с динамическим обновлением upstream.
Что дальше?
Посмотрите паттерны RBAC в Keycloak и интеграцию Keycloak с Next.js.