light-sentry-sdk/docs/06-deployment.md

12 KiB
Raw Blame History

部署与运维设计文档

一、部署方式

1.1 Docker Compose推荐

一键部署,适合中小团队。

docker compose up -d

包含的服务:

服务 镜像 端口 说明
light-sentry-api 自建 (Node.js) 9000 API 服务 + 管理后台
loki grafana/loki 3100 日志存储
promtail grafana/promtail - 日志收集(容器日志)
grafana grafana/grafana 3000 数据可视化
dozzle amir20/dozzle 8080 容器日志查看
nginx (系统已有) 80/443 反向代理 + SSL

1.2 二进制部署

适合对 Docker 不熟悉的场景:

  1. 安装 Node.js 18+
  2. 安装 Loki单二进制
  3. 安装 Grafana
  4. 配置 Nginx
  5. 启动 API 服务pm2 守护)

1.3 Kubernetes 部署

适合大规模、多租户场景:

  • Helm Chart 部署
  • HPA 自动扩缩容
  • Loki 分布式模式
  • MySQL / PostgreSQL 集群

二、资源需求

2.1 最小配置(测试/个人用)

资源 配置 说明
CPU 1 核 低流量下足够
内存 1GB 紧张,可能需要调小 Loki 缓存
磁盘 20GB 存 7 天日志(每天 ~2GB
网络 1Mbps 上报流量不大

承载能力

  • 10 个项目以内
  • 每天 1 万事件以内

2.2 推荐配置(小团队)

资源 配置 说明
CPU 2 核 应对突发流量
内存 4GB Loki + API + Grafana 都够
磁盘 100GB SSD 存 30 天日志
网络 5Mbps 足够

承载能力

  • 50 个项目以内
  • 每天 100 万事件以内

2.3 生产配置(中大型团队)

资源 配置 说明
CPU 4 核以上 高并发上报
内存 8GB 以上 Loki 内存索引
磁盘 500GB+ SSD 大量日志存储
网络 10Mbps+ 大流量上报

承载能力

  • 200 个项目以内
  • 每天 1000 万事件以内

三、Docker Compose 配置详解

3.1 完整配置说明

version: '3.8'

services:
  # API 服务 + 管理后台
  light-sentry-api:
    build: .
    container_name: light-sentry-api
    network_mode: host
    environment:
      - NODE_ENV=production
      - PORT=9000
      - LOKI_URL=http://127.0.0.1:3100
      - DATA_DIR=/app/data
    volumes:
      - ./data:/app/data
    restart: unless-stopped
    depends_on:
      - loki

  # Loki - 日志存储
  loki:
    image: grafana/loki:2.9.4
    container_name: light-sentry-loki
    network_mode: host
    command: -config.file=/etc/loki/local-config.yaml
    volumes:
      - ./loki/config:/etc/loki
      - loki-data:/loki
    restart: unless-stopped

  # Promtail - 收集容器日志
  promtail:
    image: grafana/promtail:2.9.4
    container_name: light-sentry-promtail
    network_mode: host
    volumes:
      - ./promtail/config:/etc/promtail
      - /var/lib/docker/containers:/var/lib/docker/containers:ro
    restart: unless-stopped
    depends_on:
      - loki

  # Grafana - 可视化
  grafana:
    image: grafana/grafana:10.2.0
    container_name: light-sentry-grafana
    network_mode: host
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=admin123
    volumes:
      - grafana-data:/var/lib/grafana
    restart: unless-stopped

  # Dozzle - 容器日志查看
  dozzle:
    image: amir20/dozzle:latest
    container_name: light-sentry-dozzle
    network_mode: host
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    restart: unless-stopped

volumes:
  loki-data:
  grafana-data:

3.2 Loki 配置

loki/config/local-config.yaml

auth_enabled: false

server:
  http_listen_port: 3100

ingester:
  lifecycler:
    ring:
      kvstore:
        store: inmemory
      replication_factor: 1
  chunk_idle_period: 30m
  chunk_retain_period: 1m
  max_transfer_retries: 0

schema_config:
  configs:
    - from: 2024-01-01
      store: boltdb-shipper
      object_store: filesystem
      schema: v12
      index:
        prefix: index_
        period: 24h

storage_config:
  boltdb_shipper:
    active_index_directory: /loki/index
    cache_location: /loki/index_cache
    shared_store: filesystem
  filesystem:
    directory: /loki/chunks

limits_config:
  retention_period: 168h  # 7 天
  per_stream_rate_limit: 10MB
  ingestion_rate_mb: 50
  ingestion_burst_size_mb: 100
  max_streams_per_user: 10000
  max_chunks_per_query: 2000000
  max_query_series: 5000

table_manager:
  retention_deletes_enabled: true
  retention_period: 168h  # 7 天

四、Nginx 配置

4.1 反向代理配置

server {
    listen 443 ssl http2;
    server_name log.example.com;

    # SSL 配置
    ssl_certificate /path/to/fullchain.pem;
    ssl_certificate_key /path/to/privkey.pem;

    # API 服务Sentry 上报 + 管理后台 API
    location /api/ {
        proxy_pass http://127.0.0.1:9000/api/;
        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;

        # 上报接口超时
        proxy_read_timeout 30s;
        proxy_connect_timeout 10s;
        proxy_send_timeout 30s;

        # CORSSDK 上报需要)
        add_header Access-Control-Allow-Origin * always;
        add_header Access-Control-Allow-Methods GET,POST,OPTIONS always;
        add_header Access-Control-Allow-Headers Content-Type,X-Sentry-Auth always;
        if ($request_method = OPTIONS) {
            return 204;
        }
    }

    # 管理后台
    location /manage/ {
        proxy_pass http://127.0.0.1:9000/manage/;
        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;
    }

    # Grafana
    location /grafana/ {
        proxy_pass http://127.0.0.1:3000/;
        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;
    }

    # Dozzle
    location /dozzle/ {
        proxy_pass http://127.0.0.1:8080/;
        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;

        # WebSocket 支持
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }

    # Loki可选直接暴露给 Grafana 用,一般不需要外部访问)
    location /loki/ {
        proxy_pass http://127.0.0.1:3100/;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        deny all;  # 禁止外部访问,只允许内网
    }

    # 根路径重定向到管理后台
    location = / {
        return 301 /manage/;
    }
}

4.2 限流配置

# 定义限流 zone
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=100r/s;

location /api/ {
    limit_req zone=api_limit burst=200 nodelay;
    # ... 其他配置
}

五、CI/CD 部署

5.1 Gitea Actions 示例

name: Deploy Light-Sentry

on:
  push:
    branches: [ main ]
  workflow_dispatch:

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Deploy via SSH
        uses: appleboy/ssh-action@v1.0.0
        with:
          host: ${{ secrets.SERVER_HOST }}
          username: ${{ secrets.SERVER_USER }}
          key: ${{ secrets.SSH_PRIVATE_KEY }}
          script: |
            cd ~/light-sentry
            git pull
            docker compose build light-sentry-api
            docker compose up -d
            echo "Deploy completed"            

5.2 智能重启(只重启变更的服务)

检测变更的文件,只重启相关服务,减少停机时间:

  • src/** → 重启 API 服务
  • loki/** → 重启 Loki
  • grafana/** → 重启 Grafana
  • docker-compose.yml → 全部重启
  • nginx/** → reload Nginx

六、监控与告警

6.1 自身监控

Light-Sentry 自己也要监控自己:

监控项 方式 告警阈值
API 服务存活 健康检查接口 + Prometheus 502 持续 1 分钟
Loki 服务存活 Grafana 内置监控 连接失败
磁盘使用率 Node Exporter > 80% 告警
内存使用率 Node Exporter > 85% 告警
CPU 使用率 Node Exporter > 90% 告警
事件上报量 Loki 查询 突增 200%
错误率 Loki 查询 > 5%

6.2 健康检查

GET /health

{
  "status": "ok",
  "timestamp": "2024-01-01T00:00:00Z",
  "uptime": 86400,
  "queue_size": 123,
  "loki": "connected",
  "mysql": "connected"
}

七、备份与恢复

7.1 需要备份的数据

数据 位置 备份频率 保留时间
项目配置 data/projects.json 每天 30 天
Loki 数据 loki-data 卷 每周 4 周
Grafana 配置 grafana-data 卷 每天 30 天
告警规则 MySQL 每天 永久
错误聚合 MySQL 每天 永久

7.2 备份脚本

#!/bin/bash
# backup.sh - Light-Sentry 备份脚本

BACKUP_DIR="/backup/light-sentry"
DATE=$(date +%Y%m%d_%H%M%S)

# 创建备份目录
mkdir -p $BACKUP_DIR

# 备份配置文件
tar czf $BACKUP_DIR/config_$DATE.tar.gz /opt/light-sentry/data/

# 备份 Loki 数据(可选,量大)
# docker run --rm -v loki-data:/data -v $BACKUP_DIR:/backup \
#   alpine tar czf /backup/loki_$DATE.tar.gz -C /data .

# 备份 Grafana
docker run --rm -v grafana-data:/data -v $BACKUP_DIR:/backup \
  alpine tar czf /backup/grafana_$DATE.tar.gz -C /data .

# 清理 30 天前的备份
find $BACKUP_DIR -name "*.tar.gz" -mtime +30 -delete

echo "Backup completed: $DATE"

7.3 恢复流程

# 1. 停止服务
docker compose down

# 2. 恢复配置
tar xzf backup/config_20240101_000000.tar.gz -C /opt/light-sentry/

# 3. 恢复 Grafana
docker run --rm -v grafana-data:/data -v /backup:/backup \
  alpine tar xzf /backup/grafana_20240101_000000.tar.gz -C /data

# 4. 启动服务
docker compose up -d

八、性能优化

8.1 API 服务优化

  • Node.js 集群模式:利用多核 CPU
  • 内存队列调优:根据流量调整队列大小和刷盘频率
  • 连接池数据库连接池、HTTP 连接池
  • 缓存:项目配置缓存,不用每次查存储

8.2 Loki 优化

  • 调整保留时间:从 7 天调整到实际需要的时间
  • 降低索引基数:减少 label 数量
  • 批量写入:增加 chunk 大小,减少写入次数
  • 内存调优:根据实际数据量调整内存

8.3 Nginx 优化

  • 启用 gzip 压缩:减少传输体积
  • 启用缓存:静态文件缓存
  • TCP 参数调优:增加连接数限制

九、安全加固

9.1 网络安全

  • 管理后台加访问密码HTTP Basic Auth 或登录)
  • Loki 不对外暴露(只允许 Grafana 访问)
  • Dozzle 加访问密码
  • 只开放必要端口80/443

9.2 数据安全

  • SDK 上报接口 CORS 限制域名(可选)
  • 项目 DSN 泄露后可重置 publicKey
  • 敏感数据自动脱敏
  • 定期备份,异地存储

9.3 依赖安全

  • 定期更新依赖
  • 镜像扫描漏洞
  • 最小权限运行

十、常见问题排查

10.1 事件上报失败

  1. 检查网络是否通:curl -I https://log.example.com/api/1001/envelope/
  2. 检查 DSN 是否正确publicKey 和 projectId 对应
  3. 查看 API 日志:docker logs light-sentry-api
  4. 查看 Nginx 日志:tail -f /var/log/nginx/access.log

10.2 Grafana 查不到数据

  1. 检查 Loki 数据源是否配置正确
  2. 检查时间范围是否正确
  3. 检查 label 拼写是否正确
  4. 查看 Loki 日志:docker logs light-sentry-loki

10.3 服务无法启动

  1. 检查端口是否被占用:netstat -tlnp | grep 9000
  2. 查看容器日志:docker logs light-sentry-api
  3. 检查配置文件格式JSON / YAML 语法
  4. 检查磁盘空间:df -h

十一、升级策略

11.1 版本升级

# 拉取最新代码
git pull

# 重新构建并启动
docker compose build light-sentry-api
docker compose up -d

# 验证
curl https://log.example.com/health

11.2 数据迁移

  • 配置向后兼容,新版本能读旧版本数据
  • 启动时自动检测并执行数据迁移
  • 迁移前自动备份