feat(infra): blue-green deployment via HAProxy
- HAProxy: api/stream/web backends with blue+green servers (backup) - docker-compose.prod: backend-api-blue/green, stream-server-blue/green, web-blue/green - haproxy-blue.cfg, haproxy-green.cfg: config variants for active stack - scripts/deploy-blue-green.sh: switch traffic via config copy + HUP reload
This commit is contained in:
parent
cdc4bd82e6
commit
0ff8a85684
5 changed files with 324 additions and 26 deletions
77
config/haproxy/haproxy-blue.cfg
Normal file
77
config/haproxy/haproxy-blue.cfg
Normal file
|
|
@ -0,0 +1,77 @@
|
||||||
|
# Blue stack active - copy to haproxy.cfg for blue deployment
|
||||||
|
# Generated from haproxy.cfg - blue servers main, green backup
|
||||||
|
global
|
||||||
|
log stdout format raw local0
|
||||||
|
maxconn 4096
|
||||||
|
daemon
|
||||||
|
stats socket /var/run/haproxy.sock level admin
|
||||||
|
|
||||||
|
defaults
|
||||||
|
log global
|
||||||
|
mode http
|
||||||
|
option httplog
|
||||||
|
option dontlognull
|
||||||
|
option forwardfor
|
||||||
|
option http-server-close
|
||||||
|
timeout connect 5000ms
|
||||||
|
timeout client 50000ms
|
||||||
|
timeout server 50000ms
|
||||||
|
timeout http-request 10000ms
|
||||||
|
|
||||||
|
frontend stats
|
||||||
|
bind *:8404
|
||||||
|
stats enable
|
||||||
|
stats uri /stats
|
||||||
|
stats refresh 30s
|
||||||
|
acl from_internal src 127.0.0.1 172.20.0.0/16
|
||||||
|
stats admin if from_internal
|
||||||
|
|
||||||
|
frontend http_frontend
|
||||||
|
bind *:80
|
||||||
|
mode http
|
||||||
|
redirect scheme https code 301 if !{ ssl_fc }
|
||||||
|
acl is_api path_beg /api/v1
|
||||||
|
acl is_stream path_beg /stream
|
||||||
|
acl is_hls path_beg /hls
|
||||||
|
acl is_web path_beg /
|
||||||
|
use_backend backend_api if is_api
|
||||||
|
use_backend stream_ws if is_stream
|
||||||
|
use_backend stream_ws if is_hls
|
||||||
|
use_backend web_frontend if is_web
|
||||||
|
|
||||||
|
frontend https_frontend
|
||||||
|
bind *:443 ssl crt /etc/ssl/veza/veza.pem
|
||||||
|
mode http
|
||||||
|
acl is_api path_beg /api/v1
|
||||||
|
acl is_stream path_beg /stream
|
||||||
|
acl is_hls path_beg /hls
|
||||||
|
acl is_web path_beg /
|
||||||
|
use_backend backend_api if is_api
|
||||||
|
use_backend stream_ws if is_stream
|
||||||
|
use_backend stream_ws if is_hls
|
||||||
|
use_backend web_frontend if is_web
|
||||||
|
|
||||||
|
backend backend_api
|
||||||
|
mode http
|
||||||
|
balance roundrobin
|
||||||
|
option httpchk GET /api/v1/health
|
||||||
|
http-check expect status 200
|
||||||
|
server api_blue backend-api-blue:8080 check inter 5s fall 3 rise 2
|
||||||
|
server api_green backend-api-green:8080 check inter 5s fall 3 rise 2 backup
|
||||||
|
|
||||||
|
backend stream_ws
|
||||||
|
mode http
|
||||||
|
balance roundrobin
|
||||||
|
option httpchk GET /health
|
||||||
|
http-check expect status 200
|
||||||
|
timeout tunnel 3600s
|
||||||
|
server stream_blue stream-server-blue:3001 check inter 5s fall 3 rise 2
|
||||||
|
server stream_green stream-server-green:3001 check inter 5s fall 3 rise 2 backup
|
||||||
|
|
||||||
|
backend web_frontend
|
||||||
|
mode http
|
||||||
|
balance roundrobin
|
||||||
|
option httpchk GET /
|
||||||
|
http-check expect status 200
|
||||||
|
server web_blue web-blue:5173 check inter 5s fall 3 rise 2
|
||||||
|
server web_green web-green:5173 check inter 5s fall 3 rise 2 backup
|
||||||
77
config/haproxy/haproxy-green.cfg
Normal file
77
config/haproxy/haproxy-green.cfg
Normal file
|
|
@ -0,0 +1,77 @@
|
||||||
|
# Green stack active - copy to haproxy.cfg for green deployment
|
||||||
|
# Generated from haproxy.cfg - green servers main, blue backup
|
||||||
|
global
|
||||||
|
log stdout format raw local0
|
||||||
|
maxconn 4096
|
||||||
|
daemon
|
||||||
|
stats socket /var/run/haproxy.sock level admin
|
||||||
|
|
||||||
|
defaults
|
||||||
|
log global
|
||||||
|
mode http
|
||||||
|
option httplog
|
||||||
|
option dontlognull
|
||||||
|
option forwardfor
|
||||||
|
option http-server-close
|
||||||
|
timeout connect 5000ms
|
||||||
|
timeout client 50000ms
|
||||||
|
timeout server 50000ms
|
||||||
|
timeout http-request 10000ms
|
||||||
|
|
||||||
|
frontend stats
|
||||||
|
bind *:8404
|
||||||
|
stats enable
|
||||||
|
stats uri /stats
|
||||||
|
stats refresh 30s
|
||||||
|
acl from_internal src 127.0.0.1 172.20.0.0/16
|
||||||
|
stats admin if from_internal
|
||||||
|
|
||||||
|
frontend http_frontend
|
||||||
|
bind *:80
|
||||||
|
mode http
|
||||||
|
redirect scheme https code 301 if !{ ssl_fc }
|
||||||
|
acl is_api path_beg /api/v1
|
||||||
|
acl is_stream path_beg /stream
|
||||||
|
acl is_hls path_beg /hls
|
||||||
|
acl is_web path_beg /
|
||||||
|
use_backend backend_api if is_api
|
||||||
|
use_backend stream_ws if is_stream
|
||||||
|
use_backend stream_ws if is_hls
|
||||||
|
use_backend web_frontend if is_web
|
||||||
|
|
||||||
|
frontend https_frontend
|
||||||
|
bind *:443 ssl crt /etc/ssl/veza/veza.pem
|
||||||
|
mode http
|
||||||
|
acl is_api path_beg /api/v1
|
||||||
|
acl is_stream path_beg /stream
|
||||||
|
acl is_hls path_beg /hls
|
||||||
|
acl is_web path_beg /
|
||||||
|
use_backend backend_api if is_api
|
||||||
|
use_backend stream_ws if is_stream
|
||||||
|
use_backend stream_ws if is_hls
|
||||||
|
use_backend web_frontend if is_web
|
||||||
|
|
||||||
|
backend backend_api
|
||||||
|
mode http
|
||||||
|
balance roundrobin
|
||||||
|
option httpchk GET /api/v1/health
|
||||||
|
http-check expect status 200
|
||||||
|
server api_blue backend-api-blue:8080 check inter 5s fall 3 rise 2 backup
|
||||||
|
server api_green backend-api-green:8080 check inter 5s fall 3 rise 2
|
||||||
|
|
||||||
|
backend stream_ws
|
||||||
|
mode http
|
||||||
|
balance roundrobin
|
||||||
|
option httpchk GET /health
|
||||||
|
http-check expect status 200
|
||||||
|
timeout tunnel 3600s
|
||||||
|
server stream_blue stream-server-blue:3001 check inter 5s fall 3 rise 2 backup
|
||||||
|
server stream_green stream-server-green:3001 check inter 5s fall 3 rise 2
|
||||||
|
|
||||||
|
backend web_frontend
|
||||||
|
mode http
|
||||||
|
balance roundrobin
|
||||||
|
option httpchk GET /
|
||||||
|
http-check expect status 200
|
||||||
|
server web_blue web-blue:5173 check inter 5s fall 3 rise 2 backup
|
||||||
|
server web_green web-green:5173 check inter 5s fall 3 rise 2
|
||||||
|
|
@ -2,6 +2,8 @@ global
|
||||||
log stdout format raw local0
|
log stdout format raw local0
|
||||||
maxconn 4096
|
maxconn 4096
|
||||||
daemon
|
daemon
|
||||||
|
# Blue-green: runtime API for server enable/disable
|
||||||
|
stats socket /var/run/haproxy.sock level admin
|
||||||
|
|
||||||
defaults
|
defaults
|
||||||
log global
|
log global
|
||||||
|
|
@ -67,35 +69,34 @@ frontend https_frontend
|
||||||
use_backend web_frontend if is_web
|
use_backend web_frontend if is_web
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
# BACKENDS
|
# BACKENDS - Blue-Green Deployment
|
||||||
|
# Use scripts/deploy-blue-green.sh to switch active stack
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
|
|
||||||
# Backend API (Go)
|
# Backend API (Go) - blue/green
|
||||||
backend backend_api
|
backend backend_api
|
||||||
mode http
|
mode http
|
||||||
balance roundrobin
|
balance roundrobin
|
||||||
option httpchk GET /api/v1/health
|
option httpchk GET /api/v1/health
|
||||||
http-check expect status 200
|
http-check expect status 200
|
||||||
server backend1 backend-api:8080 check inter 5s fall 3 rise 2
|
server api_blue backend-api-blue:8080 check inter 5s fall 3 rise 2
|
||||||
# Add more servers for load balancing:
|
server api_green backend-api-green:8080 check inter 5s fall 3 rise 2 backup
|
||||||
# server backend2 backend-api-2:8080 check inter 5s fall 3 rise 2
|
|
||||||
|
|
||||||
# Stream WebSocket (Rust)
|
# Stream WebSocket (Rust) - blue/green
|
||||||
backend stream_ws
|
backend stream_ws
|
||||||
mode http
|
mode http
|
||||||
balance roundrobin
|
balance roundrobin
|
||||||
option httpchk GET /health
|
option httpchk GET /health
|
||||||
http-check expect status 200
|
http-check expect status 200
|
||||||
server stream1 stream-server:3001 check inter 5s fall 3 rise 2
|
|
||||||
# WebSocket specific options
|
|
||||||
timeout tunnel 3600s
|
timeout tunnel 3600s
|
||||||
|
server stream_blue stream-server-blue:3001 check inter 5s fall 3 rise 2
|
||||||
|
server stream_green stream-server-green:3001 check inter 5s fall 3 rise 2 backup
|
||||||
|
|
||||||
# Web Frontend (React/Vite)
|
# Web Frontend (React/Vite) - blue/green
|
||||||
backend web_frontend
|
backend web_frontend
|
||||||
mode http
|
mode http
|
||||||
balance roundrobin
|
balance roundrobin
|
||||||
option httpchk GET /
|
option httpchk GET /
|
||||||
http-check expect status 200
|
http-check expect status 200
|
||||||
server web1 web:5173 check inter 5s fall 3 rise 2
|
server web_blue web-blue:5173 check inter 5s fall 3 rise 2
|
||||||
# Add more servers for load balancing:
|
server web_green web-green:5173 check inter 5s fall 3 rise 2 backup
|
||||||
# server web2 web-2:5173 check inter 5s fall 3 rise 2
|
|
||||||
|
|
|
||||||
|
|
@ -139,17 +139,19 @@ services:
|
||||||
memory: 256M
|
memory: 256M
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
# APPLICATION SERVICES
|
# APPLICATION SERVICES - Blue-Green Deployment
|
||||||
|
# STACK_COLOR=blue|green. Use scripts/deploy-blue-green.sh to switch.
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
backend-api:
|
backend-api-blue:
|
||||||
build:
|
build:
|
||||||
context: ./veza-backend-api
|
context: ./veza-backend-api
|
||||||
dockerfile: Dockerfile.production
|
dockerfile: Dockerfile.production
|
||||||
image: veza-backend-api:latest
|
image: veza-backend-api:latest
|
||||||
container_name: veza_backend_api
|
container_name: veza_backend_api_blue
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
environment:
|
environment:
|
||||||
- APP_ENV=production
|
- APP_ENV=production
|
||||||
|
- STACK_COLOR=blue
|
||||||
- DATABASE_URL=postgres://${DB_USER:-veza}:${DB_PASS:?DB_PASS must be set}@postgres:5432/${DB_NAME:-veza}?sslmode=require
|
- DATABASE_URL=postgres://${DB_USER:-veza}:${DB_PASS:?DB_PASS must be set}@postgres:5432/${DB_NAME:-veza}?sslmode=require
|
||||||
- REDIS_URL=redis://:${REDIS_PASSWORD:?REDIS_PASSWORD must be set}@redis:6379
|
- REDIS_URL=redis://:${REDIS_PASSWORD:?REDIS_PASSWORD must be set}@redis:6379
|
||||||
- AMQP_URL=amqp://${DB_USER:-veza}:${RABBITMQ_PASS:?RABBITMQ_PASS must be set}@rabbitmq:5672
|
- AMQP_URL=amqp://${DB_USER:-veza}:${RABBITMQ_PASS:?RABBITMQ_PASS must be set}@rabbitmq:5672
|
||||||
|
|
@ -192,14 +194,92 @@ services:
|
||||||
timeout: 5s
|
timeout: 5s
|
||||||
retries: 3
|
retries: 3
|
||||||
|
|
||||||
# Chat Server removed in v0.502 -- chat is now handled by backend-api WebSocket at /api/v1/ws
|
backend-api-green:
|
||||||
|
build:
|
||||||
|
context: ./veza-backend-api
|
||||||
|
dockerfile: Dockerfile.production
|
||||||
|
image: veza-backend-api:latest
|
||||||
|
container_name: veza_backend_api_green
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
- APP_ENV=production
|
||||||
|
- STACK_COLOR=green
|
||||||
|
- DATABASE_URL=postgres://${DB_USER:-veza}:${DB_PASS:?DB_PASS must be set}@postgres:5432/${DB_NAME:-veza}?sslmode=require
|
||||||
|
- REDIS_URL=redis://:${REDIS_PASSWORD:?REDIS_PASSWORD must be set}@redis:6379
|
||||||
|
- AMQP_URL=amqp://${DB_USER:-veza}:${RABBITMQ_PASS:?RABBITMQ_PASS must be set}@rabbitmq:5672
|
||||||
|
- JWT_SECRET=${JWT_SECRET:?JWT_SECRET must be set for production}
|
||||||
|
- COOKIE_SECURE=true
|
||||||
|
- COOKIE_SAME_SITE=strict
|
||||||
|
- COOKIE_HTTP_ONLY=true
|
||||||
|
- CORS_ALLOWED_ORIGINS=${CORS_ORIGINS:-http://veza.fr}
|
||||||
|
- HYPERSWITCH_URL=http://hyperswitch:8080
|
||||||
|
- HYPERSWITCH_API_KEY=${HYPERSWITCH_API_KEY:-}
|
||||||
|
- HYPERSWITCH_WEBHOOK_SECRET=${HYPERSWITCH_WEBHOOK_SECRET:-}
|
||||||
|
- HYPERSWITCH_ENABLED=${HYPERSWITCH_ENABLED:-false}
|
||||||
|
- CHECKOUT_SUCCESS_URL=${CHECKOUT_SUCCESS_URL:-https://veza.fr/purchases}
|
||||||
|
- ENABLE_CLAMAV=true
|
||||||
|
- CLAMAV_REQUIRED=true
|
||||||
|
- CLAMAV_ADDRESS=clamav:3310
|
||||||
|
- AWS_S3_ENDPOINT=http://minio:9000
|
||||||
|
- AWS_S3_BUCKET=veza-files
|
||||||
|
- AWS_ACCESS_KEY_ID=${S3_ACCESS_KEY:?S3_ACCESS_KEY must be set}
|
||||||
|
- AWS_SECRET_ACCESS_KEY=${S3_SECRET_KEY:?S3_SECRET_KEY must be set}
|
||||||
|
- AWS_REGION=${AWS_REGION:-us-east-1}
|
||||||
|
- HLS_STREAMING=true
|
||||||
|
- HLS_STORAGE_DIR=/data/hls
|
||||||
|
volumes:
|
||||||
|
- hls_prod_data:/data/hls
|
||||||
|
depends_on:
|
||||||
|
postgres:
|
||||||
|
condition: service_healthy
|
||||||
|
redis:
|
||||||
|
condition: service_healthy
|
||||||
|
rabbitmq:
|
||||||
|
condition: service_healthy
|
||||||
|
clamav:
|
||||||
|
condition: service_started
|
||||||
|
networks:
|
||||||
|
- veza-network
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:8080/api/v1/health"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 3
|
||||||
|
|
||||||
stream-server:
|
stream-server-blue:
|
||||||
build:
|
build:
|
||||||
context: ./veza-stream-server
|
context: ./veza-stream-server
|
||||||
dockerfile: Dockerfile.production
|
dockerfile: Dockerfile.production
|
||||||
image: veza-stream-server:latest
|
image: veza-stream-server:latest
|
||||||
container_name: veza_stream_server
|
container_name: veza_stream_server_blue
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
- DATABASE_URL=postgres://${DB_USER:-veza}:${DB_PASS:?DB_PASS must be set}@postgres:5432/${DB_NAME:-veza}?sslmode=require
|
||||||
|
- REDIS_URL=redis://:${REDIS_PASSWORD:?REDIS_PASSWORD must be set}@redis:6379
|
||||||
|
- JWT_SECRET=${JWT_SECRET:?JWT_SECRET must be set}
|
||||||
|
- PORT=3001
|
||||||
|
- HLS_OUTPUT_DIR=/data/hls
|
||||||
|
volumes:
|
||||||
|
- hls_prod_data:/data/hls
|
||||||
|
depends_on:
|
||||||
|
postgres:
|
||||||
|
condition: service_healthy
|
||||||
|
redis:
|
||||||
|
condition: service_healthy
|
||||||
|
networks:
|
||||||
|
- veza-network
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:3001/health"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 3
|
||||||
|
|
||||||
|
stream-server-green:
|
||||||
|
build:
|
||||||
|
context: ./veza-stream-server
|
||||||
|
dockerfile: Dockerfile.production
|
||||||
|
image: veza-stream-server:latest
|
||||||
|
container_name: veza_stream_server_green
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
environment:
|
environment:
|
||||||
- DATABASE_URL=postgres://${DB_USER:-veza}:${DB_PASS:?DB_PASS must be set}@postgres:5432/${DB_NAME:-veza}?sslmode=require
|
- DATABASE_URL=postgres://${DB_USER:-veza}:${DB_PASS:?DB_PASS must be set}@postgres:5432/${DB_NAME:-veza}?sslmode=require
|
||||||
|
|
@ -257,20 +337,42 @@ services:
|
||||||
networks:
|
networks:
|
||||||
- veza-network
|
- veza-network
|
||||||
|
|
||||||
web:
|
web-blue:
|
||||||
build:
|
build:
|
||||||
context: ./apps/web
|
context: ./apps/web
|
||||||
dockerfile: Dockerfile.production
|
dockerfile: Dockerfile.production
|
||||||
image: veza-web:latest
|
image: veza-web:latest
|
||||||
container_name: veza_web
|
container_name: veza_web_blue
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
environment:
|
environment:
|
||||||
- VITE_API_URL=http://haproxy/api/v1
|
- VITE_API_URL=http://haproxy/api/v1
|
||||||
- VITE_STREAM_URL=ws://haproxy/stream
|
- VITE_STREAM_URL=ws://haproxy/stream
|
||||||
- VITE_UPLOAD_URL=http://haproxy/api/v1/uploads
|
- VITE_UPLOAD_URL=http://haproxy/api/v1/uploads
|
||||||
depends_on:
|
depends_on:
|
||||||
- backend-api
|
- backend-api-blue
|
||||||
- stream-server
|
- stream-server-blue
|
||||||
|
networks:
|
||||||
|
- veza-network
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:5173"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 3
|
||||||
|
|
||||||
|
web-green:
|
||||||
|
build:
|
||||||
|
context: ./apps/web
|
||||||
|
dockerfile: Dockerfile.production
|
||||||
|
image: veza-web:latest
|
||||||
|
container_name: veza_web_green
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
- VITE_API_URL=http://haproxy/api/v1
|
||||||
|
- VITE_STREAM_URL=ws://haproxy/stream
|
||||||
|
- VITE_UPLOAD_URL=http://haproxy/api/v1/uploads
|
||||||
|
depends_on:
|
||||||
|
- backend-api-green
|
||||||
|
- stream-server-green
|
||||||
networks:
|
networks:
|
||||||
- veza-network
|
- veza-network
|
||||||
healthcheck:
|
healthcheck:
|
||||||
|
|
@ -280,7 +382,7 @@ services:
|
||||||
retries: 3
|
retries: 3
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
# REVERSE PROXY - HAProxy
|
# REVERSE PROXY - HAProxy (Blue-Green)
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
haproxy:
|
haproxy:
|
||||||
image: haproxy:2.8-alpine
|
image: haproxy:2.8-alpine
|
||||||
|
|
@ -298,9 +400,12 @@ services:
|
||||||
- ./config/haproxy/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro
|
- ./config/haproxy/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro
|
||||||
- ./config/ssl:/etc/ssl/veza:ro
|
- ./config/ssl:/etc/ssl/veza:ro
|
||||||
depends_on:
|
depends_on:
|
||||||
- backend-api
|
- backend-api-blue
|
||||||
- stream-server
|
- backend-api-green
|
||||||
- web
|
- stream-server-blue
|
||||||
|
- stream-server-green
|
||||||
|
- web-blue
|
||||||
|
- web-green
|
||||||
networks:
|
networks:
|
||||||
- veza-network
|
- veza-network
|
||||||
healthcheck:
|
healthcheck:
|
||||||
|
|
|
||||||
38
scripts/deploy-blue-green.sh
Executable file
38
scripts/deploy-blue-green.sh
Executable file
|
|
@ -0,0 +1,38 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# Blue-Green deployment switch for Veza production
|
||||||
|
# Usage: ./scripts/deploy-blue-green.sh [blue|green]
|
||||||
|
# Requires: docker, config/haproxy/ directory, veza_haproxy container running
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||||
|
HAPROXY_DIR="$REPO_ROOT/config/haproxy"
|
||||||
|
TARGET="${1:-}"
|
||||||
|
|
||||||
|
if [[ "$TARGET" != "blue" && "$TARGET" != "green" ]]; then
|
||||||
|
echo "Usage: $0 [blue|green]"
|
||||||
|
echo " blue - Route traffic to blue stack (default)"
|
||||||
|
echo " green - Route traffic to green stack"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
CONFIG_SOURCE="$HAPROXY_DIR/haproxy-$TARGET.cfg"
|
||||||
|
CONFIG_DEST="$HAPROXY_DIR/haproxy.cfg"
|
||||||
|
|
||||||
|
if [[ ! -f "$CONFIG_SOURCE" ]]; then
|
||||||
|
echo "Error: Config file not found: $CONFIG_SOURCE"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Switching to $TARGET stack..."
|
||||||
|
cp "$CONFIG_SOURCE" "$CONFIG_DEST"
|
||||||
|
|
||||||
|
# Reload HAProxy (graceful, no connection drop)
|
||||||
|
if docker ps --format '{{.Names}}' | grep -q '^veza_haproxy$'; then
|
||||||
|
docker kill -s HUP veza_haproxy 2>/dev/null || {
|
||||||
|
echo "Warning: Could not send HUP to HAProxy. Try: docker restart veza_haproxy"
|
||||||
|
}
|
||||||
|
echo "HAProxy reloaded. Active stack: $TARGET"
|
||||||
|
else
|
||||||
|
echo "Warning: veza_haproxy container not running. Config updated; start stack to apply."
|
||||||
|
fi
|
||||||
Loading…
Reference in a new issue