Phase 6: 部署文档 + 启动脚本 + 配置样例
- README.md (英文): 项目概览 + 11 Tool 表格 + 12 env 变量全表 + 6 admin 端点 + 安全模型 (3 道防线 + 4 项额外保证) + dev 命令 - .env.example: 12 env 变量 + 默认值 + 必填标注 - scripts/dev.sh: 一键 build + 后台启动 (nohup + PID 文件) + healthz 验证 - scripts/seed.sh: admin POST 一个示例 cluster (从 .env 读 admin token) - ARCHITECTURE.md (中文): 包依赖图 + 数据流 + 11 Tool 分类 + 关键设计决策 - docs/runbook.md (中文): 部署 + 升级 + 故障排查 (401/404/422 等) - docs/systemd/spark-mcp-go.service: systemd unit 模板 README 安全模型小修正: 第 3 道防线从"spark_submit flag 白名单" (实际不存在) 改为 "upload_file 路径白名单", 加 Additional guarantees 小节列 slice form / json:"-" / 跨主机 redirect / per-tool log 权限。 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
# spark-mcp-go 部署与排障手册
|
||||
|
||||
## 部署步骤
|
||||
|
||||
### 1. 构建
|
||||
|
||||
```bash
|
||||
cd /opt/spark-mcp-go
|
||||
go build -o spark-mcp-go .
|
||||
```
|
||||
|
||||
### 2. 配置
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
# 编辑 .env:ADMIN_TOKENS、AGENT_TOKEN、LISTEN_ADDR、DATA_DIR 等
|
||||
```
|
||||
|
||||
### 3. 使用 systemd 运行
|
||||
|
||||
参见 [docs/systemd/spark-mcp-go.service](systemd/spark-mcp-go.service)。
|
||||
|
||||
### 4. 初始化示例 cluster
|
||||
|
||||
```bash
|
||||
ADMIN_HOST=http://127.0.0.1:8080 ./scripts/seed.sh prod http://rm.example.com:8088 http://shs.example.com:18080 /opt/spark/bin/spark-submit
|
||||
```
|
||||
|
||||
### 5. 升级流程
|
||||
|
||||
1. 停止服务:`systemctl stop spark-mcp-go`
|
||||
2. 备份数据库:`cp ./data/spark-mcp.db ./data/spark-mcp.db.bak`
|
||||
3. 替换二进制:`cp spark-mcp-go /usr/local/bin/`
|
||||
4. 启动服务:`systemctl start spark-mcp-go`
|
||||
5. 验证:`curl -sS http://127.0.0.1:${LISTEN_ADDR:-:8080}/healthz`
|
||||
|
||||
## 故障排查
|
||||
|
||||
### 401 Unauthorized
|
||||
|
||||
- 检查请求是否带 `Authorization: Bearer <token>`。
|
||||
- 区分 `ADMIN_TOKENS`(管理面)和 `AGENT_TOKEN`(MCP 面)。
|
||||
- `.env` 中 token 不能含前导/尾随空格。
|
||||
|
||||
### 404 "Invalid session ID"
|
||||
|
||||
- Streamable HTTP 需要先走 MCP `initialize` 握手,拿到 `Mcp-Session-Id` 后再调用 Tool。
|
||||
- 确保客户端保存并回传 response header 中的 session ID。
|
||||
|
||||
### 422 cluster not found
|
||||
|
||||
- `cluster_id` 拼写错误,或 cluster 未激活。
|
||||
- 先用 `list_clusters` 确认可用的 cluster ID。
|
||||
|
||||
### "host not in allowlist"
|
||||
|
||||
- 对应 cluster 的 `url_allowlist` 未包含目标主机。
|
||||
- 使用 `admin` 更新 cluster,把 RM/SHS 主机加入 allowlist。
|
||||
|
||||
### `spark_submit` 返回 exit_code 7
|
||||
|
||||
- `spark_submit_execute_bin` 路径错误,或 YARN 拒绝提交。
|
||||
- 查看返回的 `stderr_tail`;在服务器上直接运行相同命令验证。
|
||||
|
||||
### `analyze_spark_log` 的 `findings` 为空
|
||||
|
||||
- SHS metrics 端点 404 或返回格式不匹配。
|
||||
- 可 fallback 到 raw log + LLM 自行分析。
|
||||
|
||||
### SQLite 锁冲突
|
||||
|
||||
- `storage` 已开启 WAL 模式,但 SQLite 仍是 single-writer。
|
||||
- 多个 server 实例共用一个 `spark-mcp.db` 会产生锁竞争;请保持一实例一数据库。
|
||||
|
||||
## 监控建议
|
||||
|
||||
- **存活探测**:HTTP `GET /healthz`
|
||||
- **日志告警**:监控 `data/logs/spark-mcp.log` 中的 `ERROR` 级别行
|
||||
- **审计日志告警**:`data/logs/tools/` 下文件过大或增长过快时检查异常调用
|
||||
- **磁盘告警**:`data/` 目录包含 SQLite、上传文件、日志,需预留空间
|
||||
@@ -0,0 +1,22 @@
|
||||
[Unit]
|
||||
Description=Spark MCP Go Server
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=spark-mcp
|
||||
Group=spark-mcp
|
||||
WorkingDirectory=/opt/spark-mcp-go
|
||||
EnvironmentFile=/opt/spark-mcp-go/.env
|
||||
ExecStart=/opt/spark-mcp-go/spark-mcp-go
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
|
||||
# Security hardening
|
||||
NoNewPrivileges=true
|
||||
ProtectSystem=strict
|
||||
ProtectHome=true
|
||||
ReadWritePaths=/opt/spark-mcp-go/data
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
Reference in New Issue
Block a user