feat: Compose and Nomad deployment
This commit is contained in:
7
.gitignore
vendored
Normal file
7
.gitignore
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
.env
|
||||||
|
*.log
|
||||||
|
docker-compose.override.yml
|
||||||
|
data/
|
||||||
|
nomad-data/
|
||||||
|
nomad.log
|
||||||
|
alloc_mounts/
|
||||||
123
Makefile
Normal file
123
Makefile
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
.PHONY: help build push up down logs ps restart clean nomad-start nomad-stop nomad-status nomad-ui nomad-job-run nomad-job-stop nomad-logs
|
||||||
|
|
||||||
|
# Default target
|
||||||
|
help:
|
||||||
|
@echo "SPORE Deployment Makefile"
|
||||||
|
@echo ""
|
||||||
|
@echo "Targets:"
|
||||||
|
@echo " make build - Build all Docker images"
|
||||||
|
@echo " make push - Build and push all Docker images to Docker Hub"
|
||||||
|
@echo " make up - Start all services"
|
||||||
|
@echo " make down - Stop all services"
|
||||||
|
@echo " make logs - View logs from all services"
|
||||||
|
@echo " make ps - Show service status"
|
||||||
|
@echo " make restart - Restart all services"
|
||||||
|
@echo " make clean - Stop services and remove data directory"
|
||||||
|
@echo " make gateway-logs - View gateway logs"
|
||||||
|
@echo " make ledlab-logs - View LEDLab logs"
|
||||||
|
@echo " make registry-logs - View registry logs"
|
||||||
|
@echo " make ui-logs - View UI logs"
|
||||||
|
@echo " make mqtt-logs - View MQTT broker logs"
|
||||||
|
@echo ""
|
||||||
|
@echo "Nomad targets:"
|
||||||
|
@echo " make nomad-start - Start Nomad locally"
|
||||||
|
@echo " make nomad-stop - Stop Nomad"
|
||||||
|
@echo " make nomad-status - Check Nomad status"
|
||||||
|
@echo " make nomad-ui - Open Nomad UI in browser"
|
||||||
|
@echo " make nomad-job-run - Deploy SPORE job to Nomad"
|
||||||
|
@echo " make nomad-job-stop - Stop SPORE job in Nomad"
|
||||||
|
@echo " make nomad-logs - View Nomad job logs"
|
||||||
|
|
||||||
|
# Build all images
|
||||||
|
build:
|
||||||
|
docker compose build
|
||||||
|
|
||||||
|
# Build and push all images to Docker Hub
|
||||||
|
push:
|
||||||
|
@echo "Building and pushing all SPORE images to Docker Hub..."
|
||||||
|
@echo "Building spore-gateway..."
|
||||||
|
@cd ../spore-gateway && make docker-build && make docker-push
|
||||||
|
@echo "Building spore-registry..."
|
||||||
|
@cd ../spore-registry && make docker-build && make docker-push
|
||||||
|
@echo "Building spore-ledlab..."
|
||||||
|
@cd ../spore-ledlab && make docker-build && make docker-push
|
||||||
|
@echo "Building spore-ui..."
|
||||||
|
@cd ../spore-ui && make docker-build && make docker-push
|
||||||
|
@echo "All images pushed successfully!"
|
||||||
|
|
||||||
|
# Start all services
|
||||||
|
up:
|
||||||
|
docker compose up -d
|
||||||
|
|
||||||
|
# Stop all services
|
||||||
|
down:
|
||||||
|
docker compose down
|
||||||
|
|
||||||
|
# View logs
|
||||||
|
logs:
|
||||||
|
docker compose logs -f
|
||||||
|
|
||||||
|
# Show service status
|
||||||
|
ps:
|
||||||
|
docker compose ps
|
||||||
|
|
||||||
|
# Restart all services
|
||||||
|
restart:
|
||||||
|
docker compose restart
|
||||||
|
|
||||||
|
# Clean (stop and remove data)
|
||||||
|
clean:
|
||||||
|
@echo "Stopping services..."
|
||||||
|
@docker compose down
|
||||||
|
@echo "Removing data directory..."
|
||||||
|
@rm -rf ./data/
|
||||||
|
@echo "Clean complete"
|
||||||
|
|
||||||
|
# Service-specific logs
|
||||||
|
gateway-logs:
|
||||||
|
docker compose logs -f gateway
|
||||||
|
|
||||||
|
ledlab-logs:
|
||||||
|
docker compose logs -f ledlab
|
||||||
|
|
||||||
|
registry-logs:
|
||||||
|
docker compose logs -f registry
|
||||||
|
|
||||||
|
ui-logs:
|
||||||
|
docker compose logs -f ui
|
||||||
|
|
||||||
|
mqtt-logs:
|
||||||
|
docker compose logs -f mqtt
|
||||||
|
|
||||||
|
# Nomad targets
|
||||||
|
nomad-start:
|
||||||
|
@echo "Starting Nomad..."
|
||||||
|
@mkdir -p nomad-data
|
||||||
|
@sudo nomad agent -dev -config=./config/nomad/nomad.hcl -data-dir=$(PWD)/nomad-data
|
||||||
|
@sleep 2
|
||||||
|
@echo "Nomad started at http://localhost:4646"
|
||||||
|
|
||||||
|
nomad-stop:
|
||||||
|
@echo "Stopping Nomad..."
|
||||||
|
@pkill -f "nomad agent" || true
|
||||||
|
@echo "Stopped"
|
||||||
|
|
||||||
|
nomad-status:
|
||||||
|
@nomad status || echo "Nomad not running"
|
||||||
|
|
||||||
|
nomad-ui:
|
||||||
|
@echo "Opening Nomad UI at http://localhost:4646"
|
||||||
|
@xdg-open http://localhost:4646 2>/dev/null || open http://localhost:4646 2>/dev/null || echo "Please open http://localhost:4646 in your browser"
|
||||||
|
|
||||||
|
nomad-job-run:
|
||||||
|
@echo "Deploying SPORE job to Nomad..."
|
||||||
|
@nomad job run ./nomad/spore.hcl
|
||||||
|
|
||||||
|
nomad-job-stop:
|
||||||
|
@echo "Stopping SPORE job in Nomad..."
|
||||||
|
@nomad job stop spore
|
||||||
|
|
||||||
|
nomad-logs:
|
||||||
|
@echo "Showing logs for SPORE jobs..."
|
||||||
|
@nomad job logs spore
|
||||||
|
|
||||||
383
README.md
Normal file
383
README.md
Normal file
@@ -0,0 +1,383 @@
|
|||||||
|
# SPORE Deployment
|
||||||
|
|
||||||
|
Complete deployment configurations for running the SPORE stack with Docker Compose or HashiCorp Nomad.
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
This repository provides two deployment options:
|
||||||
|
|
||||||
|
1. **Docker Compose** - Simple deployment with docker-compose for development and production
|
||||||
|
2. **Nomad** - Production-ready orchestration using HashiCorp Nomad
|
||||||
|
|
||||||
|
Both deployments include all SPORE services with proper networking, volumes, and service discovery.
|
||||||
|
|
||||||
|
## Services
|
||||||
|
|
||||||
|
- **mosquitto**: MQTT broker for message routing (port 1883, 9001)
|
||||||
|
- **spore-gateway**: Node discovery and WebSocket gateway with MQTT integration (port 3001, UDP 4210)
|
||||||
|
- **spore-registry**: Firmware registry service (port 8090)
|
||||||
|
- **spore-ledlab**: LED animation studio (port 8080)
|
||||||
|
- **spore-ui**: Web UI for cluster management (port 3000)
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
### For Docker Compose
|
||||||
|
- Docker and Docker Compose installed
|
||||||
|
- Available ports: 1883, 3000, 3001, 4210, 8080, 8090
|
||||||
|
|
||||||
|
### For Nomad
|
||||||
|
- HashiCorp Nomad installed
|
||||||
|
- Docker installed (Nomad uses Docker to run containers)
|
||||||
|
- Available ports: 1883, 3000, 3001, 4210, 8080, 8090, 4646
|
||||||
|
|
||||||
|
## Deployment Options
|
||||||
|
|
||||||
|
### Option 1: Docker Compose (Recommended for development)
|
||||||
|
|
||||||
|
Simple, single-node deployment with docker-compose.
|
||||||
|
|
||||||
|
#### Quick Start
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd spore-deployment
|
||||||
|
|
||||||
|
# Start all services
|
||||||
|
docker compose up -d
|
||||||
|
|
||||||
|
# View logs
|
||||||
|
docker compose logs -f
|
||||||
|
|
||||||
|
# Stop all services
|
||||||
|
docker compose down
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Services Access
|
||||||
|
|
||||||
|
- **Web UI**: http://localhost:3000
|
||||||
|
- **LED Lab**: http://localhost:8080
|
||||||
|
- **Registry API**: http://localhost:8090
|
||||||
|
- **Gateway API**: http://localhost:3001
|
||||||
|
- **MQTT Broker**: tcp://localhost:1883 (WebSocket: ws://localhost:9001)
|
||||||
|
|
||||||
|
#### Data Storage
|
||||||
|
|
||||||
|
All data is persisted in local `./data/` directory:
|
||||||
|
- Registry data: `./data/registry`
|
||||||
|
- MQTT data: `./data/mqtt/`
|
||||||
|
|
||||||
|
#### Management
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# View logs for all services
|
||||||
|
make logs
|
||||||
|
|
||||||
|
# View logs for specific service
|
||||||
|
make gateway-logs
|
||||||
|
make registry-logs
|
||||||
|
make ledlab-logs
|
||||||
|
make ui-logs
|
||||||
|
make mqtt-logs
|
||||||
|
|
||||||
|
# Restart services
|
||||||
|
make restart
|
||||||
|
|
||||||
|
# Clean (stop and remove all data)
|
||||||
|
make clean
|
||||||
|
```
|
||||||
|
|
||||||
|
### Option 2: Nomad (Recommended for production)
|
||||||
|
|
||||||
|
Distributed deployment with HashiCorp Nomad.
|
||||||
|
|
||||||
|
#### Quick Start
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd spore-deployment
|
||||||
|
|
||||||
|
# Start Nomad in dev mode
|
||||||
|
make nomad-start
|
||||||
|
|
||||||
|
# Build Docker images first
|
||||||
|
cd ../spore-gateway && make docker-build
|
||||||
|
cd ../spore-ledlab && make docker-build
|
||||||
|
cd ../spore-registry && make docker-build
|
||||||
|
cd ../spore-ui && make docker-build
|
||||||
|
|
||||||
|
# Deploy the job
|
||||||
|
make nomad-job-run
|
||||||
|
|
||||||
|
# View status
|
||||||
|
make nomad-status
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Services Access
|
||||||
|
|
||||||
|
Same ports as Docker Compose deployment.
|
||||||
|
|
||||||
|
#### Nomad UI
|
||||||
|
|
||||||
|
Access the Nomad UI at http://localhost:4646 to manage and monitor jobs.
|
||||||
|
|
||||||
|
#### Management
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# View Nomad UI
|
||||||
|
make nomad-ui
|
||||||
|
|
||||||
|
# View job logs
|
||||||
|
make nomad-logs
|
||||||
|
|
||||||
|
# Stop the job
|
||||||
|
make nomad-job-stop
|
||||||
|
|
||||||
|
# Restart Nomad
|
||||||
|
make nomad-stop
|
||||||
|
make nomad-start
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Nomad Configuration
|
||||||
|
|
||||||
|
Nomad configuration is in `config/nomad/nomad.hcl`:
|
||||||
|
- Dev mode with single agent
|
||||||
|
- Docker driver enabled
|
||||||
|
- Host networking for all services
|
||||||
|
- UI enabled on port 4646
|
||||||
|
|
||||||
|
See [nomad/README.md](./nomad/README.md) for detailed Nomad documentation.
|
||||||
|
|
||||||
|
## Common Tasks
|
||||||
|
|
||||||
|
### Building Images
|
||||||
|
|
||||||
|
Both deployment methods require Docker images to be built first.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Using make in each project
|
||||||
|
cd ../spore-gateway && make docker-build
|
||||||
|
cd ../spore-ledlab && make docker-build
|
||||||
|
cd ../spore-registry && make docker-build
|
||||||
|
cd ../spore-ui && make docker-build
|
||||||
|
|
||||||
|
# Or build and push all at once from deployment directory
|
||||||
|
make push
|
||||||
|
```
|
||||||
|
|
||||||
|
### Environment Variables
|
||||||
|
|
||||||
|
#### Docker Compose
|
||||||
|
|
||||||
|
Create a `.env` file to override defaults:
|
||||||
|
|
||||||
|
```env
|
||||||
|
LOG_LEVEL=debug
|
||||||
|
MATRIX_WIDTH=32
|
||||||
|
MATRIX_HEIGHT=32
|
||||||
|
FPS=30
|
||||||
|
```
|
||||||
|
|
||||||
|
Then run:
|
||||||
|
```bash
|
||||||
|
docker compose --env-file .env up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Nomad
|
||||||
|
|
||||||
|
Edit `nomad/spore.hcl` to modify environment variables or resource allocations.
|
||||||
|
|
||||||
|
### Data Management
|
||||||
|
|
||||||
|
#### Backup
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Backup all data
|
||||||
|
tar czf spore-backup.tar.gz ./data/
|
||||||
|
|
||||||
|
# Backup registry only
|
||||||
|
tar czf registry-backup.tar.gz ./data/registry/
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Restore
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Restore all data
|
||||||
|
tar xzf spore-backup.tar.gz
|
||||||
|
|
||||||
|
# Restore registry only
|
||||||
|
tar xzf registry-backup.tar.gz
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Reset Data
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Docker Compose
|
||||||
|
make clean
|
||||||
|
|
||||||
|
# Nomad
|
||||||
|
rm -rf nomad-data/
|
||||||
|
```
|
||||||
|
|
||||||
|
## Logs
|
||||||
|
|
||||||
|
### Docker Compose
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# All services
|
||||||
|
docker compose logs -f
|
||||||
|
|
||||||
|
# Specific service
|
||||||
|
docker compose logs -f gateway
|
||||||
|
docker compose logs -f registry
|
||||||
|
```
|
||||||
|
|
||||||
|
### Nomad
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# All job logs
|
||||||
|
make nomad-logs
|
||||||
|
|
||||||
|
# Specific task
|
||||||
|
nomad alloc logs <alloc-id> <task-name>
|
||||||
|
|
||||||
|
# Follow logs
|
||||||
|
nomad alloc logs -f <alloc-id> <task-name>
|
||||||
|
```
|
||||||
|
|
||||||
|
## MQTT Integration
|
||||||
|
|
||||||
|
Both deployments enable MQTT integration for the gateway service.
|
||||||
|
|
||||||
|
### Publishing to MQTT
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Using mosquitto_pub
|
||||||
|
mosquitto_pub -h localhost -t "spore/cluster/broadcast" -m '{"command":"update"}'
|
||||||
|
|
||||||
|
# Send to specific node
|
||||||
|
mosquitto_pub -h localhost -t "spore/nodes/192.168.1.100/command" -m '{"action":"update"}'
|
||||||
|
```
|
||||||
|
|
||||||
|
### Monitoring MQTT
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Subscribe to all SPORE topics
|
||||||
|
mosquitto_sub -h localhost -t "spore/#" -v
|
||||||
|
|
||||||
|
# Watch specific topic
|
||||||
|
mosquitto_sub -h localhost -t "spore/cluster/status" -v
|
||||||
|
```
|
||||||
|
|
||||||
|
### MQTT Authentication
|
||||||
|
|
||||||
|
Enable authentication by setting environment variables:
|
||||||
|
|
||||||
|
**Docker Compose:**
|
||||||
|
```yaml
|
||||||
|
gateway:
|
||||||
|
environment:
|
||||||
|
- MQTT_SERVER=tcp://localhost:1883
|
||||||
|
- MQTT_USER=username
|
||||||
|
- MQTT_PASSWORD=password
|
||||||
|
```
|
||||||
|
|
||||||
|
**Nomad:**
|
||||||
|
Edit `nomad/spore.hcl` to add MQTT_USER and MQTT_PASSWORD env vars.
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Port Conflicts
|
||||||
|
|
||||||
|
If ports are already in use:
|
||||||
|
|
||||||
|
**Docker Compose:** Edit port mappings in `docker-compose.yml`
|
||||||
|
|
||||||
|
**Nomad:** Edit ports in `nomad/spore.hcl`
|
||||||
|
|
||||||
|
### Services Not Starting
|
||||||
|
|
||||||
|
**Docker Compose:**
|
||||||
|
```bash
|
||||||
|
# Check logs
|
||||||
|
make logs
|
||||||
|
|
||||||
|
# Check container status
|
||||||
|
docker compose ps
|
||||||
|
```
|
||||||
|
|
||||||
|
**Nomad:**
|
||||||
|
```bash
|
||||||
|
# Check job status
|
||||||
|
make nomad-status
|
||||||
|
|
||||||
|
# Check allocation logs
|
||||||
|
nomad alloc logs <alloc-id> <task-name>
|
||||||
|
|
||||||
|
# Check allocation status
|
||||||
|
nomad alloc status <alloc-id>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Network Issues
|
||||||
|
|
||||||
|
Both deployments use host networking for proper UDP broadcast support. If services can't communicate:
|
||||||
|
|
||||||
|
1. Check firewall settings
|
||||||
|
2. Verify ports are not blocked
|
||||||
|
3. Check service logs for connection errors
|
||||||
|
|
||||||
|
### Images Not Found
|
||||||
|
|
||||||
|
Ensure Docker images are built before deploying:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Build all images
|
||||||
|
make push
|
||||||
|
|
||||||
|
# Or build individually
|
||||||
|
cd ../spore-gateway && make docker-build
|
||||||
|
cd ../spore-ledlab && make docker-build
|
||||||
|
cd ../spore-registry && make docker-build
|
||||||
|
cd ../spore-ui && make docker-build
|
||||||
|
```
|
||||||
|
|
||||||
|
## Production Deployment
|
||||||
|
|
||||||
|
### Docker Compose
|
||||||
|
|
||||||
|
For production, consider:
|
||||||
|
1. Using environment-specific configuration files
|
||||||
|
2. Setting up proper logging aggregation
|
||||||
|
3. Using Docker secrets for sensitive data
|
||||||
|
4. Implementing health checks
|
||||||
|
5. Setting resource limits
|
||||||
|
|
||||||
|
### Nomad
|
||||||
|
|
||||||
|
For production deployment:
|
||||||
|
1. Use a multi-node Nomad cluster
|
||||||
|
2. Enable ACLs for security
|
||||||
|
3. Configure TLS for all connections
|
||||||
|
4. Use external storage for volumes
|
||||||
|
5. Set up proper monitoring and alerting
|
||||||
|
6. Configure auto-scaling based on load
|
||||||
|
|
||||||
|
## Comparing Deployment Options
|
||||||
|
|
||||||
|
| Feature | Docker Compose | Nomad |
|
||||||
|
|---------|---------------|-------|
|
||||||
|
| Ease of setup | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ |
|
||||||
|
| Scalability | ⭐⭐ | ⭐⭐⭐⭐⭐ |
|
||||||
|
| Multi-node | No | Yes |
|
||||||
|
| Service discovery | Manual | Built-in |
|
||||||
|
| Rolling updates | Manual | Automatic |
|
||||||
|
| Resource management | Basic | Advanced |
|
||||||
|
| Production-ready | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
|
||||||
|
|
||||||
|
**Recommendation:**
|
||||||
|
- Use **Docker Compose** for development, testing, or single-node deployments
|
||||||
|
- Use **Nomad** for production, multi-node clusters, or when you need advanced orchestration features
|
||||||
|
|
||||||
|
## Additional Resources
|
||||||
|
|
||||||
|
- [SPORE Documentation](../spore/README.md)
|
||||||
|
- [Nomad Deployment Guide](./nomad/README.md)
|
||||||
|
- [Docker Compose Documentation](https://docs.docker.com/compose/)
|
||||||
|
- [Nomad Documentation](https://www.nomadproject.io/docs)
|
||||||
10
config/mqtt/mosquitto.conf
Normal file
10
config/mqtt/mosquitto.conf
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
# -----------------------------
|
||||||
|
# Basic Mosquitto configuration
|
||||||
|
# -----------------------------
|
||||||
|
listener 1883
|
||||||
|
allow_anonymous true
|
||||||
|
|
||||||
|
# (Optional) WebSocket listener if you exposed port 9001 above
|
||||||
|
# listener 9001
|
||||||
|
# protocol websockets
|
||||||
|
# allow_anonymous true
|
||||||
60
config/nomad/nomad.hcl
Normal file
60
config/nomad/nomad.hcl
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
# Nomad configuration for local development
|
||||||
|
# This runs a single Nomad instance (both server and client)
|
||||||
|
# No Consul required - using Nomad's built-in service discovery
|
||||||
|
|
||||||
|
# Data directory (use absolute path)
|
||||||
|
data_dir = "nomad-data"
|
||||||
|
|
||||||
|
# Server configuration
|
||||||
|
server {
|
||||||
|
enabled = true
|
||||||
|
bootstrap_expect = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Client configuration
|
||||||
|
client {
|
||||||
|
enabled = true
|
||||||
|
|
||||||
|
# Host network for services that need it
|
||||||
|
host_network "host" {
|
||||||
|
cidr = "127.0.0.1/32"
|
||||||
|
reserved_ports = "3000,3001,3002,4210,8080,8090,1883,9001"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Volumes are now handled via Docker volumes
|
||||||
|
}
|
||||||
|
|
||||||
|
# Plugin configuration (for Docker driver)
|
||||||
|
plugin "docker" {
|
||||||
|
config {
|
||||||
|
endpoint = "unix:///var/run/docker.sock"
|
||||||
|
allow_privileged = true
|
||||||
|
volumes {
|
||||||
|
enabled = true
|
||||||
|
selinuxlabel = "z"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Enable UI
|
||||||
|
ui {
|
||||||
|
enabled = true
|
||||||
|
}
|
||||||
|
|
||||||
|
# Logging
|
||||||
|
log_level = "INFO"
|
||||||
|
|
||||||
|
# Addresses
|
||||||
|
addresses {
|
||||||
|
http = "127.0.0.1"
|
||||||
|
rpc = "127.0.0.1"
|
||||||
|
serf = "127.0.0.1"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Ports
|
||||||
|
ports {
|
||||||
|
http = 4646
|
||||||
|
rpc = 4647
|
||||||
|
serf = 4648
|
||||||
|
}
|
||||||
|
|
||||||
105
docker-compose.yml
Normal file
105
docker-compose.yml
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
services:
|
||||||
|
mqtt:
|
||||||
|
image: eclipse-mosquitto:2.0
|
||||||
|
container_name: spore-mqtt
|
||||||
|
ports:
|
||||||
|
- "1883:1883"
|
||||||
|
- "9001:9001"
|
||||||
|
volumes:
|
||||||
|
- ./data/mqtt/data:/mosquitto/data
|
||||||
|
- ./config/mqtt/mosquitto.conf:/mosquitto/config/mosquitto.conf
|
||||||
|
restart: unless-stopped
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "nc -z localhost 1883 || exit 1"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 3
|
||||||
|
|
||||||
|
gateway:
|
||||||
|
build:
|
||||||
|
context: ../spore-gateway
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
image: wirelos/spore-gateway:latest
|
||||||
|
container_name: spore-gateway
|
||||||
|
network_mode: host
|
||||||
|
environment:
|
||||||
|
- LOG_LEVEL=info
|
||||||
|
- MQTT_SERVER=tcp://localhost:1883
|
||||||
|
- MQTT_USER=
|
||||||
|
- MQTT_PASSWORD=
|
||||||
|
depends_on:
|
||||||
|
mqtt:
|
||||||
|
condition: service_healthy
|
||||||
|
restart: unless-stopped
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "nc -z localhost 3001 || exit 1"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 3
|
||||||
|
start_period: 40s
|
||||||
|
|
||||||
|
registry:
|
||||||
|
build:
|
||||||
|
context: ../spore-registry
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
image: wirelos/spore-registry:latest
|
||||||
|
container_name: spore-registry
|
||||||
|
ports:
|
||||||
|
- "3002:3002"
|
||||||
|
volumes:
|
||||||
|
- ./data/registry:/data/registry
|
||||||
|
environment:
|
||||||
|
- REGISTRY_PATH=/data/registry
|
||||||
|
restart: unless-stopped
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "wget", "-q", "--spider", "http://localhost:3002/health"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 3
|
||||||
|
start_period: 40s
|
||||||
|
|
||||||
|
ledlab:
|
||||||
|
build:
|
||||||
|
context: ../spore-ledlab
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
image: wirelos/spore-ledlab:latest
|
||||||
|
container_name: spore-ledlab
|
||||||
|
network_mode: host
|
||||||
|
environment:
|
||||||
|
- PORT=8080
|
||||||
|
- UDP_PORT=4210
|
||||||
|
- GATEWAY_URL=http://localhost:3001
|
||||||
|
- FILTER_APP_LABEL=pixelstream
|
||||||
|
- MATRIX_WIDTH=16
|
||||||
|
- MATRIX_HEIGHT=16
|
||||||
|
- FPS=20
|
||||||
|
depends_on:
|
||||||
|
- gateway
|
||||||
|
restart: unless-stopped
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "wget", "-q", "--spider", "http://localhost:8080/api/status"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 3
|
||||||
|
start_period: 40s
|
||||||
|
|
||||||
|
ui:
|
||||||
|
build:
|
||||||
|
context: ../spore-ui
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
image: wirelos/spore-ui:latest
|
||||||
|
container_name: spore-ui
|
||||||
|
ports:
|
||||||
|
- "3000:3000"
|
||||||
|
environment:
|
||||||
|
- PORT=3000
|
||||||
|
depends_on:
|
||||||
|
- gateway
|
||||||
|
restart: unless-stopped
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "wget", "-q", "--spider", "http://localhost:3000/health"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 3
|
||||||
|
start_period: 40s
|
||||||
|
|
||||||
234
nomad/README.md
Normal file
234
nomad/README.md
Normal file
@@ -0,0 +1,234 @@
|
|||||||
|
# SPORE Nomad Deployment
|
||||||
|
|
||||||
|
This directory contains Nomad job specifications for deploying the SPORE stack on HashiCorp Nomad.
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
1. **Install Nomad**: https://www.nomadproject.io/downloads
|
||||||
|
2. **Docker**: Nomad uses Docker to run containers
|
||||||
|
|
||||||
|
Note: Consul is not required. This setup uses Nomad's built-in service discovery.
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
### 1. Start Nomad
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make nomad-start
|
||||||
|
```
|
||||||
|
|
||||||
|
This starts:
|
||||||
|
- Nomad at http://localhost:4646
|
||||||
|
|
||||||
|
### 2. Build Docker Images
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Build all images
|
||||||
|
cd ../spore-gateway && make docker-build
|
||||||
|
cd ../spore-ledlab && make docker-build
|
||||||
|
cd ../spore-registry && make docker-build
|
||||||
|
cd ../spore-ui && make docker-build
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Deploy the Job
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make nomad-job-run
|
||||||
|
```
|
||||||
|
|
||||||
|
Or manually:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
nomad job run spore.hcl
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Check Status
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check job status
|
||||||
|
make nomad-status
|
||||||
|
|
||||||
|
# Or use Nomad UI
|
||||||
|
make nomad-ui
|
||||||
|
```
|
||||||
|
|
||||||
|
## Job Specification
|
||||||
|
|
||||||
|
The `spore.hcl` file defines 5 service groups:
|
||||||
|
|
||||||
|
1. **mqtt** - MQTT broker (Mosquitto)
|
||||||
|
2. **gateway** - Node discovery and WebSocket gateway
|
||||||
|
3. **registry** - Firmware registry service
|
||||||
|
4. **ledlab** - LED animation studio
|
||||||
|
5. **ui** - Web UI for cluster management
|
||||||
|
|
||||||
|
### Networking
|
||||||
|
|
||||||
|
- **MQTT, Gateway, LEDLab**: Use host networking for UDP/WebSocket
|
||||||
|
- **Registry, UI**: Use bridge networking with mapped ports
|
||||||
|
|
||||||
|
### Resources
|
||||||
|
|
||||||
|
Each service has appropriate CPU and memory allocations:
|
||||||
|
- MQTT: 100 CPU, 128 MB RAM
|
||||||
|
- Gateway: 200 CPU, 256 MB RAM
|
||||||
|
- Registry: 200 CPU, 256 MB RAM
|
||||||
|
- LEDLab: 300 CPU, 512 MB RAM
|
||||||
|
- UI: 100 CPU, 256 MB RAM
|
||||||
|
|
||||||
|
## Management
|
||||||
|
|
||||||
|
### View Logs
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make nomad-logs
|
||||||
|
```
|
||||||
|
|
||||||
|
Or for specific task:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
nomad alloc logs <alloc-id> <task-name>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Stop/Start Job
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Stop
|
||||||
|
make nomad-job-stop
|
||||||
|
|
||||||
|
# Start
|
||||||
|
make nomad-job-run
|
||||||
|
```
|
||||||
|
|
||||||
|
### Scale Services
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Scale a specific group
|
||||||
|
nomad job scale -group mqtt -count 1 spore
|
||||||
|
```
|
||||||
|
|
||||||
|
### Update Job
|
||||||
|
|
||||||
|
Edit `spore.hcl` and run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make nomad-job-run
|
||||||
|
```
|
||||||
|
|
||||||
|
Nomad will perform a rolling update if the job is running.
|
||||||
|
|
||||||
|
## Service Discovery
|
||||||
|
|
||||||
|
Nomad uses built-in service discovery. Services are discoverable via Nomad's internal DNS:
|
||||||
|
|
||||||
|
- `spore-gateway.service.nomad`
|
||||||
|
- `spore-mqtt.service.nomad`
|
||||||
|
- `spore-registry.service.nomad`
|
||||||
|
- `spore-ledlab.service.nomad`
|
||||||
|
- `spore-ui.service.nomad`
|
||||||
|
|
||||||
|
## Health Checks
|
||||||
|
|
||||||
|
All services include health checks that:
|
||||||
|
- Verify TCP connectivity
|
||||||
|
- Check HTTP endpoints for HTTP-based services
|
||||||
|
- Automatically restart unhealthy tasks
|
||||||
|
|
||||||
|
## Volumes
|
||||||
|
|
||||||
|
The registry service uses a host volume mount to persist firmware data:
|
||||||
|
|
||||||
|
```hcl
|
||||||
|
volume "registry" {
|
||||||
|
type = "host"
|
||||||
|
source = "registry"
|
||||||
|
read_only = false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Volume data is stored in `nomad-data/` directory.
|
||||||
|
|
||||||
|
## Stopping Everything
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make nomad-stop
|
||||||
|
```
|
||||||
|
|
||||||
|
This stops both Nomad and Consul and cleans up data directories.
|
||||||
|
|
||||||
|
## Advanced Usage
|
||||||
|
|
||||||
|
### View Job Status
|
||||||
|
|
||||||
|
```bash
|
||||||
|
nomad job status spore
|
||||||
|
```
|
||||||
|
|
||||||
|
### Inspect Task
|
||||||
|
|
||||||
|
```bash
|
||||||
|
nomad job inspect spore
|
||||||
|
```
|
||||||
|
|
||||||
|
### Watch Job Events
|
||||||
|
|
||||||
|
```bash
|
||||||
|
nomad job status spore -verbose
|
||||||
|
```
|
||||||
|
|
||||||
|
### Connect to Task
|
||||||
|
|
||||||
|
```bash
|
||||||
|
nomad alloc exec <alloc-id> <task-name> /bin/sh
|
||||||
|
```
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Services Not Starting
|
||||||
|
|
||||||
|
Check logs:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make nomad-logs
|
||||||
|
```
|
||||||
|
|
||||||
|
### Port Conflicts
|
||||||
|
|
||||||
|
If ports are in use, modify the job specification in `spore.hcl`:
|
||||||
|
|
||||||
|
```hcl
|
||||||
|
network {
|
||||||
|
mode = "bridge"
|
||||||
|
port "http" {
|
||||||
|
static = 3001 # Change this
|
||||||
|
to = 3001
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Images Not Found
|
||||||
|
|
||||||
|
Ensure Docker images are built and available:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker images | grep wirelos
|
||||||
|
```
|
||||||
|
|
||||||
|
If using a registry, update the image URLs in `spore.hcl`.
|
||||||
|
|
||||||
|
|
||||||
|
## Production Deployment
|
||||||
|
|
||||||
|
For production environments:
|
||||||
|
|
||||||
|
1. **Configure ACLs**: Enable authentication
|
||||||
|
2. **Use Nomad Agents**: Deploy on multiple nodes
|
||||||
|
3. **TLS**: Enable TLS for all connections
|
||||||
|
4. **Resource Limits**: Adjust based on cluster capacity
|
||||||
|
5. **Persistence**: Use external storage for volumes
|
||||||
|
|
||||||
|
## Next Steps
|
||||||
|
|
||||||
|
- [Nomad Documentation](https://www.nomadproject.io/docs)
|
||||||
|
- [SPORE Documentation](../README.md)
|
||||||
|
|
||||||
145
nomad/spore.hcl
Normal file
145
nomad/spore.hcl
Normal file
@@ -0,0 +1,145 @@
|
|||||||
|
job "spore" {
|
||||||
|
datacenters = ["dc1"]
|
||||||
|
type = "service"
|
||||||
|
|
||||||
|
group "mqtt" {
|
||||||
|
count = 1
|
||||||
|
|
||||||
|
network {
|
||||||
|
mode = "host"
|
||||||
|
}
|
||||||
|
|
||||||
|
task "mqtt" {
|
||||||
|
driver = "docker"
|
||||||
|
|
||||||
|
config {
|
||||||
|
image = "eclipse-mosquitto:2.0"
|
||||||
|
network_mode = "host"
|
||||||
|
}
|
||||||
|
|
||||||
|
resources {
|
||||||
|
cpu = 100
|
||||||
|
memory = 128
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
group "gateway" {
|
||||||
|
count = 1
|
||||||
|
|
||||||
|
network {
|
||||||
|
mode = "host"
|
||||||
|
}
|
||||||
|
|
||||||
|
task "gateway" {
|
||||||
|
driver = "docker"
|
||||||
|
|
||||||
|
config {
|
||||||
|
image = "wirelos/spore-gateway:latest"
|
||||||
|
network_mode = "host"
|
||||||
|
}
|
||||||
|
|
||||||
|
env {
|
||||||
|
LOG_LEVEL = "info"
|
||||||
|
MQTT_SERVER = "tcp://localhost:1883"
|
||||||
|
MQTT_USER = ""
|
||||||
|
MQTT_PASSWORD = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
resources {
|
||||||
|
cpu = 200
|
||||||
|
memory = 256
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
group "registry" {
|
||||||
|
count = 1
|
||||||
|
|
||||||
|
network {
|
||||||
|
mode = "host"
|
||||||
|
}
|
||||||
|
|
||||||
|
task "registry" {
|
||||||
|
driver = "docker"
|
||||||
|
|
||||||
|
config {
|
||||||
|
image = "wirelos/spore-registry:latest"
|
||||||
|
network_mode = "host"
|
||||||
|
|
||||||
|
volumes = [
|
||||||
|
"/opt/nomad/spore/data/registry:/data/registry"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
env {
|
||||||
|
REGISTRY_PATH = "/data/registry"
|
||||||
|
DB_PATH = "/data/registry/registry.db"
|
||||||
|
}
|
||||||
|
|
||||||
|
resources {
|
||||||
|
cpu = 200
|
||||||
|
memory = 256
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
group "ledlab" {
|
||||||
|
count = 1
|
||||||
|
|
||||||
|
network {
|
||||||
|
mode = "host"
|
||||||
|
}
|
||||||
|
|
||||||
|
task "ledlab" {
|
||||||
|
driver = "docker"
|
||||||
|
|
||||||
|
config {
|
||||||
|
image = "wirelos/spore-ledlab:latest"
|
||||||
|
network_mode = "host"
|
||||||
|
}
|
||||||
|
|
||||||
|
env {
|
||||||
|
PORT = "8080"
|
||||||
|
UDP_PORT = "4210"
|
||||||
|
GATEWAY_URL = "http://localhost:3001"
|
||||||
|
FILTER_APP_LABEL = "pixelstream"
|
||||||
|
MATRIX_WIDTH = "16"
|
||||||
|
MATRIX_HEIGHT = "16"
|
||||||
|
FPS = "20"
|
||||||
|
}
|
||||||
|
|
||||||
|
resources {
|
||||||
|
cpu = 300
|
||||||
|
memory = 512
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
group "ui" {
|
||||||
|
count = 1
|
||||||
|
|
||||||
|
network {
|
||||||
|
mode = "host"
|
||||||
|
}
|
||||||
|
|
||||||
|
task "ui" {
|
||||||
|
driver = "docker"
|
||||||
|
|
||||||
|
config {
|
||||||
|
image = "wirelos/spore-ui:latest"
|
||||||
|
network_mode = "host"
|
||||||
|
}
|
||||||
|
|
||||||
|
env {
|
||||||
|
PORT = "3000"
|
||||||
|
}
|
||||||
|
|
||||||
|
resources {
|
||||||
|
cpu = 100
|
||||||
|
memory = 256
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user