#!/bin/bash # ============================================================================= # RWADurian API Gateway (Kong) - 部署脚本 # ============================================================================= # Usage: # ./deploy.sh up # 启动网关 # ./deploy.sh down # 停止网关 # ./deploy.sh restart # 重启网关 # ./deploy.sh logs # 查看日志 # ./deploy.sh status # 查看状态 # ./deploy.sh health # 健康检查 # ./deploy.sh reload # 重载 Kong 配置 # ./deploy.sh routes # 查看所有路由 # ./deploy.sh monitoring # 启动监控栈 (Prometheus + Grafana) # ./deploy.sh metrics # 查看 Prometheus 指标 # ============================================================================= set -e # 颜色定义 RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # 日志函数 log_info() { echo -e "${BLUE}[INFO]${NC} $1"; } log_success() { echo -e "${GREEN}[SUCCESS]${NC} $1"; } log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; } log_error() { echo -e "${RED}[ERROR]${NC} $1"; } # 项目信息 PROJECT_NAME="rwa-api-gateway" KONG_ADMIN_URL="http://localhost:8001" KONG_PROXY_URL="http://localhost:8000" # 脚本目录 SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" # 切换到脚本所在目录 cd "$SCRIPT_DIR" # 加载环境变量 if [ -f ".env" ]; then log_info "Loading environment from .env file" set -a source .env set +a elif [ -f ".env.example" ]; then log_warn ".env file not found!" log_warn "Creating .env from .env.example..." cp .env.example .env log_error "Please edit .env file to configure your environment, then run again" exit 1 else log_error "Neither .env nor .env.example found!" exit 1 fi # 检查 Docker check_docker() { if ! command -v docker &> /dev/null; then log_error "Docker 未安装" exit 1 fi if ! docker info &> /dev/null; then log_error "Docker 服务未运行" exit 1 fi } # 检查 Docker Compose check_docker_compose() { if docker compose version &> /dev/null; then COMPOSE_CMD="docker compose" elif command -v docker-compose &> /dev/null; then COMPOSE_CMD="docker-compose" else log_error "Docker Compose 未安装" exit 1 fi } # 检查后端服务连通性(可选) check_backend() { local BACKEND_IP="${BACKEND_SERVER_IP:-192.168.1.111}" log_info "检查后端服务器 $BACKEND_IP 连通性..." if ping -c 1 -W 2 $BACKEND_IP &> /dev/null; then log_success "后端服务器可达" else log_warn "无法 ping 通后端服务器 $BACKEND_IP" log_warn "请确保后端服务已启动且网络可达" fi } # 启动服务 cmd_up() { log_info "启动 Kong API Gateway..." check_backend $COMPOSE_CMD up -d log_info "等待 Kong 启动..." sleep 10 # 检查状态 if docker ps | grep -q rwa-kong; then log_success "Kong API Gateway 启动成功!" echo "" echo "服务地址:" echo " Proxy: http://localhost:8000" echo " Admin API: http://localhost:8001" echo " Admin GUI: http://localhost:8002" echo "" echo "查看路由: ./deploy.sh routes" else log_error "Kong 启动失败,查看日志: ./deploy.sh logs" exit 1 fi } # 启动服务 (2.0 standalone 模式) # 使用 docker-compose.standalone.yml override: # - Kong 加 extra_hosts: host.docker.internal (访问同机 2.0 服务) # - kong-config 加载 kong-standalone.yml (2.0 → localhost, 1.0 → 192.168.1.111) cmd_up2() { log_info "启动 Kong API Gateway (standalone 模式)..." check_backend local STANDALONE="$COMPOSE_CMD -f docker-compose.yml -f docker-compose.standalone.yml" $STANDALONE up -d log_info "等待 Kong 启动..." sleep 10 if docker ps | grep -q rwa-kong; then log_success "Kong API Gateway (standalone) 启动成功!" echo "" echo "模式: standalone (2.0 → host.docker.internal, 1.0 → 192.168.1.111)" echo "服务地址:" echo " Proxy: http://localhost:8000" echo " Admin API: http://localhost:8001" echo " Admin GUI: http://localhost:8002" echo "" else log_error "Kong 启动失败,查看日志: $STANDALONE logs" exit 1 fi } # 重新同步 standalone 配置 cmd_sync2() { log_info "同步 kong-standalone.yml 到 Kong..." local STANDALONE="$COMPOSE_CMD -f docker-compose.yml -f docker-compose.standalone.yml" $STANDALONE run --rm kong-config log_success "standalone 配置同步完成" echo "" echo "查看路由: ./deploy.sh routes" } # 停止服务 cmd_down() { log_info "停止 Kong API Gateway..." $COMPOSE_CMD down log_success "Kong 已停止" } # 重启服务 cmd_restart() { log_info "重启 Kong API Gateway..." $COMPOSE_CMD restart log_success "Kong 已重启" } # 查看日志 cmd_logs() { $COMPOSE_CMD logs -f } # 查看状态 cmd_status() { log_info "Kong API Gateway 状态:" $COMPOSE_CMD ps } # 健康检查 cmd_health() { log_info "Kong 健康检查..." # 检查 Kong 状态 response=$(curl -s $KONG_ADMIN_URL/status 2>/dev/null) if [ $? -eq 0 ]; then log_success "Kong Admin API 正常" echo "$response" | python3 -m json.tool 2>/dev/null || echo "$response" else log_error "Kong Admin API 不可用" exit 1 fi } # 重载配置 (触发 deck sync) cmd_reload() { log_info "重载 Kong 配置..." $COMPOSE_CMD run --rm kong-config log_success "配置已重载" } # 同步配置到数据库 cmd_sync() { log_info "同步 kong.yml 配置到数据库..." $COMPOSE_CMD run --rm kong-config log_success "配置同步完成" echo "" echo "查看路由: ./deploy.sh routes" } # 查看所有路由 cmd_routes() { log_info "Kong 路由列表:" curl -s $KONG_ADMIN_URL/routes | python3 -m json.tool 2>/dev/null || curl -s $KONG_ADMIN_URL/routes } # 查看所有服务 cmd_services() { log_info "Kong 服务列表:" curl -s $KONG_ADMIN_URL/services | python3 -m json.tool 2>/dev/null || curl -s $KONG_ADMIN_URL/services } # 测试 API cmd_test() { log_info "测试 API 路由..." echo "" echo "测试 /api/v1/versions (admin-service):" curl -s -o /dev/null -w " HTTP Status: %{http_code}\n" $KONG_PROXY_URL/api/v1/versions echo "" echo "测试 /api/v1/auth (identity-service):" curl -s -o /dev/null -w " HTTP Status: %{http_code}\n" $KONG_PROXY_URL/api/v1/auth } # 清理 cmd_clean() { log_info "清理 Kong 容器和数据..." $COMPOSE_CMD down -v --remove-orphans docker image prune -f log_success "清理完成" } # 启动监控栈 cmd_monitoring_up() { log_info "启动监控栈 (Prometheus + Grafana)..." $COMPOSE_CMD -f docker-compose.yml -f docker-compose.monitoring.yml up -d prometheus grafana log_info "等待服务启动..." sleep 5 log_success "监控栈启动成功!" echo "" echo "监控服务地址:" echo " Grafana: http://localhost:3030 (admin/admin123)" echo " Prometheus: http://localhost:9099" echo " Kong 指标: http://localhost:8001/metrics" echo "" } # 安装监控栈 (包括 Nginx + SSL) cmd_monitoring_install() { local domain="${1:-monitor.szaiai.com}" log_info "安装监控栈..." if [ ! -f "$SCRIPT_DIR/scripts/install-monitor.sh" ]; then log_error "安装脚本不存在: scripts/install-monitor.sh" exit 1 fi sudo bash "$SCRIPT_DIR/scripts/install-monitor.sh" "$domain" } # 停止监控栈 cmd_monitoring_down() { log_info "停止监控栈..." docker stop rwa-prometheus rwa-grafana 2>/dev/null || true docker rm rwa-prometheus rwa-grafana 2>/dev/null || true log_success "监控栈已停止" } # 查看 Prometheus 指标 cmd_metrics() { log_info "Kong Prometheus 指标概览:" echo "" # 获取关键指标 metrics=$(curl -s $KONG_ADMIN_URL/metrics 2>/dev/null) if [ $? -eq 0 ]; then echo "=== 请求统计 ===" echo "$metrics" | grep -E "^kong_http_requests_total" | head -20 echo "" echo "=== 延迟统计 ===" echo "$metrics" | grep -E "^kong_latency_" | head -10 echo "" echo "完整指标: curl $KONG_ADMIN_URL/metrics" else log_error "无法获取指标,请确保 Kong 正在运行且 prometheus 插件已启用" fi } # 安装 Nginx + SSL 证书 (新域名) cmd_nginx_install() { local domain="${1:-mapi.szaiai.com}" local email="${2:-admin@szaiai.com}" local conf_file="$SCRIPT_DIR/nginx/${domain}.conf" log_info "为域名 $domain 安装 Nginx + SSL..." # 检查 conf 文件是否存在 if [ ! -f "$conf_file" ]; then log_error "Nginx 配置文件不存在: $conf_file" log_error "请先在 nginx/ 目录下创建 ${domain}.conf" exit 1 fi # 检查 root 权限 if [ "$EUID" -ne 0 ]; then log_error "需要 root 权限: sudo ./deploy.sh nginx install $domain" exit 1 fi # 1. 安装依赖 log_info "[1/4] 检查并安装依赖..." if ! command -v nginx &> /dev/null; then apt update && apt install -y nginx systemctl enable nginx systemctl start nginx fi log_success "Nginx 已就绪" if ! command -v certbot &> /dev/null; then apt install -y certbot python3-certbot-nginx fi log_success "Certbot 已就绪" # 2. 部署 HTTP 临时配置 log_info "[2/4] 部署 HTTP 临时配置..." mkdir -p /var/www/certbot cat > /etc/nginx/sites-available/$domain << HTTPEOF server { listen 80; listen [::]:80; server_name $domain; location /.well-known/acme-challenge/ { root /var/www/certbot; } location / { proxy_pass http://127.0.0.1:8000; proxy_http_version 1.1; proxy_set_header Host \$host; proxy_set_header X-Real-IP \$remote_addr; proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto \$scheme; } } HTTPEOF ln -sf /etc/nginx/sites-available/$domain /etc/nginx/sites-enabled/ nginx -t && systemctl reload nginx log_success "HTTP 配置完成" # 3. 申请 SSL 证书 log_info "[3/4] 申请 SSL 证书..." if [ -d "/etc/letsencrypt/live/$domain" ]; then log_warn "证书已存在,跳过申请" else echo "" log_warn "请确保 DNS A 记录 $domain 已指向本服务器 IP" read -p "继续申请证书? (y/n): " confirm if [ "$confirm" != "y" ] && [ "$confirm" != "Y" ]; then log_info "已跳过,当前为 HTTP 模式。稍后运行: sudo ./deploy.sh nginx ssl $domain" return 0 fi certbot certonly --webroot --webroot-path=/var/www/certbot \ --email $email --agree-tos --no-eff-email -d $domain fi log_success "SSL 证书就绪" # 4. 部署 HTTPS 完整配置 log_info "[4/4] 部署 HTTPS 配置..." cp "$conf_file" /etc/nginx/sites-available/$domain nginx -t && systemctl reload nginx log_success "$domain 配置完成!" echo "" echo -e " 访问地址: ${BLUE}https://$domain${NC}" echo -e " 查看日志: tail -f /var/log/nginx/${domain}.access.log" echo "" } # 仅申请/续期 SSL 证书 cmd_nginx_ssl() { local domain="${1:-mapi.szaiai.com}" local email="${2:-admin@szaiai.com}" local conf_file="$SCRIPT_DIR/nginx/${domain}.conf" if [ "$EUID" -ne 0 ]; then log_error "需要 root 权限: sudo ./deploy.sh nginx ssl $domain" exit 1 fi if [ -d "/etc/letsencrypt/live/$domain" ]; then log_info "证书已存在,尝试续期..." certbot renew --cert-name $domain else log_info "为 $domain 申请 SSL 证书..." certbot certonly --webroot --webroot-path=/var/www/certbot \ --email $email --agree-tos --no-eff-email -d $domain fi # 部署 HTTPS 配置 if [ -f "$conf_file" ]; then cp "$conf_file" /etc/nginx/sites-available/$domain nginx -t && systemctl reload nginx log_success "HTTPS 配置已部署" fi } # 显示帮助 show_help() { echo "" echo "RWADurian API Gateway (Kong) 部署脚本" echo "" echo "用法: ./deploy.sh [命令]" echo "" echo "命令:" echo " up 启动 Kong 网关" echo " down 停止 Kong 网关" echo " restart 重启 Kong 网关" echo " logs 查看日志" echo " status 查看状态" echo " health 健康检查" echo " sync 同步 kong.yml 配置到数据库" echo " reload 重载 Kong 配置 (同 sync)" echo " routes 查看所有路由" echo " services 查看所有服务" echo " test 测试 API 路由" echo " clean 清理容器和数据" echo "" echo "Standalone 模式 (2.0 服务与 Kong 同机):" echo " up2 启动 Kong (standalone, 2.0 → host.docker.internal)" echo " sync2 重新同步 kong-standalone.yml 配置" echo "" echo "Nginx 命令:" echo " nginx install [domain] 安装 Nginx + SSL 证书 (默认: mapi.szaiai.com)" echo " nginx ssl [domain] 申请/续期 SSL 证书" echo "" echo "监控命令:" echo " monitoring install [domain] 一键安装监控 (Nginx+SSL+服务)" echo " monitoring up 启动监控栈" echo " monitoring down 停止监控栈" echo " metrics 查看 Prometheus 指标" echo "" echo " help 显示帮助" echo "" echo "注意: 需要先启动 backend/services 才能启动 Kong" echo "" } # 主函数 main() { check_docker check_docker_compose case "${1:-help}" in up) cmd_up ;; down) cmd_down ;; restart) cmd_restart ;; logs) cmd_logs ;; status) cmd_status ;; health) cmd_health ;; sync) cmd_sync ;; reload) cmd_reload ;; routes) cmd_routes ;; services) cmd_services ;; test) cmd_test ;; clean) cmd_clean ;; up2) cmd_up2 ;; sync2) cmd_sync2 ;; nginx) case "${2:-install}" in install) cmd_nginx_install "$3" "$4" ;; ssl) cmd_nginx_ssl "$3" "$4" ;; *) log_error "未知 nginx 命令: $2" echo "用法: ./deploy.sh nginx [install|ssl] [domain]" exit 1 ;; esac ;; monitoring) case "${2:-up}" in install) cmd_monitoring_install "$3" ;; up) cmd_monitoring_up ;; down) cmd_monitoring_down ;; *) log_error "未知监控命令: $2" echo "用法: ./deploy.sh monitoring [install|up|down]" exit 1 ;; esac ;; metrics) cmd_metrics ;; help|--help|-h) show_help ;; *) log_error "未知命令: $1" show_help exit 1 ;; esac } main "$@"