#!/bin/bash # ============================================================================= # Kong 监控栈一键安装脚本 # ============================================================================= # 功能: # - 自动配置 Nginx 反向代理 # - 自动申请 Let's Encrypt SSL 证书 # - 启动 Prometheus + Grafana 监控服务 # # 用法: # ./install-monitor.sh # 使用默认域名 monitor.szaiai.com # ./install-monitor.sh mydomain.com # 使用自定义域名 # ============================================================================= set -e # 颜色定义 RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' CYAN='\033[0;36m' NC='\033[0m' # 日志函数 log_info() { echo -e "${BLUE}[INFO]${NC} $1"; } log_success() { echo -e "${GREEN}[OK]${NC} $1"; } log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; } log_error() { echo -e "${RED}[ERROR]${NC} $1"; } log_step() { echo -e "${CYAN}[STEP]${NC} $1"; } # 默认配置 DOMAIN="${1:-monitor.szaiai.com}" GRAFANA_PORT=3030 PROMETHEUS_PORT=9099 GRAFANA_USER="admin" GRAFANA_PASS="admin123" # 获取脚本目录 SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_DIR="$(dirname "$SCRIPT_DIR")" # 显示 Banner show_banner() { echo -e "${CYAN}" echo "╔═══════════════════════════════════════════════════════════════╗" echo "║ Kong 监控栈一键安装脚本 ║" echo "║ Prometheus + Grafana ║" echo "╚═══════════════════════════════════════════════════════════════╝" echo -e "${NC}" echo "域名: $DOMAIN" echo "Grafana 端口: $GRAFANA_PORT" echo "Prometheus 端口: $PROMETHEUS_PORT" echo "" } # 检查 root 权限 check_root() { if [ "$EUID" -ne 0 ]; then log_error "请使用 root 权限运行此脚本" echo "用法: sudo $0 [domain]" exit 1 fi } # 检查依赖 check_dependencies() { log_step "检查依赖..." local missing=() if ! command -v docker &> /dev/null; then missing+=("docker") fi if ! command -v nginx &> /dev/null; then missing+=("nginx") fi if ! command -v certbot &> /dev/null; then missing+=("certbot") fi if [ ${#missing[@]} -gt 0 ]; then log_error "缺少依赖: ${missing[*]}" echo "" echo "请先安装:" echo " apt update && apt install -y docker.io nginx certbot python3-certbot-nginx" exit 1 fi log_success "依赖检查通过" } # 检查 DNS 解析 check_dns() { log_step "检查 DNS 解析..." local resolved_ip=$(dig +short $DOMAIN 2>/dev/null | head -1) local server_ip=$(curl -s ifconfig.me 2>/dev/null || curl -s icanhazip.com 2>/dev/null) if [ -z "$resolved_ip" ]; then log_error "无法解析域名 $DOMAIN" echo "请先在 DNS 管理面板添加 A 记录:" echo " $DOMAIN -> $server_ip" exit 1 fi if [ "$resolved_ip" != "$server_ip" ]; then log_warn "DNS 解析的 IP ($resolved_ip) 与本机公网 IP ($server_ip) 不匹配" read -p "是否继续? [y/N] " -n 1 -r echo if [[ ! $REPLY =~ ^[Yy]$ ]]; then exit 1 fi fi log_success "DNS 解析正确: $DOMAIN -> $resolved_ip" } # 生成 Nginx 配置 generate_nginx_config() { log_step "生成 Nginx 配置..." cat > /etc/nginx/sites-available/$DOMAIN.conf << EOF # Kong 监控面板 Nginx 配置 # 自动生成于 $(date) # HTTP -> HTTPS 重定向 server { listen 80; listen [::]:80; server_name $DOMAIN; location /.well-known/acme-challenge/ { root /var/www/certbot; } location / { return 301 https://\$host\$request_uri; } } # HTTPS 配置 server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name $DOMAIN; # SSL 证书 (Let's Encrypt) ssl_certificate /etc/letsencrypt/live/$DOMAIN/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/$DOMAIN/privkey.pem; # SSL 优化 ssl_session_timeout 1d; ssl_session_cache shared:SSL:50m; ssl_session_tickets off; ssl_protocols TLSv1.2 TLSv1.3; ssl_prefer_server_ciphers off; # HSTS add_header Strict-Transport-Security "max-age=63072000" always; # 日志 access_log /var/log/nginx/$DOMAIN.access.log; error_log /var/log/nginx/$DOMAIN.error.log; # Grafana location / { proxy_pass http://127.0.0.1:$GRAFANA_PORT; proxy_http_version 1.1; # WebSocket support proxy_set_header Upgrade \$http_upgrade; proxy_set_header Connection 'upgrade'; # Standard proxy headers proxy_set_header Host \$http_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; proxy_set_header X-Forwarded-Host \$host; proxy_set_header X-Forwarded-Port \$server_port; # Grafana 10+ 反向代理支持 proxy_set_header Origin \$scheme://\$host; # 缓存和超时 proxy_cache_bypass \$http_upgrade; proxy_read_timeout 86400; proxy_buffering off; } # Prometheus (仅内网) location /prometheus/ { allow 127.0.0.1; allow 10.0.0.0/8; allow 172.16.0.0/12; allow 192.168.0.0/16; deny all; proxy_pass http://127.0.0.1:$PROMETHEUS_PORT/; proxy_http_version 1.1; proxy_set_header Host \$host; proxy_set_header X-Real-IP \$remote_addr; } # 健康检查 location = /health { access_log off; return 200 '{"status":"ok","service":"monitor-nginx"}'; add_header Content-Type application/json; } } EOF log_success "Nginx 配置已生成: /etc/nginx/sites-available/$DOMAIN.conf" } # 申请 SSL 证书 obtain_ssl_cert() { log_step "申请 SSL 证书..." # 检查证书是否已存在 if [ -f "/etc/letsencrypt/live/$DOMAIN/fullchain.pem" ]; then log_success "SSL 证书已存在" return 0 fi # 创建 certbot webroot 目录 mkdir -p /var/www/certbot # 临时启用 HTTP 配置用于验证 cat > /etc/nginx/sites-available/$DOMAIN-temp.conf << EOF server { listen 80; server_name $DOMAIN; location /.well-known/acme-challenge/ { root /var/www/certbot; } location / { return 200 'Waiting for SSL...'; add_header Content-Type text/plain; } } EOF ln -sf /etc/nginx/sites-available/$DOMAIN-temp.conf /etc/nginx/sites-enabled/ nginx -t && systemctl reload nginx # 申请证书 certbot certonly --webroot -w /var/www/certbot -d $DOMAIN --non-interactive --agree-tos --email admin@$DOMAIN || { log_error "SSL 证书申请失败" rm -f /etc/nginx/sites-enabled/$DOMAIN-temp.conf rm -f /etc/nginx/sites-available/$DOMAIN-temp.conf exit 1 } # 清理临时配置 rm -f /etc/nginx/sites-enabled/$DOMAIN-temp.conf rm -f /etc/nginx/sites-available/$DOMAIN-temp.conf log_success "SSL 证书申请成功" } # 启用 Nginx 配置 enable_nginx_config() { log_step "启用 Nginx 配置..." ln -sf /etc/nginx/sites-available/$DOMAIN.conf /etc/nginx/sites-enabled/ nginx -t || { log_error "Nginx 配置测试失败" exit 1 } systemctl reload nginx log_success "Nginx 配置已启用" } # 启动监控服务 start_monitoring_services() { log_step "启动监控服务..." cd "$PROJECT_DIR" # 检查 Kong 是否运行 if ! docker ps | grep -q rwa-kong; then log_warn "Kong 未运行,先启动 Kong..." docker compose up -d sleep 10 fi # 同步 Kong 配置 (启用 prometheus 插件) log_info "同步 Kong 配置..." docker compose run --rm kong-config || log_warn "配置同步失败,可能已是最新" # 启动监控栈 log_info "启动 Prometheus + Grafana..." docker compose -f docker-compose.yml -f docker-compose.monitoring.yml up -d prometheus grafana # 等待服务启动 sleep 5 # 检查服务状态 if docker ps | grep -q rwa-grafana && docker ps | grep -q rwa-prometheus; then log_success "监控服务启动成功" else log_error "监控服务启动失败" docker compose -f docker-compose.yml -f docker-compose.monitoring.yml logs --tail=50 exit 1 fi } # 显示安装结果 show_result() { echo "" echo -e "${GREEN}╔═══════════════════════════════════════════════════════════════╗${NC}" echo -e "${GREEN}║ 安装完成! ║${NC}" echo -e "${GREEN}╚═══════════════════════════════════════════════════════════════╝${NC}" echo "" echo "访问地址:" echo -e " Grafana: ${CYAN}https://$DOMAIN${NC}" echo -e " 用户名: ${YELLOW}$GRAFANA_USER${NC}" echo -e " 密码: ${YELLOW}$GRAFANA_PASS${NC}" echo "" echo "Prometheus (仅内网可访问):" echo -e " 地址: ${CYAN}https://$DOMAIN/prometheus/${NC}" echo "" echo "Kong 指标端点:" echo -e " 地址: ${CYAN}http://localhost:8001/metrics${NC}" echo "" echo "管理命令:" echo " ./deploy.sh monitoring up # 启动监控" echo " ./deploy.sh monitoring down # 停止监控" echo " ./deploy.sh metrics # 查看指标" echo "" } # 卸载函数 uninstall() { log_warn "正在卸载监控栈..." # 停止服务 cd "$PROJECT_DIR" docker stop rwa-prometheus rwa-grafana 2>/dev/null || true docker rm rwa-prometheus rwa-grafana 2>/dev/null || true # 删除 Nginx 配置 rm -f /etc/nginx/sites-enabled/$DOMAIN.conf rm -f /etc/nginx/sites-available/$DOMAIN.conf systemctl reload nginx 2>/dev/null || true log_success "监控栈已卸载" echo "注意: SSL 证书未删除,如需删除请运行: certbot delete --cert-name $DOMAIN" } # 主函数 main() { show_banner # 检查是否卸载 if [ "$1" = "uninstall" ] || [ "$1" = "--uninstall" ]; then uninstall exit 0 fi check_root check_dependencies check_dns generate_nginx_config obtain_ssl_cert enable_nginx_config start_monitoring_services show_result } main "$@"