205 lines
6.0 KiB
YAML
205 lines
6.0 KiB
YAML
version: '3.8'
|
|
|
|
services:
|
|
# BACKBEAT Pulse Service - Leader-elected tempo broadcaster
|
|
# REQ: BACKBEAT-REQ-001 - Single BeatFrame publisher per cluster
|
|
# REQ: BACKBEAT-OPS-001 - One replica prefers leadership
|
|
backbeat-pulse:
|
|
image: anthonyrawlins/backbeat-pulse:v1.0.4
|
|
command: >
|
|
./pulse
|
|
-cluster=chorus-production
|
|
-admin-port=8080
|
|
-raft-bind=0.0.0.0:9000
|
|
-data-dir=/data
|
|
-nats=nats://nats:4222
|
|
-tempo=2
|
|
-bar-length=8
|
|
-log-level=info
|
|
environment:
|
|
# REQ: BACKBEAT-OPS-003 - Configuration via environment variables
|
|
- BACKBEAT_CLUSTER_ID=chorus-production
|
|
- BACKBEAT_TEMPO_BPM=2 # 30-second beats for production
|
|
- BACKBEAT_BAR_LENGTH=8 # 4-minute windows
|
|
- BACKBEAT_PHASE_PLAN=plan,work,review
|
|
- BACKBEAT_NATS_URL=nats://nats:4222
|
|
- BACKBEAT_MIN_BPM=1 # 60-second beats minimum
|
|
- BACKBEAT_MAX_BPM=60 # 1-second beats maximum
|
|
- BACKBEAT_LOG_LEVEL=info
|
|
|
|
# REQ: BACKBEAT-OPS-002 - Health probes for liveness/readiness
|
|
healthcheck:
|
|
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:8080/healthz"]
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 3
|
|
start_period: 60s
|
|
|
|
deploy:
|
|
replicas: 1 # Single leader with automatic failover
|
|
restart_policy:
|
|
condition: on-failure
|
|
delay: 30s # Wait longer for NATS to be ready
|
|
max_attempts: 5
|
|
window: 120s
|
|
update_config:
|
|
parallelism: 1
|
|
delay: 30s # Wait for leader election
|
|
failure_action: rollback
|
|
monitor: 60s
|
|
order: start-first
|
|
placement:
|
|
preferences:
|
|
- spread: node.hostname
|
|
constraints:
|
|
- node.hostname != rosewood # Avoid intermittent gaming PC
|
|
resources:
|
|
limits:
|
|
memory: 256M
|
|
cpus: '0.5'
|
|
reservations:
|
|
memory: 128M
|
|
cpus: '0.25'
|
|
# Traefik routing for admin API
|
|
labels:
|
|
- traefik.enable=true
|
|
- traefik.http.routers.backbeat-pulse.rule=Host(`backbeat-pulse.chorus.services`)
|
|
- traefik.http.routers.backbeat-pulse.tls=true
|
|
- traefik.http.routers.backbeat-pulse.tls.certresolver=letsencryptresolver
|
|
- traefik.http.services.backbeat-pulse.loadbalancer.server.port=8080
|
|
|
|
networks:
|
|
- backbeat-net
|
|
- tengig # External network for Traefik
|
|
|
|
# Container logging
|
|
logging:
|
|
driver: "json-file"
|
|
options:
|
|
max-size: "10m"
|
|
max-file: "3"
|
|
tag: "backbeat-pulse/{{.Name}}/{{.ID}}"
|
|
|
|
# BACKBEAT Reverb Service - StatusClaim aggregator
|
|
# REQ: BACKBEAT-REQ-020 - Subscribe to INT-B and group by window_id
|
|
# REQ: BACKBEAT-OPS-001 - Reverb can scale stateless
|
|
backbeat-reverb:
|
|
image: anthonyrawlins/backbeat-reverb:v1.0.1
|
|
command: >
|
|
./reverb
|
|
-cluster=chorus-production
|
|
-nats=nats://nats:4222
|
|
-bar-length=8
|
|
-log-level=info
|
|
environment:
|
|
# REQ: BACKBEAT-OPS-003 - Configuration matching pulse service
|
|
- BACKBEAT_CLUSTER_ID=chorus-production
|
|
- BACKBEAT_NATS_URL=nats://nats:4222
|
|
- BACKBEAT_LOG_LEVEL=info
|
|
- BACKBEAT_WINDOW_TTL=300s # 5-minute cleanup
|
|
- BACKBEAT_MAX_WINDOWS=100 # Memory limit
|
|
|
|
# REQ: BACKBEAT-OPS-002 - Health probes for orchestration
|
|
healthcheck:
|
|
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:8080/healthz"]
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 3
|
|
start_period: 60s
|
|
|
|
deploy:
|
|
replicas: 2 # Stateless, can scale horizontally
|
|
restart_policy:
|
|
condition: on-failure
|
|
delay: 10s
|
|
max_attempts: 3
|
|
window: 120s
|
|
update_config:
|
|
parallelism: 1
|
|
delay: 15s
|
|
failure_action: rollback
|
|
monitor: 45s
|
|
order: start-first
|
|
placement:
|
|
preferences:
|
|
- spread: node.hostname
|
|
constraints:
|
|
- node.hostname != rosewood
|
|
resources:
|
|
limits:
|
|
memory: 512M # Larger for window aggregation
|
|
cpus: '1.0'
|
|
reservations:
|
|
memory: 256M
|
|
cpus: '0.5'
|
|
# Traefik routing for admin API
|
|
labels:
|
|
- traefik.enable=true
|
|
- traefik.http.routers.backbeat-reverb.rule=Host(`backbeat-reverb.chorus.services`)
|
|
- traefik.http.routers.backbeat-reverb.tls=true
|
|
- traefik.http.routers.backbeat-reverb.tls.certresolver=letsencryptresolver
|
|
- traefik.http.services.backbeat-reverb.loadbalancer.server.port=8080
|
|
|
|
networks:
|
|
- backbeat-net
|
|
- tengig # External network for Traefik
|
|
|
|
# Container logging
|
|
logging:
|
|
driver: "json-file"
|
|
options:
|
|
max-size: "10m"
|
|
max-file: "3"
|
|
tag: "backbeat-reverb/{{.Name}}/{{.ID}}"
|
|
|
|
# NATS Message Broker - Use existing or deploy dedicated instance
|
|
# REQ: BACKBEAT-INT-001 - Topics via NATS for at-least-once delivery
|
|
nats:
|
|
image: nats:2.9-alpine
|
|
command: ["--jetstream"]
|
|
|
|
deploy:
|
|
replicas: 1
|
|
restart_policy:
|
|
condition: on-failure
|
|
delay: 10s
|
|
max_attempts: 3
|
|
window: 120s
|
|
placement:
|
|
preferences:
|
|
- spread: node.hostname
|
|
constraints:
|
|
- node.hostname != rosewood
|
|
resources:
|
|
limits:
|
|
memory: 256M
|
|
cpus: '0.5'
|
|
reservations:
|
|
memory: 128M
|
|
cpus: '0.25'
|
|
|
|
networks:
|
|
- backbeat-net
|
|
|
|
# Container logging
|
|
logging:
|
|
driver: "json-file"
|
|
options:
|
|
max-size: "10m"
|
|
max-file: "3"
|
|
tag: "nats/{{.Name}}/{{.ID}}"
|
|
|
|
# Network configuration
|
|
networks:
|
|
tengig:
|
|
external: true # External network for Traefik
|
|
|
|
backbeat-net:
|
|
driver: overlay
|
|
attachable: true # Allow external containers to connect
|
|
ipam:
|
|
config:
|
|
- subnet: 10.202.0.0/24
|
|
|
|
# Persistent storage
|
|
# volumes: |