381 lines
11 KiB
Bash
381 lines
11 KiB
Bash
#!/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 "$@"
|