feat(ift): EventHub AI Router stack for Zed
FastAPI gateway with A/B/C lane orchestration, LiteLLM proxy config, Swarm stack (postgres, redis, VPN off-by-default), deploy/smoke/audit scripts.
This commit is contained in:
@@ -0,0 +1,243 @@
|
||||
version: "3.8"
|
||||
|
||||
# AI Router stack — IFT Docker Swarm
|
||||
# VPN (vless-proxy, vpn-watchdog) scaled to 0 by default
|
||||
|
||||
networks:
|
||||
ai-internal:
|
||||
driver: overlay
|
||||
internal: true
|
||||
eventhub-ift:
|
||||
external: true
|
||||
name: eventhub-ift-net
|
||||
|
||||
volumes:
|
||||
litellm-postgres-data:
|
||||
uptime-kuma-data:
|
||||
|
||||
configs:
|
||||
litellm_config:
|
||||
file: ./litellm_config.yaml
|
||||
litellm_entrypoint:
|
||||
file: ./scripts/litellm-entrypoint.sh
|
||||
router_entrypoint:
|
||||
file: ./scripts/router-entrypoint.sh
|
||||
routing_config:
|
||||
file: ./config/routing_rules.yaml
|
||||
model_matrix:
|
||||
file: ./config/model_matrix.yaml
|
||||
orchestration_config:
|
||||
file: ./config/orchestration.yaml
|
||||
|
||||
secrets:
|
||||
novita_api_key:
|
||||
external: true
|
||||
litellm_master_key:
|
||||
external: true
|
||||
litellm_salt_key:
|
||||
external: true
|
||||
router_api_key:
|
||||
external: true
|
||||
postgres_password:
|
||||
external: true
|
||||
groq_api_key:
|
||||
external: true
|
||||
gemini_api_key:
|
||||
external: true
|
||||
vless_conf:
|
||||
external: true
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:16-alpine
|
||||
environment:
|
||||
POSTGRES_DB: ${POSTGRES_DB:-litellm}
|
||||
POSTGRES_USER: ${POSTGRES_USER:-litellm}
|
||||
POSTGRES_PASSWORD_FILE: /run/secrets/postgres_password
|
||||
secrets:
|
||||
- postgres_password
|
||||
volumes:
|
||||
- litellm-postgres-data:/var/lib/postgresql/data
|
||||
networks:
|
||||
- ai-internal
|
||||
deploy:
|
||||
replicas: 1
|
||||
restart_policy:
|
||||
condition: on-failure
|
||||
placement:
|
||||
constraints:
|
||||
- node.role == manager
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-litellm} -d ${POSTGRES_DB:-litellm}"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
start_period: 20s
|
||||
|
||||
redis:
|
||||
image: redis:7-alpine
|
||||
command: ["redis-server", "--save", "", "--appendonly", "no"]
|
||||
networks:
|
||||
- ai-internal
|
||||
deploy:
|
||||
replicas: 1
|
||||
restart_policy:
|
||||
condition: on-failure
|
||||
placement:
|
||||
constraints:
|
||||
- node.role == manager
|
||||
healthcheck:
|
||||
test: ["CMD", "redis-cli", "ping"]
|
||||
interval: 10s
|
||||
timeout: 3s
|
||||
retries: 3
|
||||
|
||||
litellm:
|
||||
image: ${LITELLM_IMAGE:-ghcr.io/berriai/litellm:main-v1.96.0-stable}
|
||||
entrypoint: ["/bin/sh", "/entrypoint/litellm-entrypoint.sh"]
|
||||
configs:
|
||||
- source: litellm_config
|
||||
target: /app/config.yaml
|
||||
- source: litellm_entrypoint
|
||||
target: /entrypoint/litellm-entrypoint.sh
|
||||
mode: 0555
|
||||
environment:
|
||||
STORE_MODEL_IN_DB: "False"
|
||||
PROXY_BASE_URL: ${PROXY_BASE_URL:-https://litellm.ift.calentiq.com}
|
||||
FORWARDED_ALLOW_IPS: "*"
|
||||
DISABLE_AIOHTTP_TRANSPORT: ${DISABLE_AIOHTTP_TRANSPORT:-True}
|
||||
USE_AIOHTTP_TRANSPORT: ${USE_AIOHTTP_TRANSPORT:-False}
|
||||
HTTP_PROXY: ${HTTP_PROXY:-}
|
||||
HTTPS_PROXY: ${HTTPS_PROXY:-}
|
||||
NO_PROXY: ${NO_PROXY:-localhost,127.0.0.1,api.novita.ai,novita.ai}
|
||||
POSTGRES_USER: ${POSTGRES_USER:-litellm}
|
||||
POSTGRES_DB: ${POSTGRES_DB:-litellm}
|
||||
secrets:
|
||||
- novita_api_key
|
||||
- litellm_master_key
|
||||
- litellm_salt_key
|
||||
- postgres_password
|
||||
- groq_api_key
|
||||
- gemini_api_key
|
||||
networks:
|
||||
ai-internal:
|
||||
aliases:
|
||||
- litellm
|
||||
eventhub-ift:
|
||||
aliases:
|
||||
- litellm
|
||||
deploy:
|
||||
replicas: 1
|
||||
restart_policy:
|
||||
condition: on-failure
|
||||
delay: 5s
|
||||
update_config:
|
||||
parallelism: 1
|
||||
failure_action: rollback
|
||||
placement:
|
||||
constraints:
|
||||
- node.role == manager
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "wget -q -O- http://127.0.0.1:4000/health/liveliness || exit 1"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 60s
|
||||
|
||||
router:
|
||||
image: ${ROUTER_IMAGE:-git.sabilin.com/eventhub/ai-router-gateway:ift}
|
||||
entrypoint: ["/bin/sh", "/entrypoint/router-entrypoint.sh"]
|
||||
configs:
|
||||
- source: router_entrypoint
|
||||
target: /entrypoint/router-entrypoint.sh
|
||||
mode: 0555
|
||||
- source: routing_config
|
||||
target: /app/config/routing_rules.yaml
|
||||
- source: model_matrix
|
||||
target: /app/config/model_matrix.yaml
|
||||
- source: orchestration_config
|
||||
target: /app/config/orchestration.yaml
|
||||
environment:
|
||||
LITELLM_INTERNAL_URL: http://litellm:4000
|
||||
REDIS_URL: redis://redis:6379/0
|
||||
CONFIG_DIR: /app/config
|
||||
DEFAULT_QUALITY_MODE: ${DEFAULT_QUALITY_MODE:-auto}
|
||||
secrets:
|
||||
- litellm_master_key
|
||||
- router_api_key
|
||||
networks:
|
||||
ai-internal:
|
||||
eventhub-ift:
|
||||
aliases:
|
||||
- ai-router
|
||||
deploy:
|
||||
replicas: 1
|
||||
restart_policy:
|
||||
condition: on-failure
|
||||
placement:
|
||||
constraints:
|
||||
- node.role == manager
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "curl -sf http://127.0.0.1:8000/health || exit 1"]
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
start_period: 20s
|
||||
|
||||
vless-proxy:
|
||||
image: ${VLESS_IMAGE:-ai-router/vless-proxy:local}
|
||||
secrets:
|
||||
- source: vless_conf
|
||||
target: /app/vless.conf
|
||||
networks:
|
||||
- ai-internal
|
||||
deploy:
|
||||
replicas: 0
|
||||
restart_policy:
|
||||
condition: any
|
||||
delay: 5s
|
||||
max_attempts: 0
|
||||
placement:
|
||||
constraints:
|
||||
- node.role == manager
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "wget -q -O- http://127.0.0.1:8080 || exit 1"]
|
||||
interval: 15s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
start_period: 20s
|
||||
|
||||
vpn-watchdog:
|
||||
image: ${WATCHDOG_IMAGE:-ai-router/vpn-watchdog:local}
|
||||
environment:
|
||||
STACK_NAME: ${STACK_NAME:-ai-router}
|
||||
VLESS_PROXY_URL: ${VLESS_PROXY_URL:-http://vless-proxy:8080}
|
||||
CHECK_INTERVAL: "60"
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
networks:
|
||||
- ai-internal
|
||||
deploy:
|
||||
replicas: 0
|
||||
restart_policy:
|
||||
condition: any
|
||||
placement:
|
||||
constraints:
|
||||
- node.role == manager
|
||||
|
||||
uptime-kuma:
|
||||
image: louislam/uptime-kuma:1
|
||||
volumes:
|
||||
- uptime-kuma-data:/app/data
|
||||
networks:
|
||||
ai-internal:
|
||||
eventhub-ift:
|
||||
aliases:
|
||||
- uptime-kuma
|
||||
deploy:
|
||||
replicas: 1
|
||||
restart_policy:
|
||||
condition: on-failure
|
||||
placement:
|
||||
constraints:
|
||||
- node.role == manager
|
||||
Reference in New Issue
Block a user