9.5 KiB
9.5 KiB
Deployment Guide
This guide covers deploying the Predictor Service using Docker and Docker Compose.
Prerequisites
- Docker Engine 20.10+
- Docker Compose 2.0+
- At least 2GB RAM available
- 10GB free disk space
Quick Deployment
1. Clone and Setup
git clone <repository-url>
cd predictor
2. Validate Configuration
# Validate Docker configuration
./scripts/validate-docker.sh
3. Deploy
# Build and start services
make up-build
# Check status
make ps
# View logs
make logs
Production Deployment
Environment Configuration
-
Copy environment template:
cp cmd/api/.env cmd/api/.env.production -
Edit production environment:
nano cmd/api/.env.production -
Key production settings:
# Security GSN_PREDICTOR_REDIS_PASSWORD=your_secure_password # Performance GSN_PREDICTOR_GRIB_PARALLEL=8 GSN_PREDICTOR_GRIB_CACHE_TTL=2h # Monitoring GSN_PREDICTOR_GRIB_UPDATER_INTERVAL=3h
Production Docker Compose
Create docker-compose.prod.yml:
version: '3.8'
services:
predictor:
build:
context: .
dockerfile: Dockerfile
container_name: predictor-prod
ports:
- "8080:8080"
env_file:
- cmd/api/.env.production
volumes:
- grib_data:/tmp/grib
depends_on:
redis:
condition: service_healthy
networks:
- predictor-network
restart: unless-stopped
deploy:
resources:
limits:
memory: 1G
cpus: '0.5'
reservations:
memory: 512M
cpus: '0.25'
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:8080/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
redis:
image: redis:7.2-alpine
container_name: predictor-redis-prod
ports:
- "6379:6379"
volumes:
- redis_data:/data
networks:
- predictor-network
restart: unless-stopped
command: redis-server --appendonly yes --maxmemory 512mb --maxmemory-policy allkeys-lru --requirepass ${GSN_PREDICTOR_REDIS_PASSWORD}
healthcheck:
test: ["CMD", "redis-cli", "-a", "${GSN_PREDICTOR_REDIS_PASSWORD}", "ping"]
interval: 10s
timeout: 3s
retries: 5
start_period: 10s
volumes:
grib_data:
driver: local
redis_data:
driver: local
networks:
predictor-network:
driver: bridge
Deploy to Production
# Deploy with production config
docker-compose -f docker-compose.prod.yml up -d
# Monitor deployment
docker-compose -f docker-compose.prod.yml logs -f
# Check health
curl http://localhost:8080/health
Kubernetes Deployment
Create Namespace
# k8s/namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
name: predictor
Redis Deployment
# k8s/redis.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis
namespace: predictor
spec:
replicas: 1
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
spec:
containers:
- name: redis
image: redis:7.2-alpine
ports:
- containerPort: 6379
command: ["redis-server", "--appendonly", "yes", "--maxmemory", "512mb", "--maxmemory-policy", "allkeys-lru"]
volumeMounts:
- name: redis-data
mountPath: /data
resources:
limits:
memory: "512Mi"
cpu: "250m"
requests:
memory: "256Mi"
cpu: "100m"
livenessProbe:
exec:
command: ["redis-cli", "ping"]
initialDelaySeconds: 10
periodSeconds: 10
readinessProbe:
exec:
command: ["redis-cli", "ping"]
initialDelaySeconds: 5
periodSeconds: 5
volumes:
- name: redis-data
persistentVolumeClaim:
claimName: redis-pvc
---
apiVersion: v1
kind: Service
metadata:
name: redis
namespace: predictor
spec:
selector:
app: redis
ports:
- port: 6379
targetPort: 6379
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: redis-pvc
namespace: predictor
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
Predictor Deployment
# k8s/predictor.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: predictor
namespace: predictor
spec:
replicas: 2
selector:
matchLabels:
app: predictor
template:
metadata:
labels:
app: predictor
spec:
containers:
- name: predictor
image: predictor:latest
ports:
- containerPort: 8080
env:
- name: GSN_PREDICTOR_REDIS_HOST
value: "redis"
- name: GSN_PREDICTOR_REDIS_PORT
value: "6379"
- name: GSN_PREDICTOR_GRIB_DIR
value: "/tmp/grib"
- name: GSN_PREDICTOR_SCHEDULER_ENABLED
value: "true"
- name: GSN_PREDICTOR_GRIB_UPDATER_INTERVAL
value: "6h"
- name: GSN_PREDICTOR_GRIB_UPDATER_TIMEOUT
value: "45m"
volumeMounts:
- name: grib-data
mountPath: /tmp/grib
resources:
limits:
memory: "1Gi"
cpu: "500m"
requests:
memory: "512Mi"
cpu: "250m"
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 40
periodSeconds: 30
readinessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 10
periodSeconds: 10
volumes:
- name: grib-data
emptyDir: {}
---
apiVersion: v1
kind: Service
metadata:
name: predictor
namespace: predictor
spec:
selector:
app: predictor
ports:
- port: 80
targetPort: 8080
type: LoadBalancer
Deploy to Kubernetes
# Apply namespace
kubectl apply -f k8s/namespace.yaml
# Apply Redis
kubectl apply -f k8s/redis.yaml
# Wait for Redis to be ready
kubectl wait --for=condition=ready pod -l app=redis -n predictor
# Apply Predictor
kubectl apply -f k8s/predictor.yaml
# Check status
kubectl get pods -n predictor
kubectl get services -n predictor
Monitoring and Logging
Health Checks
The service includes built-in health checks:
# Application health
curl http://localhost:8080/health
# Docker health
docker inspect predictor | jq '.[0].State.Health'
# Kubernetes health
kubectl describe pod -l app=predictor -n predictor
Logging
# Docker logs
docker-compose logs -f predictor
# Kubernetes logs
kubectl logs -f deployment/predictor -n predictor
Metrics
Consider adding Prometheus metrics:
# Add to docker-compose.yml
prometheus:
image: prom/prometheus:latest
ports:
- "9090:9090"
volumes:
- ./monitoring/prometheus.yml:/etc/prometheus/prometheus.yml
networks:
- predictor-network
Backup and Recovery
Redis Backup
# Create backup
docker exec predictor-redis redis-cli BGSAVE
# Copy backup file
docker cp predictor-redis:/data/dump.rdb ./backup/redis-$(date +%Y%m%d).rdb
GRIB Data Backup
# Backup GRIB data
docker run --rm -v predictor_grib_data:/data -v $(pwd)/backup:/backup alpine tar czf /backup/grib-$(date +%Y%m%d).tar.gz -C /data .
Automated Backup Script
#!/bin/bash
# scripts/backup.sh
BACKUP_DIR="./backup/$(date +%Y%m%d)"
mkdir -p $BACKUP_DIR
# Redis backup
docker exec predictor-redis redis-cli BGSAVE
sleep 5
docker cp predictor-redis:/data/dump.rdb $BACKUP_DIR/redis.rdb
# GRIB data backup
docker run --rm -v predictor_grib_data:/data -v $(pwd)/$BACKUP_DIR:/backup alpine tar czf /backup/grib.tar.gz -C /data .
echo "Backup completed: $BACKUP_DIR"
Troubleshooting
Common Issues
-
Redis Connection Issues:
# Check Redis status docker-compose exec redis redis-cli ping # Check network connectivity docker-compose exec predictor wget -O- http://redis:6379 -
GRIB Download Failures:
# Check disk space docker-compose exec predictor df -h /tmp/grib # Check internet connectivity docker-compose exec predictor wget -O- https://nomads.ncep.noaa.gov/ -
Memory Issues:
# Check memory usage docker stats # Check container logs docker-compose logs predictor | grep -i memory
Performance Tuning
-
Redis Optimization:
# Increase Redis memory GSN_PREDICTOR_REDIS_MAXMEMORY=1gb # Optimize Redis settings redis-server --maxmemory 1gb --maxmemory-policy allkeys-lru -
GRIB Processing:
# Increase parallel workers GSN_PREDICTOR_GRIB_PARALLEL=8 # Optimize cache TTL GSN_PREDICTOR_GRIB_CACHE_TTL=2h -
Container Resources:
# In docker-compose.yml deploy: resources: limits: memory: 2G cpus: '1.0' reservations: memory: 1G cpus: '0.5'
Security Considerations
-
Network Security:
- Use internal networks for service communication
- Expose only necessary ports
- Use reverse proxy for external access
-
Container Security:
- Run as non-root user
- Use minimal base images
- Regular security updates
-
Data Security:
- Encrypt sensitive environment variables
- Use secrets management for passwords
- Regular backups
-
Access Control:
- Implement API authentication
- Use HTTPS in production
- Monitor access logs