Переделать связь нод в кластере на автоматическое обнаружение #9
This commit is contained in:
29
docker/ApiTests.Dockerfile
Normal file
29
docker/ApiTests.Dockerfile
Normal file
@@ -0,0 +1,29 @@
|
||||
# ============================================================
|
||||
# Одноэтапный Dockerfile (сборка и рантайм в одном образе)
|
||||
# ============================================================
|
||||
FROM erlang:28-alpine
|
||||
|
||||
# Устанавливаем инструменты для сборки и runtime-зависимости
|
||||
RUN apk add \
|
||||
# для сборки
|
||||
#git curl gcc
|
||||
make musl-dev \
|
||||
rust cargo openssl-dev libsodium-dev
|
||||
#\
|
||||
# для рантайма
|
||||
#openssl libstdc++ libgcc ncurses-libs
|
||||
|
||||
# Рабочая директория
|
||||
#RUN mkdir -p log/test/ct
|
||||
|
||||
# Копируем конфигурацию и исходники
|
||||
COPY rebar.config ./
|
||||
COPY include/ include/
|
||||
COPY src/ src/
|
||||
COPY test/api_SUITE.erl test/
|
||||
COPY test/api/ test/api/
|
||||
|
||||
# Компилируем и запускаем тесты
|
||||
RUN rebar3 compile
|
||||
|
||||
CMD rebar3 ct --sname ci_api_test -v
|
||||
14
docker/build-images.sh
Normal file
14
docker/build-images.sh
Normal file
@@ -0,0 +1,14 @@
|
||||
# Основной образ EventHub (единственный для нод)
|
||||
docker build -t eventhub:latest -f docker/Dockerfile .
|
||||
|
||||
# Сервис заглушка
|
||||
docker build -t fallback:latest -f docker/fallback/Dockerfile docker/fallback
|
||||
|
||||
# Observer Web
|
||||
docker build -t observer_web:latest -f docker/ObserverWeb.Dockerfile .
|
||||
|
||||
# Logrotate
|
||||
docker build -t logrotate:latest -f docker/logrotate/Dockerfile docker/logrotate
|
||||
|
||||
# Admin UI – из соседней папки EventHubFrontAdmin
|
||||
docker build -t admin-ui:latest -f ../EventHubFrontAdmin/Dockerfile ../EventHubFrontAdmin
|
||||
191
docker/docker-compose.swarm.yml
Normal file
191
docker/docker-compose.swarm.yml
Normal file
@@ -0,0 +1,191 @@
|
||||
# docker/docker-compose.swarm.yml
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
# ================== Балансировщик ==================
|
||||
traefik:
|
||||
image: traefik:latest
|
||||
command:
|
||||
# - "--log.level=DEBUG"
|
||||
- "--api.insecure=true"
|
||||
- "--providers.docker=true"
|
||||
# - "--providers.swarm.endpoint=unix:///var/run/docker.sock" # провайдер Swarm
|
||||
- "--providers.docker.exposedbydefault=false"
|
||||
- "--providers.file.filename=/etc/traefik/dynamic_conf.yml"
|
||||
- "--entrypoints.web.address=:80"
|
||||
- "--entrypoints.websecure.address=:443"
|
||||
- "--metrics.prometheus=true"
|
||||
- "--metrics.prometheus.buckets=0.1,0.3,1.2,5.0"
|
||||
- "--metrics.prometheus.addEntryPointsLabels=true"
|
||||
- "--metrics.prometheus.addServicesLabels=true"
|
||||
- "--accesslog=true"
|
||||
- "--accesslog.filepath=/var/log/traefik/access.log"
|
||||
- "--accesslog.format=json"
|
||||
- "--experimental.plugins.coraza.modulename=github.com/jcchavezs/coraza-http-wasm-traefik"
|
||||
- "--experimental.plugins.coraza.version=v0.3.0"
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
- "8080:8080"
|
||||
volumes:
|
||||
- "/var/run/docker.sock:/var/run/docker.sock:ro"
|
||||
- "./traefik/certs:/etc/traefik/certs:ro"
|
||||
- "./traefik/dynamic_conf.yml:/etc/traefik/dynamic_conf.yml:ro"
|
||||
- "traefik-logs:/var/log/traefik"
|
||||
- "traefik-plugins:/plugins-storage"
|
||||
networks:
|
||||
- eventhub-net
|
||||
deploy:
|
||||
replicas: 1
|
||||
restart_policy:
|
||||
condition: any
|
||||
|
||||
# ================== Сервис заглушка ==================
|
||||
fallback:
|
||||
image: fallback:latest
|
||||
networks:
|
||||
- eventhub-net
|
||||
deploy:
|
||||
replicas: 0
|
||||
restart_policy:
|
||||
condition: any
|
||||
|
||||
# ================== Кластер EventHub ==================
|
||||
eventhub:
|
||||
image: eventhub:latest
|
||||
hostname: "eventhub-node{{.Task.Slot}}"
|
||||
environment:
|
||||
- NODE_NAME=eventhub-node{{.Task.Slot}}
|
||||
- RELEASE_COOKIE=${RELEASE_COOKIE:-eventhub_cookie}
|
||||
- JWT_SECRET=${JWT_SECRET:-eventhub_top_secret}
|
||||
- ADMIN_SUPER_EMAIL=${ADMIN_SUPER_EMAIL:-superadmin@eventhub.local}
|
||||
- ADMIN_SUPER_PASSWORD=${ADMIN_SUPER_PASSWORD:-SuperAdmin123!}
|
||||
- ADMIN_MODER_EMAIL=${ADMIN_MODER_EMAIL:-moderator@eventhub.local}
|
||||
- ADMIN_MODER_PASSWORD=${ADMIN_MODER_PASSWORD:-Moderator123!}
|
||||
- ADMIN_SUPPORT_EMAIL=${ADMIN_SUPPORT_EMAIL:-support@eventhub.local}
|
||||
- ADMIN_SUPPORT_PASSWORD=${ADMIN_SUPPORT_PASSWORD:-Support123!}
|
||||
networks:
|
||||
eventhub-net:
|
||||
aliases:
|
||||
- eventhub-node
|
||||
volumes:
|
||||
- eventhub-data:/app/data
|
||||
deploy:
|
||||
replicas: 1
|
||||
endpoint_mode: dnsrr
|
||||
restart_policy:
|
||||
condition: any
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
|
||||
# ================== Admin UI ==================
|
||||
admin-ui:
|
||||
image: admin-ui:latest
|
||||
networks:
|
||||
- eventhub-net
|
||||
deploy:
|
||||
replicas: 0
|
||||
restart_policy:
|
||||
condition: any
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
|
||||
# ================== Мониторинг ==================
|
||||
prometheus:
|
||||
image: prom/prometheus:latest
|
||||
command:
|
||||
- '--config.file=/etc/prometheus/prometheus.yml'
|
||||
- '--storage.tsdb.path=/prometheus'
|
||||
- '--web.console.libraries=/usr/share/prometheus/console_libraries'
|
||||
- '--web.console.templates=/usr/share/prometheus/consoles'
|
||||
- '--storage.tsdb.retention.time=30d'
|
||||
- '--storage.tsdb.retention.size=15GB'
|
||||
volumes:
|
||||
- ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml
|
||||
- prometheus-data:/prometheus
|
||||
networks:
|
||||
- eventhub-net
|
||||
ports:
|
||||
- "9090:9090"
|
||||
deploy:
|
||||
replicas: 0
|
||||
restart_policy:
|
||||
condition: any
|
||||
|
||||
grafana:
|
||||
image: grafana/grafana:latest
|
||||
environment:
|
||||
- GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_ADMIN_PASSWORD}
|
||||
- GF_SECURITY_DISABLE_INITIAL_ADMIN_PASSWORD_CHANGE=false
|
||||
- GF_USERS_ALLOW_SIGN_UP=false
|
||||
- GF_AUTH_ANONYMOUS_ENABLED=false
|
||||
volumes:
|
||||
- ./grafana/provisioning:/etc/grafana/provisioning
|
||||
- ./grafana/dashboards:/etc/grafana/dashboards
|
||||
- grafana-data:/var/lib/grafana
|
||||
networks:
|
||||
- eventhub-net
|
||||
ports:
|
||||
- "3000:3000"
|
||||
deploy:
|
||||
replicas: 0
|
||||
restart_policy:
|
||||
condition: any
|
||||
|
||||
# ================== Аналитика логов ==================
|
||||
loglynx:
|
||||
image: k0lin/loglynx:latest
|
||||
user: root
|
||||
ports:
|
||||
- "6123:6123"
|
||||
volumes:
|
||||
- traefik-logs:/app/traefik/logs:ro
|
||||
- loglynx-data:/app/data
|
||||
environment:
|
||||
- TRAEFIK_LOG_PATH=${TRAEFIK_LOG_PATH}
|
||||
- SERVER_PORT=6123
|
||||
- DATABASE_PATH=/app/data/loglynx.db
|
||||
networks:
|
||||
- eventhub-net
|
||||
deploy:
|
||||
replicas: 0
|
||||
restart_policy:
|
||||
condition: any
|
||||
|
||||
# ================== Инструмент отладки ==================
|
||||
observer_web:
|
||||
image: observer_web:latest
|
||||
environment:
|
||||
- RELEASE_COOKIE=${RELEASE_COOKIE}
|
||||
networks:
|
||||
- eventhub-net
|
||||
ports:
|
||||
- "4000:4000"
|
||||
deploy:
|
||||
replicas: 0
|
||||
restart_policy:
|
||||
condition: any
|
||||
|
||||
# ================== Ротация логов ==================
|
||||
logrotate:
|
||||
image: logrotate:latest
|
||||
volumes:
|
||||
- traefik-logs:/var/log/traefik:rw
|
||||
networks:
|
||||
- eventhub-net
|
||||
deploy:
|
||||
replicas: 0
|
||||
restart_policy:
|
||||
condition: any
|
||||
|
||||
networks:
|
||||
eventhub-net:
|
||||
driver: overlay
|
||||
|
||||
volumes:
|
||||
eventhub-data:
|
||||
prometheus-data:
|
||||
grafana-data:
|
||||
traefik-logs:
|
||||
loglynx-data:
|
||||
traefik-plugins:
|
||||
@@ -45,6 +45,7 @@ services:
|
||||
networks:
|
||||
- eventhub-net
|
||||
restart: unless-stopped
|
||||
profiles: ['ci']
|
||||
|
||||
# ================== Кластер EventHub (3 ноды) ==================
|
||||
eventhub-node1:
|
||||
@@ -56,9 +57,10 @@ services:
|
||||
- NODE_NAME=eventhub-node1@eventhub-node1.local
|
||||
- RELEASE_COOKIE=${RELEASE_COOKIE}
|
||||
- JWT_SECRET=${JWT_SECRET}
|
||||
- JOIN_NODES=eventhub-node1@eventhub-node1.local,eventhub-node2@eventhub-node2.local,eventhub-node3@eventhub-node3.local
|
||||
networks:
|
||||
- eventhub-net
|
||||
eventhub-net:
|
||||
aliases:
|
||||
- eventhub-node # ← общий алиас для DNS-лукапа
|
||||
volumes:
|
||||
- eventhub-node1-data:/app/data
|
||||
labels:
|
||||
@@ -74,9 +76,10 @@ services:
|
||||
- NODE_NAME=eventhub-node2@eventhub-node2.local
|
||||
- RELEASE_COOKIE=${RELEASE_COOKIE}
|
||||
- JWT_SECRET=${JWT_SECRET}
|
||||
- JOIN_NODES=eventhub-node1@eventhub-node1.local,eventhub-node2@eventhub-node2.local,eventhub-node3@eventhub-node3.local
|
||||
networks:
|
||||
- eventhub-net
|
||||
eventhub-net:
|
||||
aliases:
|
||||
- eventhub-node # ← общий алиас для DNS-лукапа
|
||||
volumes:
|
||||
- eventhub-node2-data:/app/data
|
||||
labels:
|
||||
@@ -92,9 +95,10 @@ services:
|
||||
- NODE_NAME=eventhub-node3@eventhub-node3.local
|
||||
- RELEASE_COOKIE=${RELEASE_COOKIE}
|
||||
- JWT_SECRET=${JWT_SECRET}
|
||||
- JOIN_NODES=eventhub-node1@eventhub-node1.local,eventhub-node2@eventhub-node2.local,eventhub-node3@eventhub-node3.local
|
||||
networks:
|
||||
- eventhub-net
|
||||
eventhub-net:
|
||||
aliases:
|
||||
- eventhub-node # ← общий алиас для DNS-лукапа
|
||||
volumes:
|
||||
- eventhub-node3-data:/app/data
|
||||
labels:
|
||||
@@ -108,9 +112,11 @@ services:
|
||||
dockerfile: Dockerfile
|
||||
networks:
|
||||
- eventhub-net
|
||||
restart: unless-stopped
|
||||
# restart: unless-stopped
|
||||
restart: no
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
profiles: ['ui']
|
||||
# ================== Мониторинг ==================
|
||||
prometheus:
|
||||
image: prom/prometheus:latest
|
||||
@@ -129,6 +135,7 @@ services:
|
||||
ports:
|
||||
- "9090:9090"
|
||||
restart: unless-stopped
|
||||
profiles: ['ci']
|
||||
|
||||
grafana:
|
||||
image: grafana/grafana:latest
|
||||
@@ -146,6 +153,7 @@ services:
|
||||
ports:
|
||||
- "3000:3000"
|
||||
restart: unless-stopped
|
||||
profiles: ['ci']
|
||||
|
||||
# ================== Аналитика логов ==================
|
||||
loglynx:
|
||||
@@ -163,6 +171,7 @@ services:
|
||||
- DATABASE_PATH=/app/data/loglynx.db
|
||||
networks:
|
||||
- eventhub-net
|
||||
profiles: ['ci']
|
||||
|
||||
# ================== Инструмент отладки ==================
|
||||
observer_web:
|
||||
@@ -176,6 +185,7 @@ services:
|
||||
ports:
|
||||
- "4000:4000"
|
||||
restart: unless-stopped
|
||||
profiles: ['ci']
|
||||
|
||||
# ================== Ротация логов Traefik ==================
|
||||
logrotate:
|
||||
@@ -187,6 +197,7 @@ services:
|
||||
networks:
|
||||
- eventhub-net
|
||||
restart: unless-stopped
|
||||
profiles: ['ci']
|
||||
|
||||
networks:
|
||||
eventhub-net:
|
||||
|
||||
@@ -9,50 +9,58 @@ tls:
|
||||
keyFile: /etc/traefik/certs/traefik.key
|
||||
|
||||
http:
|
||||
serversTransports:
|
||||
http1-ws-transport:
|
||||
disableHTTP2: true
|
||||
insecureSkipVerify: true
|
||||
|
||||
middlewares:
|
||||
redirect-to-https:
|
||||
redirectScheme:
|
||||
scheme: https
|
||||
permanent: true
|
||||
|
||||
strip-api-prefix:
|
||||
stripPrefix:
|
||||
prefixes:
|
||||
- "/api"
|
||||
|
||||
waf:
|
||||
plugin:
|
||||
coraza:
|
||||
directives:
|
||||
# - "SecRuleEngine DetectionOnly" # можно раскомментировать для тестирования
|
||||
- "SecRuleEngine On"
|
||||
- "SecDebugLog /dev/stdout"
|
||||
- "SecDebugLogLevel 2"
|
||||
# - "SecRule REQUEST_URI \"@rx /admin\" \"id:101,phase:1,log,deny,status:403\""
|
||||
- "SecRule ARGS \"@rx (union|select|insert|drop|alter)\" \"id:102,phase:2,log,deny,status:403\""
|
||||
|
||||
api-ratelimit:
|
||||
rateLimit:
|
||||
average: 100
|
||||
average: 5000
|
||||
period: 1m
|
||||
burst: 50
|
||||
burst: 500
|
||||
|
||||
admin-ratelimit:
|
||||
rateLimit:
|
||||
average: 20
|
||||
average: 5000
|
||||
period: 1m
|
||||
burst: 5
|
||||
burst: 500
|
||||
|
||||
routers:
|
||||
# --- REST API пользователей ---
|
||||
# Пользовательский REST API
|
||||
api:
|
||||
rule: "Host(`api.eventhub.local`)"
|
||||
entryPoints: ["web"]
|
||||
middlewares: ["redirect-to-https", "api-ratelimit", "waf"]
|
||||
middlewares: ["redirect-to-https", "strip-api-prefix", "api-ratelimit", "waf"]
|
||||
service: "api"
|
||||
api-secure:
|
||||
rule: "Host(`api.eventhub.local`)"
|
||||
entryPoints: ["websecure"]
|
||||
tls: true
|
||||
middlewares: ["api-ratelimit", "waf"]
|
||||
middlewares: ["strip-api-prefix", "api-ratelimit", "waf"]
|
||||
service: "api"
|
||||
|
||||
# --- WebSocket пользователей (без WAF) ---
|
||||
# Пользовательский WebSocket
|
||||
ws:
|
||||
rule: "Host(`ws.eventhub.local`)"
|
||||
entryPoints: ["web"]
|
||||
@@ -64,45 +72,56 @@ http:
|
||||
tls: true
|
||||
service: "ws"
|
||||
|
||||
# --- Админ-панель (SPA) ---
|
||||
# Админский REST API
|
||||
admin-api:
|
||||
rule: "Host(`admin-api.eventhub.local`)"
|
||||
entryPoints: ["web"]
|
||||
middlewares: ["redirect-to-https", "strip-api-prefix", "admin-ratelimit", "waf"]
|
||||
service: "admin-api"
|
||||
admin-api-secure:
|
||||
rule: "Host(`admin-api.eventhub.local`)"
|
||||
entryPoints: ["websecure"]
|
||||
tls: true
|
||||
middlewares: ["strip-api-prefix", "admin-ratelimit", "waf"]
|
||||
service: "admin-api"
|
||||
|
||||
# Админский WebSocket
|
||||
admin-ws:
|
||||
rule: "Host(`admin-ws.eventhub.local`)"
|
||||
entryPoints: ["web"]
|
||||
middlewares: ["redirect-to-https"]
|
||||
service: "admin-ws"
|
||||
admin-ws-secure:
|
||||
rule: "Host(`admin-ws.eventhub.local`)"
|
||||
entryPoints: ["websecure"]
|
||||
tls: true
|
||||
service: "admin-ws"
|
||||
|
||||
# Админский UI
|
||||
admin-ui:
|
||||
rule: "Host(`admin.eventhub.local`) && !PathPrefix(`/api/`) && !PathPrefix(`/ws/`)"
|
||||
rule: "Host(`admin-ui.eventhub.local`)"
|
||||
entryPoints: ["web"]
|
||||
middlewares: ["redirect-to-https"]
|
||||
service: "admin-ui-service"
|
||||
admin-ui-secure:
|
||||
rule: "Host(`admin.eventhub.local`) && !PathPrefix(`/api/`) && !PathPrefix(`/ws/`)"
|
||||
rule: "Host(`admin-ui.eventhub.local`)"
|
||||
entryPoints: ["websecure"]
|
||||
tls: true
|
||||
service: "admin-ui-service"
|
||||
|
||||
# --- Проксирование /api/ на админский REST ---
|
||||
admin-api-proxy:
|
||||
rule: "Host(`admin.eventhub.local`) && PathPrefix(`/api/`)"
|
||||
entryPoints: ["web"]
|
||||
middlewares: ["redirect-to-https", "admin-ratelimit", "waf"]
|
||||
service: "admin-api"
|
||||
admin-api-proxy-secure:
|
||||
rule: "Host(`admin.eventhub.local`) && PathPrefix(`/api/`)"
|
||||
entryPoints: ["websecure"]
|
||||
tls: true
|
||||
middlewares: ["admin-ratelimit", "waf"]
|
||||
service: "admin-api"
|
||||
|
||||
# --- Проксирование /ws/ на админский WebSocket ---
|
||||
admin-ws-proxy:
|
||||
rule: "Host(`admin.eventhub.local`) && PathPrefix(`/ws/`)"
|
||||
# Клиентский UI
|
||||
client-ui:
|
||||
rule: "Host(`ui.eventhub.local`)"
|
||||
entryPoints: ["web"]
|
||||
middlewares: ["redirect-to-https"]
|
||||
service: "admin-ws"
|
||||
admin-ws-proxy-secure:
|
||||
rule: "Host(`admin.eventhub.local`) && PathPrefix(`/ws/`)"
|
||||
service: "client-ui-service"
|
||||
client-ui-secure:
|
||||
rule: "Host(`ui.eventhub.local`)"
|
||||
entryPoints: ["websecure"]
|
||||
tls: true
|
||||
service: "admin-ws"
|
||||
service: "client-ui-service"
|
||||
|
||||
services:
|
||||
# --- Пользовательский REST API (failover) ---
|
||||
api:
|
||||
failover:
|
||||
service: api-live
|
||||
@@ -110,9 +129,7 @@ http:
|
||||
api-live:
|
||||
loadbalancer:
|
||||
servers:
|
||||
- url: "http://eventhub-node1:8080"
|
||||
- url: "http://eventhub-node2:8080"
|
||||
- url: "http://eventhub-node3:8080"
|
||||
- url: "http://eventhub:8080"
|
||||
healthCheck:
|
||||
path: "/health"
|
||||
interval: "10s"
|
||||
@@ -122,15 +139,12 @@ http:
|
||||
servers:
|
||||
- url: "http://fallback:80"
|
||||
|
||||
# --- Пользовательский WebSocket ---
|
||||
ws:
|
||||
loadbalancer:
|
||||
servers:
|
||||
- url: "http://eventhub-node1:8081"
|
||||
- url: "http://eventhub-node2:8081"
|
||||
- url: "http://eventhub-node3:8081"
|
||||
- url: "http://eventhub:8081"
|
||||
serversTransport: http1-ws-transport
|
||||
|
||||
# --- Админский REST (failover) ---
|
||||
admin-api:
|
||||
failover:
|
||||
service: admin-api-live
|
||||
@@ -138,11 +152,9 @@ http:
|
||||
admin-api-live:
|
||||
loadbalancer:
|
||||
servers:
|
||||
- url: "http://eventhub-node1:8445"
|
||||
- url: "http://eventhub-node2:8445"
|
||||
- url: "http://eventhub-node3:8445"
|
||||
- url: "http://eventhub:8445"
|
||||
healthCheck:
|
||||
path: "/health"
|
||||
path: "/v1/admin/health"
|
||||
interval: "10s"
|
||||
timeout: "3s"
|
||||
admin-api-fallback:
|
||||
@@ -150,16 +162,18 @@ http:
|
||||
servers:
|
||||
- url: "http://fallback:80"
|
||||
|
||||
# --- Админский WebSocket ---
|
||||
admin-ws:
|
||||
loadbalancer:
|
||||
servers:
|
||||
- url: "http://eventhub-node1:8446"
|
||||
- url: "http://eventhub-node2:8446"
|
||||
- url: "http://eventhub-node3:8446"
|
||||
- url: "http://eventhub:8446"
|
||||
serversTransport: http1-ws-transport
|
||||
|
||||
# --- SPA (админ‑панель) ---
|
||||
admin-ui-service:
|
||||
loadbalancer:
|
||||
servers:
|
||||
- url: "http://admin-ui:80"
|
||||
- url: "http://admin-ui:80"
|
||||
|
||||
client-ui-service:
|
||||
loadbalancer:
|
||||
servers:
|
||||
- url: "http://client-ui:80"
|
||||
Reference in New Issue
Block a user