diff --git a/.gitignore b/.gitignore index 860e8c3..2affab2 100644 --- a/.gitignore +++ b/.gitignore @@ -56,3 +56,6 @@ agent/bin/ # embed 模式临时目录(前端构建产物,编译后清理) backend/cmd/static/ + +# Hermes agent config (personal, not project) +.hermes/ diff --git a/.hermes/plans/2026-06-18_monitoring_overhaul.md b/.hermes/plans/2026-06-18_monitoring_overhaul.md deleted file mode 100644 index c4db25c..0000000 --- a/.hermes/plans/2026-06-18_monitoring_overhaul.md +++ /dev/null @@ -1,238 +0,0 @@ -# 监控系统全面升级实施方案 - -> **For Hermes:** Execute phase by phase, each phase is independently deployable. - -**Goal:** 构建 4 大监控模块:主机监控、中间件监控、SNMP 设备监控、站点拨测 - -**架构:** Agent 扩展采集器 → Backend 新增路由/处理器 → 前端新建监控面板 - -**Tech Stack:** Go (Agent/Backend), React+TypeScript (Frontend), MySQL+Redis (Storage), gosnmp (SNMP library) - ---- - -## Phase 1: Agent 指标扩展 + 主机监控仪表盘 🖥️ - -### Task 1.1: Agent 新增采集器 - 网络指标 -**Files:** -- Create: `agent/collector/network.go` -- Modify: `agent/model/model.go` -- Modify: `agent/main.go` - -**网络指标采集:** -- 并发连接数 (ESTABLISHED via /proc/net/sockstat) -- TIME_WAIT 连接数 -- 网卡 rx_bytes/s, tx_bytes/s(两次采集差值 / 间隔) -- 网卡名列表和速率 - -### Task 1.2: Agent 新增采集器 - 磁盘 IO -**Files:** -- Create: `agent/collector/diskio.go` -- Modify: `agent/model/model.go` - -**磁盘 IO 指标:** -- 读取 BPS (bytes/s) -- 写入 BPS (bytes/s) -- 读取 IOPS (count/s) -- 写入 IOPS (count/s) - -### Task 1.3: Agent 新增采集器 - 进程监控 -**Files:** -- Create: `agent/collector/process.go` -- Modify: `agent/model/model.go` - -**进程监控:** -- Top N 进程 CPU/内存使用 -- 进程总数 -- 僵尸进程数 - -### Task 1.4: Agent 新增采集器 - 系统信息(启动时一次) -**Files:** -- Create: `agent/collector/system.go` -- Modify: `agent/model/model.go` - -**系统信息:** -- OS 版本 (cat /etc/os-release) -- 内核版本 (uname -r) -- 运行时间 (uptime) -- ulimit -n (nofile 上限) -- ulimit -u (nproc 上限) - -### Task 1.5: Backend - 扩展 AgentReport 模型 -**Files:** -- Modify: `backend/internal/models/agent.go` -- Modify: `backend/internal/api/handlers/agent.go` (ReceiveReport) - -**扩展字段:** -- NetworkInfo JSON (net_connections, net_rx_bps, net_tx_bps, nic_name) -- DiskIOInfo JSON (read_bps, write_bps, read_iops, write_iops) -- ProcessInfo JSON (top_processes, total_proc, zombie_count) -- SystemInfo JSON (os_version, kernel, uptime, ulimit_nofile, ulimit_nproc) - -### Task 1.6: Backend - 主机监控 API -**Files:** -- Create: `backend/internal/api/handlers/host_monitor.go` -- Modify: `backend/internal/api/routes/routes.go` - -**API 端点:** -- `GET /api/v1/monitor/host/:hostname/overview` - 主机概览 -- `GET /api/v1/monitor/host/:hostname/metrics?metric=cpu&from=&to=` - 历史指标 -- `GET /api/v1/monitor/host/:hostname/processes` - 进程列表 -- `GET /api/v1/monitor/host/:hostname/network` - 网络指标 - -### Task 1.7: Frontend - 主机监控面板 -**Files:** -- Create: `frontend/src/pages/HostMonitor.tsx` -- Create: `frontend/src/components/monitor/HostCard.tsx` -- Create: `frontend/src/components/monitor/MetricChart.tsx` -- Modify: `frontend/src/App.tsx` (add route /monitor/host) - -**展示内容:** -- 主机卡片:CPU/内存/磁盘使用率仪表盘 -- 趋势图:CPU/内存/磁盘 5m/1h/6h/24h -- 网络:并发连接数、网卡带宽趋势 -- 进程 TOP 10 表格 - ---- - -## Phase 2: 中间件监控 🔌 - -### Task 2.1: Agent 新增采集器 - Redis -**Files:** -- Create: `agent/collector/redis.go` -- Modify: `agent/model/model.go` - -**Redis 指标(需要配置 host:port:password):** -- 连接数 (connected_clients) -- 内存使用 (used_memory) -- 命中率 (keyspace_hits / (hits + misses)) -- Key 数量 -- 慢查询数 -- QPS (instantaneous_ops_per_sec) - -### Task 2.2: Agent 新增采集器 - MySQL -**Files:** -- Create: `agent/collector/mysql.go` - -**MySQL 指标:** -- 当前连接数 / 最大连接数 -- QPS (Questions 差值) -- 慢查询数 -- Buffer Pool 命中率 -- 复制延迟(如有) - -### Task 2.3: Backend - 中间件监控 API + 配置管理 -**Files:** -- Create: `backend/internal/api/handlers/middleware_monitor.go` -- Create: `backend/internal/models/middleware_config.go` (RedisConfig, MySQLConfig) -- Modify: `backend/internal/api/routes/routes.go` - -**API:** -- `POST /api/v1/monitor/middleware/config` - 配置中间件认证 -- `GET /api/v1/monitor/middleware/redis/:hostname` - Redis 指标 -- `GET /api/v1/monitor/middleware/mysql/:hostname` - MySQL 指标 - -### Task 2.4: Frontend - 中间件监控面板 -**Files:** -- Create: `frontend/src/pages/MiddlewareMonitor.tsx` - ---- - -## Phase 3: SNMP 设备监控 📡 - -### Task 3.1: Backend - SNMP 采集引擎 + OID 模板系统 -**Files:** -- Create: `backend/internal/api/handlers/snmp_monitor.go` -- Create: `backend/internal/models/snmp_template.go` -- Create: `backend/pkg/snmp/collector.go` (uses gosnmp) -- Add dep: `github.com/gosnmp/gosnmp` - -**SNMP 模板系统:** -- 模板包含一组 OID → 指标名映射 -- 预置模板:Cisco 交换机、H3C 交换机、华为交换机、服务器 iLO/iDRAC -- 用户可自定义 OID 模板 - -### Task 3.2: Backend - SNMP 定时采集任务 -**Files:** -- Create: `backend/internal/scheduler/snmp_scheduler.go` - -**定时采集:** -- 每 5 分钟对配置的 SNMP 设备执行采集 -- 存储到 agent_reports 表(type=snmp) - -### Task 3.3: Frontend - SNMP 设备管理 + 监控面板 -**Files:** -- Create: `frontend/src/pages/SNMPMonitor.tsx` -- Create: `frontend/src/components/monitor/SNMPDeviceCard.tsx` - ---- - -## Phase 4: 站点拨测 🌐 - -### Task 4.1: Backend - 拨测引擎 -**Files:** -- Create: `backend/internal/api/handlers/site_monitor.go` -- Create: `backend/internal/models/site_task.go` -- Create: `backend/pkg/probe/` (HTTP, PING, WebSocket, DNS, TCP, UDP, SMTP, POP3, FTP probes) - -**8 种拨测类型实现:** -- HTTP(S): GET/POST,检查状态码 + 响应时间 + 正则匹配 body -- PING: ICMP echo -- WebSocket: 连接 + 心跳 -- DNS: 解析时间 + 结果验证 -- TCP: 端口连通性 -- UDP: 端口连通性 -- SMTP: 连接 + STARTTLS -- POP3: 连接 + 认证 -- FTP: 连接 + 登录 - -### Task 4.2: Backend - 拨测定时任务 -**Files:** -- Modify: `backend/internal/scheduler/` (add probe scheduler) - -### Task 4.3: Frontend - 站点拨测管理面板 -**Files:** -- Create: `frontend/src/pages/SiteMonitor.tsx` -- Create: `frontend/src/components/monitor/ProbeTaskForm.tsx` -- Create: `frontend/src/components/monitor/ProbeResultChart.tsx` - -**展示内容:** -- 拨测任务列表(类型、URL、频率、状态) -- 响应时间趋势图 -- 可用率统计 -- 告警配置 - ---- - -## Phase 5: 导航重构 🧭 - -### Task 5.1: 导航结构重组 -**Files:** -- Modify: `frontend/src/components/layout/MainLayout.tsx` 或 Sidebar - -**新导航结构:** -``` -📊 监控告警 - ├── 🖥️ 主机监控 /monitor/host - ├── 🔌 中间件监控 /monitor/middleware - ├── 📡 SNMP 监控 /monitor/snmp - ├── 🌐 站点拨测 /monitor/site - ├── 📈 Agent 监控 /agent-monitor (已有) - ├── 🚨 告警中心 /alert-center (已有) - └── 📜 告警规则 /agent-alerts (已有) -``` - ---- - -## 执行顺序 - -1. **Phase 1**(最优先,用户当前最需要) - → Agent 扩展网络/磁盘IO/进程/系统信息 - → 前端主机监控面板 - -2. **Phase 2** → 中间件监控 - -3. **Phase 3** → SNMP 设备监控(较复杂,需 gosnmp 依赖) - -4. **Phase 4** → 站点拨测 - -5. **Phase 5** → 导航重构(收尾) diff --git a/CLAUDE.md b/CLAUDE.md index c89199f..1f6e66d 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -10,43 +10,113 @@ **AIOps** 是一个企业级智能运维平台,聚焦三大核心能力: 1. **资产管理** — 服务器管理、云资源(云账号/域名/账单)、K8s 集群 -2. **监控告警** — Agent 采集指标、告警引擎(资源阈值/离线检测)、告警中心、日志能力、链路追踪、监控大屏 -3. **自动化运维 / AIOps** — CronJob/Script/Ansible 自动化、资源申请审批、AI 智能运维(告警分析/故障诊断/脚本生成) +2. **监控告警** — Agent 采集指标、告警引擎(资源阈值/离线检测)、告警中心、链路追踪、监控大屏 +3. **自动化运维 / AIOps** — 流水线 CI/CD、定时任务/脚本库、远程执行(Go-native SSH)、资源申请审批、AI 智能运维(智能助手/告警分析/容量预测) ### 核心特性 - **Agent 双通道** — 指标采集通道(10s 上报 `/proc`)+ 远程任务通道(5s 轮询执行命令) - **LDAP 集成** — 配置管理、用户导入、OU 管理、LDAP 用户 CRUD -- **资源申请审批** — 云服务器申请、应用部署申请(Git 地址/端口/Nacos 等配置),动态表单 +- **资源申请审批** — 云服务器申请、应用部署申请,动态表单 - **5 套主题** — CSS 变量驱动,暗色/亮色/紫色/绿色/玫红一键切换 - **WebShell** — WebSocket 终端,在线 SSH 操作服务器 +- **凭证系统 v2** — 7 种统一凭证类型(SSH/Docker/TLS/AKSK/DB/API/Generic),加密存储 +- **CI/CD 流水线** — GitLab CI 风格可视化,阶段色块进度条,实时日志,文件浏览器 +- **Kubectl 终端** — WebSocket + PTY 交互式 K8s 终端,懒加载 kubectl 二进制 ## 技术栈 | 层 | 技术 | 端口 | |---|---|---| -| 后端 | Go 1.21 + Gin + GORM + SQLite (CGO) + JWT + Zap | 8080 | +| 后端 | Go 1.24 + Gin + GORM + MySQL 8.0 + Redis 7 + JWT + Zap | 8080 | | 前端 | React 19 + TypeScript + Vite + Tailwind + shadcn/ui + Zustand + TanStack Query | 5173 | | Agent | Go 1.24 (CGO_ENABLED=0 静态二进制, amd64+arm64) | — | -## 常用命令 +## 三种部署方式 -### 快速启动 +项目通过统一入口 `./run.sh` 支持三种部署方式,适配不同场景: + +### 方式一:独立二进制(`./run.sh build` / `./run.sh binary`) + +前端通过 `go:embed` 嵌入后端二进制,生成单一可执行文件。零外部依赖,直接运行。 ```bash -./run.sh start # 启动前后端 -./run.sh stop # 停止服务 -./run.sh restart # 重启服务 -./run.sh status # 查看服务状态 -./run.sh logs # 查看实时日志 +./run.sh build # 编译独立二进制 → backend/aiops +./run.sh binary # 编译 + 直接启动 +./run.sh build agent # 交叉编译 Agent (amd64+arm64) ``` +**二进制用法:** +```bash +./backend/aiops # 默认启动 (SQLite, 端口 8080) +./backend/aiops --port 9090 # 自定义端口 +./backend/aiops --db-driver mysql --db-host 10.10.10.75 ... # MySQL 模式(需 --redis-driver redis) +./backend/aiops --config config.yaml # 使用配置文件 +``` + +> ⚠️ MySQL 模式必须显式传 `--redis-driver redis`,否则默认 redka(CGO 依赖)在 `CGO_ENABLED=0` 下静默失败。 + +### 方式二:Kubernetes(`./run.sh k8s deploy`) + +在 K8s 集群 `devops` 命名空间部署,单容器 embed 模式,NodePort 30080 暴露。 + +```bash +./run.sh k8s deploy # 构建 Dockerfile.embed 镜像 + 全量部署 (MySQL+Redis+App) +./run.sh k8s upgrade # 重新构建 + 滚动更新(不停机) +./run.sh k8s status # 查看 pods/svc/pvc/ingress +./run.sh k8s logs # 应用日志 (follow) +./run.sh k8s exec # 进入容器 Shell +./run.sh k8s mysql # MySQL CLI +./run.sh k8s redis # Redis CLI +./run.sh k8s scale 3 # 扩缩容 +./run.sh k8s port-forward # 端口转发 localhost:8080 → svc/aiops +./run.sh k8s delete # 清理资源(保留 PVC) +``` + +**K8s 部署文件** (`deploy/k8s/`): namespace.yaml / secret.yaml / configmap.yaml / mysql.yaml / redis.yaml / deployment.yaml / ingress.yaml + +> ⚠️ 健康检查用 `/version`(无 DB 依赖),不用 `/health`(启动早期可能不响应)。 + +### 方式三:Docker Compose(`./run.sh docker up`) + +传统 4 容器部署:`aiops-mysql` + `aiops-redis` + `aiops-backend` + `aiops-frontend` (nginx)。 + +```bash +./run.sh docker up # 构建 + 启动全部容器 +./run.sh docker down # 停止 + 移除容器 +./run.sh docker build # 仅构建镜像 +./run.sh docker restart # 重启容器 +./run.sh docker logs # 实时日志 +./run.sh docker ps # 容器状态 +./run.sh docker clean # 清理构建缓存 +``` + +**容器清单:** +| 容器 | 镜像 | 端口 | 说明 | +|------|------|------|------| +| `aiops-mysql` | `mysql:8.0` | 3306 | 数据库 | +| `aiops-redis` | `redis:7-alpine` | 6379 | 缓存 | +| `aiops-backend` | `backend/Dockerfile` (3-stage) | 8080 | Go API | +| `aiops-frontend` | `frontend/Dockerfile` (nginx:alpine) | 80 | React SPA | + +### 本地开发(`./run.sh dev`) + +```bash +./run.sh dev # 前后端热重载 (5173 + 8080) +./run.sh stop # 停止 +./run.sh restart # 重启 +./run.sh status # 查看状态 +./run.sh logs # 实时日志 +``` + +## 常用命令 + ### 后端 (backend/) ```bash cd backend -# 编译(每次修改后端必须执行) +# 编译 unset http_proxy https_proxy && export GOPROXY=https://goproxy.cn,direct && GOTOOLCHAIN=local CGO_ENABLED=1 go build -o aiops-server ./cmd/ # 直接运行 @@ -70,14 +140,14 @@ npx tsc --noEmit # 类型检查(提交前必须零错误) ```bash cd agent -# 本地构建(macOS 测试用) +# 本地构建 CGO_ENABLED=0 go build -o aiops-agent . # 交叉编译 GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -o aiops-agent-linux-amd64 . GOOS=linux GOARCH=arm64 CGO_ENABLED=0 go build -o aiops-agent-linux-arm64 . -# 运行 Agent +# 运行 ./aiops-agent --server http://localhost:8080 --token ``` @@ -90,90 +160,81 @@ aiops/ ├── backend/ │ ├── cmd/ │ │ ├── main.go # 应用入口 -│ │ └── seed.go # 种子数据(用户/角色/审批模板/LDAP配置) +│ │ ├── embed.go # go:embed 前端静态资源 +│ │ ├── seed.go # 种子数据 +│ │ └── static/ # embed 目标目录 (必须存在) │ ├── internal/ │ │ ├── config/config.go # Viper 配置 -│ │ ├── models/ # GORM 模型(每模块独立文件) +│ │ ├── models/ # GORM 模型 │ │ └── api/ -│ │ ├── handlers/ # HTTP handler(按模块拆分,每文件 <400 行) -│ │ ├── middleware/auth.go # JWT + Admin 中间件 -│ │ └── routes/routes.go # 路由注册 -│ ├── pkg/database/database.go # DB 连接 + AutoMigrate -│ └── scripts/mock.go # Mock 种子(已废弃) +│ │ ├── handlers/ # HTTP handler +│ │ ├── middleware/ # JWT + Admin + PipelineAccess +│ │ └── routes/ # 路由注册 +│ ├── pkg/ +│ │ ├── database/ # DB 连接 + AutoMigrate +│ │ ├── kubernetesclient/ # 轻量 K8s API 客户端 +│ │ ├── remoteexec/ # Go-native SSH 远程执行 +│ │ └── toolinstaller/ # 工具懒加载 + 镜像回退 +│ └── Dockerfile # 3 阶段构建 (Backend+Agent→Alpine Runtime) │ ├── frontend/ -│ ├── src/ -│ │ ├── components/ -│ │ │ ├── dashboard/ # 仪表盘(统计/图表/最近活动) -│ │ │ ├── server/ # 服务器管理 -│ │ │ ├── cloud/ # 云资源管理 -│ │ │ ├── k8s/ # K8s 集群管理 -│ │ │ ├── deploy/ # 应用发布(CI/CD 流水线) -│ │ │ ├── monitor/ # 监控告警(指标/告警中心/日志/大屏/Agent告警) -│ │ │ ├── automation/ # 自动化运维(CronJob/Script/Ansible) -│ │ │ ├── approval/ # 资源申请审批 -│ │ │ ├── aiops/ # AI 智能运维 -│ │ │ ├── system/ # 系统管理(用户/LDAP/审计) -│ │ │ ├── navigation/ # 站内导航 -│ │ │ └── layout/ # 布局(Sidebar/Header) -│ │ ├── services/ -│ │ │ ├── api.ts # API 定义(按模块分组) -│ │ │ └── http.ts # Axios 封装(拦截器自动注入 Token) -│ │ ├── store/ # Zustand 状态管理 -│ │ ├── hooks/ # React hooks(useConfirm 等) -│ │ └── types/index.ts # 全局类型 -│ └── App.tsx # 路由 + 顶层 Provider +│ ├── src/components/ +│ │ ├── dashboard/ # 仪表盘 +│ │ ├── server/ # 服务器管理 +│ │ ├── cloud/ # 云资源 +│ │ ├── k8s/ # K8s 集群管理 +│ │ ├── deploy/ # 应用发布(流水线/发布配置/发布权限/工具配置) +│ │ ├── monitor/ # 监控告警 +│ │ ├── automation/ # 定时任务/脚本库/远程执行 +│ │ ├── approval/ # 资源申请审批 +│ │ ├── aiops/ # AI 智能运维(助手/告警分析/容量预测) +│ │ ├── system/ # 系统管理 +│ │ └── layout/ # Sidebar/Header +│ ├── src/services/ +│ │ ├── api.ts # API 定义 +│ │ └── http.ts # http 封装(自动解包 data + Token 注入) +│ └── Dockerfile # Node build → nginx:alpine │ ├── agent/ # 监控 Agent(独立 Go module) -│ ├── main.go # CLI 入口 -│ ├── collector/ # /proc 采集器(CPU/内存/磁盘/端口) -│ ├── task/ # 远程任务执行器(command/script) -│ ├── reporter/http.go # HTTP 上报 -│ └── model/model.go # 数据结构 +│ ├── collector/ # /proc 采集器 +│ ├── task/ # 远程任务执行器 +│ └── reporter/ # HTTP 上报 │ -└── run.sh # 一键启动脚本 +├── deploy/k8s/ # K8s 部署清单 (devops 命名空间) +├── Dockerfile.embed # 4 阶段 Embed 镜像 (前端→后端→Agent→Runtime) +├── docker-compose.yml # 4 容器部署 (mysql+redis+backend+frontend) +├── run.sh # 统一入口脚本 +└── Makefile # 快捷命令 ``` -### 后端分层 - -``` -handlers/ (HTTP 处理) → models/ (GORM 数据操作) - ↓ -middleware/auth.go (JWT 验证) -``` - -**新增模块 4 步**: -1. `models/xxx.go` — 定义 GORM 模型 -2. `handlers/xxx.go` — 实现 handler(所有返回必须用 `models.Response{Code:200}` 包裹) -3. `routes/routes.go` — 注册路由 -4. `pkg/database/database.go` — 添加 AutoMigrate - ### API 响应格式 ```go -// 统一响应(所有 handler 必须遵循) +// 统一响应 type Response struct { Code int `json:"code"` Message string `json:"message"` Data interface{} `json:"data"` } -// 列表响应(Data 内层) +// 列表响应 type ListResponse struct { List interface{} `json:"list"` Total int64 `json:"total"` } ``` -**前端 http.ts 已自动提取 `.data`**,所以组件中拿到的是 `Response.Data`。列表 API 返回 `{list, total}`,组件中需 `.list` 提取数组。 +**前端 http.ts 已自动提取 `.data`**,组件中拿到的就是 `Response.Data`。列表返回 `{list, total}`。 ### 认证流程 ``` -Login(本地/LDAP fallback) → JWT Token → 前端 Zustand persist 存储 -→ http.ts 自动注入 Bearer → JWTAuth 中间件验证 → AdminAuth 中间件(管理类路由) +Login(本地/LDAP fallback) → JWT Token → 前端 Zustand persist + localStorage 双写 +→ http.ts 自动注入 Bearer → JWTAuth 中间件 → AdminAuth 中间件(管理类路由) ``` +WebSocket 无法设自定义 header → 后端 JWTAuth 支持 `?token=` query param 回退。 + ### Agent 双通道架构 ``` @@ -181,70 +242,48 @@ Login(本地/LDAP fallback) → JWT Token → 前端 Zustand persist 存储 任务通道: ticker(5s) → GET /agent/tasks/poll → execute → POST /agent/tasks/:id/result ``` -### 告警引擎 - -- 内嵌后端 cron 定时器,每分钟扫描 AgentReport -- **资源阈值告警** — CPU/内存/磁盘超阈值(需配置规则) -- **主机离线告警** — 内置检测(3 分钟无数据上报即告警,不需配置规则) -- **端口告警** — 监控端口消失 - ## 开发规范 ### ⛔ 文件大小红线 | 类型 | 上限 | 超出处理 | |------|------|----------| -| Go handler | **400 行** | 按 sub-domain 拆分到独立文件(同一 package) | +| Go handler | **400 行** | 按 sub-domain 拆分 | | Go model | **300 行** | 按模块拆分 | -| React 组件 (.tsx) | **700 行** | 提取子组件到同目录 | +| React 组件 (.tsx) | **700 行** | 提取子组件 | | 任何文件 | **700 行(硬上限)** | 必须拆分 | -```bash -# 检查超限文件 -find backend -name "*.go" -not -path "*/vendor/*" | xargs wc -l | awk '$1 > 400 && $2 != "total"' -find frontend/src -name "*.tsx" -o -name "*.ts" | xargs wc -l | awk '$1 > 700 && $2 != "total"' -``` - ### ⛔ Go 代码规范 -1. **所有 handler 返回必须用 `models.Response{Code:200, Data:...}` 包裹** — 前端 `http.ts` 从 `json.data` 取值,裸 `gin.H{}` 会导致前端拿到 undefined 静默失败 -2. **编译命令**(每次必须): - ```bash - cd backend && unset http_proxy https_proxy && export GOPROXY=https://goproxy.cn,direct && GOTOOLCHAIN=local CGO_ENABLED=1 go build -o aiops-server ./cmd/ - ``` -3. **新增 handler 不绑 model** — 用独立 request struct 接收 `ShouldBindJSON`,再映射到 GORM model -4. **GORM 指针字段必须解引用** — model 中 `*int`/`*string` 字段传给 `fmt.Sprintf` 时先 `*field` -5. **SQLite 必须 CGO_ENABLED=1**(macOS 默认开) +1. **所有 handler 返回必须用 `models.Response{Code:200, Data:...}` 包裹** +2. **编译命令**: `unset proxy + GOPROXY=goproxy.cn + GOTOOLCHAIN=local + CGO_ENABLED=1` +3. **新增 handler 不绑 model** — 用独立 request struct +4. **GORM 指针字段必须解引用** — `*field` 后再用 +5. **Update handler 禁止复用 CreateRequest** — 用 `map[string]interface{}` 接收 ### ⛔ React 前端规范 -1. **API 列表响应解包** — 后端返回 `{code, data: {list: T[], total: N}}`,http.ts 提取 `.data` 后仍是 `{list, total}` 对象,组件中必须 `.list` 提取数组 -2. **禁止 `window.confirm()`/`alert()`** — 用 `ConfirmProvider`(`useConfirm()` hook)替代,用 `toast.error()`/`toast.success()` 替代 alert -3. **Radix Dialog 必须有 ``** — 至少加 `` -4. **Token 不在 localStorage** — 用 `useUserStore.getState().token`(Zustand persist) -5. **新增组件 2 步**: API 层(`services/api.ts` 添加) → 组件+路由(`App.tsx` 加 Route,`Sidebar.tsx` 加菜单) +1. **API 列表响应解包** — `http.ts` 自动取 `.data`,列表返回 `{list, total}` +2. **禁止 `window.confirm()`/`alert()`** — 用 `useConfirm()` + `toast` +3. **Radix Dialog 必须有 ``** +4. **Token 双保险**: `useUserStore.getState().token || localStorage.getItem('token')` ### ⛔ UI 设计原则 -- **能去掉的都去掉** — 不要多余边框、高亮框、装饰性分隔线 +- **能去掉的都去掉** — 不要多余边框、装饰线 - **按钮文案 2-4 字** — "批量导入" 而非 "批量导入用户" -- **不留占位按钮** — 功能没做好就不放按钮,不要 `toast.info('开发中')` +- **不留占位按钮** — 功能没做好就不放按钮 - **页面打开即用** — 不需要额外"新建"按钮跳转 -- **主题感知** — 用 CSS 变量 `bg-[var(--dg-bg-secondary)]`,不用硬编码颜色 -- **表单操作按钮在字段下方** — 用 `mt-4 pt-4 border-t` 分隔,不放 Card 标题右侧 -- **主动排查同类问题** — 用户报一个 UI 问题,全局搜索同类一次性修复 +- **主题感知** — 用 CSS 变量 `var(--dg-xxx)`,不硬编码颜色 ### ⛔ 通用开发流程 ``` -分析需求 → 写代码 → go build + tsc --noEmit → ./run.sh restart → 浏览器验证 → git commit + push +分析需求 → 写代码 → go build + tsc --noEmit → ./run.sh docker up → curl 验证 → git commit + push ``` -- **修改前端后必须在浏览器实际测试**,不能只说"刷新试试" -- **提交前编译验证**:后端 `go build ./...`,前端 `npx tsc --noEmit && npm run build` -- **Git 提交**: `git add -A && git commit -m "feat: 描述" && git push origin master` +- **代码改完不算完成,端到端验证通过才算完成** - **大变更前先 git commit** — 方便回滚 -- **开发日志**: 每次开发后更新 `docs/dev-log.md` ## 默认账号 @@ -257,26 +296,12 @@ find frontend/src -name "*.tsx" -o -name "*.ts" | xargs wc -l | awk '$1 > 700 && ⚠️ **生产环境请修改默认密码** -## 主题系统 - -5 套预设主题(CSS 变量驱动): - -| Key | 名称 | 场景 | -|-----|------|------| -| `ocean-deep` | 深海蓝(默认) | 暗色主界面 | -| `light-professional` | 专业亮色 | 亮色模式 | -| `midnight-purple` | 午夜紫 | 个性化 | -| `forest-green` | 森林绿 | 个性化 | -| `dark-rose` | 暗夜玫红 | 个性化 | - -所有组件必须用 `var(--dg-xxx)` 变量,禁止硬编码颜色值。 - ## 访问地址 -- 前端:`http://localhost:5173` +- 前端:`http://localhost:5173` (dev) / `http://localhost:80` (docker) - 后端:`http://localhost:8080` - 健康检查:`http://localhost:8080/health` -- Agent 下载:`http://localhost:8080/agent/arch` +- K8s:`http://:30080` ## 常见陷阱速查 @@ -285,29 +310,32 @@ find frontend/src -name "*.tsx" -o -name "*.ts" | xargs wc -l | awk '$1 > 700 && | Go1 | go build 超时 | `unset proxy + GOPROXY=goproxy.cn + GOTOOLCHAIN=local` | | Go2 | handler 不包裹 Response | 必须 `models.Response{Code:200, Data:...}` | | Go3 | GORM 指针字段 | `*field` 解引用后再用 | -| Go4 | GORM First() 连续查带上次 ID | 用 `Take()` | -| Go5 | go map literal 不能有 duplicate key | 检查重复键 | +| Go4 | Update 复用 CreateRequest | 用 `map[string]interface{}` | +| Go5 | CGO_ENABLED=0 + redka → 缓存静默失败 | `--redis-driver redis` | | FE1 | 白屏无堆栈 | 90% 是列表 `{list,total}` 未解包 | | FE2 | confirm() 冻结自动化 | 用 `useConfirm()` | -| FE3 | Token 获取 | `useUserStore.getState().token`,不是 localStorage | +| FE3 | Token 获取 | `useUserStore.getState().token` + `localStorage` | | FE4 | Radix Dialog 警告 | 必须有 `` | -| FE5 | browser_click 不触发 toggle | 改用 `browser_console` 注入 `.click()` | -| FE6 | API 字段名不匹配 | 前端 `base_dn` vs 后端 `ou_dn` 类型问题 | +| FE5 | Select.Item 空字符串 value | 用 sentinel 值 `__manual` | +| FE6 | API 字段名不匹配 | 检查前后端命名一致性 | ## 注释规范 新增或修改代码必须写中文注释,注释结尾署名 `// Logan.Li`。 -```go -// ListServers 获取服务器列表 // Logan.Li -func (h *ServerHandler) ListServers(c *gin.Context) { - // 业务逻辑 -} -``` - ## 远程仓库 ``` https://gitee.com/attacker/aiops.git Git 用户: attacker / attacker@gitee.com +分支: main ``` + +## 关键设计决策 + +- **凭证驱动管理** — 不在表单手动输入密码/密钥,用凭证下拉关联(7 种类型统一模型) +- **工具懒加载** — kubectl/maven/nodejs/helm 首次使用时自动下载,国内网络自动优先国内镜像 +- **远程执行** — Ansible 已替换为 Go-native SSH(`pkg/remoteexec/`),零新增依赖 +- **K8s 客户端** — 轻量自研(net/http + crypto/tls),不引入 50MB+ 的 client-go +- **BuildKit cache mount** — Docker 构建从 13min 降至 3sec(二次构建) +- **健康检查用 `/version`** — K8s 中 `/health` 可能依赖 DB,`/version` 始终 200 diff --git a/Makefile b/Makefile index 4841b14..5a017d8 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ # AIOps 智能运维平台 - Makefile # 使用方式: make help .PHONY: help install dev build build-ui build-api build-binary status stop restart logs lint clean \ - docker-up docker-down docker-build docker-logs docker-embed + docker-up docker-down docker-build docker-logs help: @echo "AIOps 智能运维平台 - 可用命令:" @@ -87,10 +87,6 @@ docker-build: docker-logs: docker-compose logs -f -# ==================== Docker 部署(单容器:embed 模式) ==================== -docker-embed: - docker-compose -f docker-compose.embed.yml up -d --build - # ==================== 二进制部署(embed 模式) ==================== build-binary: build-ui @echo "构建单二进制(前端嵌入后端)..." diff --git a/README.md b/README.md index 085c385..7356901 100644 --- a/README.md +++ b/README.md @@ -9,84 +9,82 @@ - Tailwind CSS + shadcn/ui - Zustand (状态管理) / TanStack Query (数据获取) - Recharts (图表) / Lucide React (图标) +- xterm.js (WebSocket 终端) ### 后端 -- Go 1.22+ / Gin Web Framework -- GORM (ORM) / MySQL 8.0+ / Redis +- Go 1.24 / Gin Web Framework +- GORM (ORM) / MySQL 8.0 / Redis 7 - JWT 认证 / Zap 日志 / Viper 配置 -- Swagger API 文档 +- WebSocket (Gorilla) / PTY 终端 (creack/pty) -## 项目结构 +### Agent +- Go 1.24 静态编译 (CGO_ENABLED=0) +- /proc 指标采集 + 远程任务双通道 +- 支持 linux-amd64 / linux-arm64 / darwin-arm64 -``` -aiops/ -├── frontend/ # 前端项目 (React + TypeScript) -│ ├── src/ -│ │ ├── components/ # 组件 (dashboard/server/k8s/monitor/deploy/aiops/...) -│ │ ├── lib/ # 工具函数 -│ │ ├── store/ # 状态管理 -│ │ ├── types/ # TypeScript 类型定义 -│ │ ├── services/ # API 服务 -│ │ └── hooks/ # 自定义 Hooks -│ ├── package.json -│ └── vite.config.ts -│ -├── backend/ # 后端项目 (Go + Gin) -│ ├── cmd/ # 应用入口 -│ ├── internal/ -│ │ ├── api/ # HTTP 处理器、中间件、路由 -│ │ ├── config/ # 配置管理 -│ │ └── models/ # 数据模型 -│ ├── pkg/ # 公共包 (database/logger) -│ ├── scripts/ # 初始化脚本 -│ ├── go.mod -│ └── Makefile -│ -├── agent/ # Agent 监控服务 -│ ├── cmd/ # Agent 入口 -│ ├── internal/ # Agent 内部逻辑 -│ └── config/ # Agent 配置 -│ -├── docs/ # 设计文档 -│ ├── PDD_PLAN.md # 产品设计文档 -│ ├── ROADMAP.md # 路线图 -│ ├── PROJECT_SUMMARY.md # 项目总结 -│ └── BACKEND_SUMMARY.md # 后端说明 -│ -└── README.md -``` +## 三种部署方式 + +| 方式 | 命令 | 架构 | 适用场景 | +|------|------|------|----------| +| **① 独立二进制** | `./run.sh build` → `./run.sh binary` | 单文件,前后端一体 | 无 Docker/K8s 环境 | +| **② Kubernetes** | `./run.sh k8s deploy` | Embed 单容器 + MySQL/Redis StatefulSet | 生产集群,devops 命名空间 | +| **③ Docker Compose** | `./run.sh docker up` | 4 容器 (MySQL+Redis+Backend+Nginx) | 单机生产,开发/测试 | + +统一入口 `./run.sh`,详见 `./run.sh help`。 ## 快速开始 -### 前端 - -```bash -cd frontend -npm install -npm run dev # 开发模式 http://localhost:5173 -npm run build # 生产构建 -``` - -### 后端 - -```bash -cd backend -cp config.yaml.example config.yaml -go mod download -go run cmd/main.go # http://localhost:8080 -``` - ### Docker Compose 部署 ```bash -# 一键启动全部服务 (前端 + 后端 + MySQL + Redis + Agent) -docker compose up -d +# 一键启动全部服务 (MySQL + Redis + 后端 + Nginx 前端) +./run.sh docker up -# 查看服务状态 -docker compose ps +# 访问 +# 前端: http://localhost:80 +# 后端: http://localhost:8080 +# 健康检查: http://localhost:8080/health -# 停止服务 -docker compose down +# 管理 +./run.sh docker logs # 查看日志 +./run.sh docker ps # 容器状态 +./run.sh docker down # 停止 +``` + +### 独立二进制部署 + +```bash +# 编译(前端自动嵌入) +./run.sh build + +# 启动 +./backend/aiops # 默认 SQLite, 端口 8080 +./backend/aiops --port 9090 # 自定义端口 +./backend/aiops --db-driver mysql --db-host ... # MySQL 模式 +``` + +### Kubernetes 部署 + +```bash +# 一键部署到 devops 命名空间 +./run.sh k8s deploy + +# 访问: http://:30080 + +# 运维 +./run.sh k8s status # 资源状态 +./run.sh k8s logs # 应用日志 +./run.sh k8s upgrade # 滚动更新 +``` + +### 本地开发 + +```bash +./run.sh dev # 前端 :5173 + 后端 :8080 (热重载) + +# 单独启动 +cd frontend && npm run dev +cd backend && go run ./cmd/ ``` ### 默认账号 @@ -94,19 +92,55 @@ docker compose down - 用户名: `admin` - 密码: `123456` +## 项目结构 + +``` +aiops/ +├── frontend/ # 前端 (React + TypeScript) +│ ├── src/components/ # dashboard/server/k8s/monitor/deploy/aiops... +│ ├── src/services/ # API + HTTP 封装 +│ ├── src/store/ # Zustand 状态管理 +│ └── Dockerfile # nginx:alpine 镜像 +│ +├── backend/ # 后端 (Go + Gin) +│ ├── cmd/ # 入口 (main + embed + seed + static/) +│ ├── internal/api/ # handlers / middleware / routes +│ ├── internal/models/ # GORM 数据模型 +│ ├── pkg/ # 公共包 (database/kubernetesclient/remoteexec/toolinstaller) +│ └── Dockerfile # 3 阶段构建 (Go build → Agent → Alpine Runtime) +│ +├── agent/ # 监控 Agent +│ ├── collector/ # /proc 指标采集 +│ ├── task/ # 远程任务执行 +│ └── reporter/ # HTTP 上报 +│ +├── deploy/k8s/ # Kubernetes 部署清单 +│ ├── namespace.yaml # devops 命名空间 +│ ├── secret.yaml # 密钥 +│ ├── configmap.yaml # 配置 +│ ├── mysql.yaml # MySQL StatefulSet +│ ├── redis.yaml # Redis StatefulSet +│ ├── deployment.yaml # AIOps Deployment + NodePort Service +│ └── ingress.yaml # Ingress 路由 +│ +├── docker-compose.yml # Docker Compose 4 容器编排 +├── Dockerfile.embed # Embed 单容器镜像 (前端→后端→Agent→Runtime) +├── run.sh # 统一入口脚本 +└── Makefile # 快捷命令 +``` + ## 核心功能 -| 模块 | 说明 | 优先级 | -|------|------|--------| -| 仪表盘 | 成本统计、告警聚合、Top资源、SSL提醒 | P0 | -| 资产管理 | 服务器CRUD、批量导入、WebShell、云账号 | P0 | -| Kubernetes | 集群/节点/工作负载、拓扑可视化 | P0 | -| 应用发布 | 流水线管理、发布审批、回滚 | P0 | -| 监控中心 | 监控大屏、资源监控、链路追踪、告警中心、数据源 | P0 | -| 自动化运维 | 定时任务、脚本库、Ansible | P1 | -| AIOps智能 | AI助手、Agent监控、告警分析、脚本生成、故障诊断 | P0 | -| 资源申请 | 资源申请审批、配额管理 | P1 | -| 系统管理 | 用户权限、操作审计、系统设置 | P1 | +| 模块 | 说明 | +|------|------| +| 仪表盘 | 成本统计、告警聚合、Top 资源、SSL 提醒 | +| 资产管理 | 服务器 CRUD、批量导入、WebShell、云账号/域名/账单、K8s 集群 | +| 应用发布 | CI/CD 流水线(GitLab CI 风格可视化)、发布配置、发布权限、工具配置 | +| 监控中心 | 监控大屏、指标监控、链路追踪、告警中心、数据源 | +| 自动化运维 | 定时任务、脚本库(Shell/Python)、远程执行(Go-native SSH) | +| AIOps 智能 | AI 智能助手、告警分析、容量预测 | +| 资源申请 | 云服务器/应用部署申请审批 | +| 系统管理 | 用户管理、角色权限、操作审计、终端审计、凭证配置、系统设置 | ## License diff --git a/docker-compose.embed.yml b/docker-compose.embed.yml deleted file mode 100644 index 3f3feea..0000000 --- a/docker-compose.embed.yml +++ /dev/null @@ -1,91 +0,0 @@ -# ============================================================ -# AIOps 单容器 docker-compose(embed 模式) -# 前端嵌入后端二进制,不需要独立 nginx 容器 -# 用法: docker-compose -f docker-compose.embed.yml up -d --build -# 署名 Logan.Li -# ============================================================ -version: '3.8' - -services: - mysql: - image: mysql:8.0 - container_name: aiops-mysql - restart: unless-stopped - environment: - MYSQL_ROOT_PASSWORD: rootpassword - MYSQL_DATABASE: aiops - MYSQL_USER: aiops - MYSQL_PASSWORD: aiops_pass_2026 - TZ: Asia/Shanghai - ports: - - "3306:3306" - volumes: - - mysql_data:/var/lib/mysql - command: > - --default-authentication-plugin=mysql_native_password - --character-set-server=utf8mb4 - --collation-server=utf8mb4_unicode_ci - healthcheck: - test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-uroot", "-p$$MYSQL_ROOT_PASSWORD"] - interval: 10s - timeout: 5s - retries: 10 - start_period: 30s - networks: - - aiops-network - - redis: - image: redis:7-alpine - container_name: aiops-redis - restart: unless-stopped - ports: - - "6379:6379" - volumes: - - redis_data:/data - command: redis-server --appendonly yes - healthcheck: - test: ["CMD", "redis-cli", "ping"] - interval: 10s - timeout: 5s - retries: 5 - networks: - - aiops-network - - # 单容器:后端 API (:8080) + 嵌入前端 (:8080) - # nginx 不再需要,gin 直接服务静态文件 - aiops: - build: - context: . - dockerfile: backend/Dockerfile.embed - container_name: aiops-app - restart: unless-stopped - ports: - - "80:8080" # 前端 + API 都走 8080 - - "8080:8080" # 也可以直接访问 8080 - volumes: - - ./backend/config.yaml:/app/config.yaml - - app_logs:/app/logs - - app_uploads:/app/uploads - depends_on: - mysql: - condition: service_healthy - redis: - condition: service_healthy - healthcheck: - test: ["CMD", "curl", "-f", "http://localhost:8080/health"] - interval: 30s - timeout: 10s - retries: 3 - start_period: 40s - networks: - - aiops-network - -volumes: - mysql_data: - redis_data: - app_logs: - app_uploads: - -networks: - aiops-network: - driver: bridge