Add production-ready deployment configuration for Raspberry Pi cluster with comprehensive documentation and automation scripts. Kubernetes Manifests (deploy/k8s/): - namespace.yaml - Dedicated namespace for the application - configmap.yaml - Environment configuration (MongoDB URI, ports, URLs) - secrets.yaml.example - Template for sensitive credentials (JWT, Cloudinary, Stripe) - mongodb-statefulset.yaml - MongoDB with persistent storage, placed on Pi 5 nodes (ARM64) - backend-deployment.yaml - Backend with 2 replicas, prefers Pi 5 nodes, health checks - frontend-deployment.yaml - Frontend with 2 replicas, can run on any node, nginx-based - ingress.yaml - Traefik/NGINX ingress for API, Socket.IO, and frontend routing Docker Configuration: - backend/Dockerfile - Multi-stage build for ARM64/ARMv7 with health checks - backend/.dockerignore - Excludes tests, coverage, node_modules from build - frontend/Dockerfile - Multi-stage build with nginx, optimized for ARM - frontend/.dockerignore - Excludes dev files from production build - frontend/nginx.conf - Production nginx config with gzip, caching, React Router support Resource Optimization for Pi Cluster: - MongoDB: 512Mi-2Gi RAM, 250m-1000m CPU (Pi 5 only, ARM64 affinity) - Backend: 256Mi-512Mi RAM, 100m-500m CPU (prefers Pi 5, ARM64) - Frontend: 64Mi-128Mi RAM, 50m-200m CPU (any node, lightweight) - Total: ~3.5GB RAM minimum, perfect for 2x Pi 5 (8GB) + 1x Pi 3B+ (1GB) Automation Scripts (deploy/scripts/): - build.sh - Build multi-arch images (ARM64/ARMv7) and push to registry - deploy.sh - Deploy all Kubernetes resources with health checks and status reporting - Both scripts include error handling, color output, and comprehensive logging Documentation (deploy/README.md): - Complete deployment guide with prerequisites - Step-by-step instructions for building and deploying - Verification commands and troubleshooting guide - Scaling, updating, and rollback procedures - Resource monitoring and cleanup instructions - Security best practices and performance optimization tips Health Endpoints: - Backend: GET /api/health (status, uptime, MongoDB connection) - Frontend: GET /health (nginx health check) - Used by Kubernetes liveness and readiness probes Key Features: - Multi-architecture support (ARM64 for Pi 5, ARMv7 for Pi 3B+) - NodeAffinity places heavy workloads (MongoDB, backend) on Pi 5 nodes - Persistent storage for MongoDB (10Gi PVC) - Horizontal pod autoscaling ready - Zero-downtime deployments with rolling updates - Comprehensive health monitoring - Production-grade nginx with security headers - Ingress routing for API, WebSocket, and static assets Security: - Secrets management with Kubernetes Secrets - secrets.yaml excluded from Git (.gitignore) - Minimal container images (alpine-based) - Health checks prevent unhealthy pods from serving traffic - Security headers in nginx (X-Frame-Options, X-Content-Type-Options, etc.) Usage: 1. Build images: ./deploy/scripts/build.sh 2. Configure secrets: cp deploy/k8s/secrets.yaml.example deploy/k8s/secrets.yaml 3. Deploy: ./deploy/scripts/deploy.sh 4. Monitor: kubectl get all -n adopt-a-street 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
128 lines
3.5 KiB
Bash
Executable File
128 lines
3.5 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# Adopt-a-Street Kubernetes Deployment Script
|
|
# This script deploys the Adopt-a-Street application to a Kubernetes cluster
|
|
|
|
set -e # Exit on error
|
|
|
|
# Colors for output
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
NC='\033[0m' # No Color
|
|
|
|
# Configuration
|
|
NAMESPACE="adopt-a-street"
|
|
DEPLOY_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
K8S_DIR="${DEPLOY_DIR}/k8s"
|
|
|
|
echo -e "${GREEN}🚀 Adopt-a-Street Kubernetes Deployment${NC}"
|
|
echo "================================================"
|
|
echo ""
|
|
|
|
# Check if kubectl is installed
|
|
if ! command -v kubectl &> /dev/null; then
|
|
echo -e "${RED}❌ kubectl not found. Please install kubectl first.${NC}"
|
|
exit 1
|
|
fi
|
|
|
|
# Check if secrets.yaml exists
|
|
if [ ! -f "${K8S_DIR}/secrets.yaml" ]; then
|
|
echo -e "${RED}❌ secrets.yaml not found!${NC}"
|
|
echo -e "${YELLOW}Please copy secrets.yaml.example to secrets.yaml and fill in your secrets:${NC}"
|
|
echo " cp ${K8S_DIR}/secrets.yaml.example ${K8S_DIR}/secrets.yaml"
|
|
echo " nano ${K8S_DIR}/secrets.yaml"
|
|
exit 1
|
|
fi
|
|
|
|
echo -e "${GREEN}✓${NC} Prerequisites check passed"
|
|
echo ""
|
|
|
|
# Function to wait for pods
|
|
wait_for_pods() {
|
|
local label=$1
|
|
local timeout=${2:-120}
|
|
echo -e "${YELLOW}⏳ Waiting for pods with label ${label} to be ready...${NC}"
|
|
kubectl wait --for=condition=ready pod -l "${label}" -n "${NAMESPACE}" --timeout="${timeout}s" || {
|
|
echo -e "${RED}❌ Timeout waiting for pods${NC}"
|
|
kubectl get pods -n "${NAMESPACE}" -l "${label}"
|
|
return 1
|
|
}
|
|
echo -e "${GREEN}✓${NC} Pods ready"
|
|
}
|
|
|
|
# Create namespace
|
|
echo "📦 Creating namespace..."
|
|
kubectl apply -f "${K8S_DIR}/namespace.yaml"
|
|
echo -e "${GREEN}✓${NC} Namespace created"
|
|
echo ""
|
|
|
|
# Apply secrets
|
|
echo "🔐 Applying secrets..."
|
|
kubectl apply -f "${K8S_DIR}/secrets.yaml"
|
|
echo -e "${GREEN}✓${NC} Secrets applied"
|
|
echo ""
|
|
|
|
# Apply configmap
|
|
echo "⚙️ Applying ConfigMap..."
|
|
kubectl apply -f "${K8S_DIR}/configmap.yaml"
|
|
echo -e "${GREEN}✓${NC} ConfigMap applied"
|
|
echo ""
|
|
|
|
# Deploy MongoDB
|
|
echo "🗄️ Deploying MongoDB..."
|
|
kubectl apply -f "${K8S_DIR}/mongodb-statefulset.yaml"
|
|
wait_for_pods "app=mongodb" 180
|
|
echo -e "${GREEN}✓${NC} MongoDB deployed"
|
|
echo ""
|
|
|
|
# Deploy backend
|
|
echo "🔧 Deploying backend..."
|
|
kubectl apply -f "${K8S_DIR}/backend-deployment.yaml"
|
|
wait_for_pods "app=backend" 120
|
|
echo -e "${GREEN}✓${NC} Backend deployed"
|
|
echo ""
|
|
|
|
# Deploy frontend
|
|
echo "🎨 Deploying frontend..."
|
|
kubectl apply -f "${K8S_DIR}/frontend-deployment.yaml"
|
|
wait_for_pods "app=frontend" 120
|
|
echo -e "${GREEN}✓${NC} Frontend deployed"
|
|
echo ""
|
|
|
|
# Deploy ingress
|
|
echo "🌐 Deploying ingress..."
|
|
kubectl apply -f "${K8S_DIR}/ingress.yaml"
|
|
echo -e "${GREEN}✓${NC} Ingress deployed"
|
|
echo ""
|
|
|
|
# Show deployment status
|
|
echo "================================================"
|
|
echo -e "${GREEN}✅ Deployment Complete!${NC}"
|
|
echo "================================================"
|
|
echo ""
|
|
|
|
echo "📊 Current Status:"
|
|
kubectl get all -n "${NAMESPACE}"
|
|
echo ""
|
|
|
|
echo "🌐 Ingress:"
|
|
kubectl get ingress -n "${NAMESPACE}"
|
|
echo ""
|
|
|
|
echo -e "${YELLOW}📝 Next Steps:${NC}"
|
|
echo "1. Check pod logs:"
|
|
echo " kubectl logs -f deployment/adopt-a-street-backend -n ${NAMESPACE}"
|
|
echo ""
|
|
echo "2. Access the application through your ingress URL"
|
|
echo ""
|
|
echo "3. Or port-forward for testing:"
|
|
echo " kubectl port-forward svc/adopt-a-street-frontend 3000:80 -n ${NAMESPACE}"
|
|
echo " Then open http://localhost:3000"
|
|
echo ""
|
|
echo "4. Monitor resources:"
|
|
echo " kubectl top pods -n ${NAMESPACE}"
|
|
echo ""
|
|
|
|
echo -e "${GREEN}🎉 Happy deploying!${NC}"
|