mirror of
https://github.com/Awuqing/BackupX.git
synced 2026-06-28 13:01:22 +08:00
功能: v2.2 节点池调度 + Grafana Dashboard + 版本漂移 UI (#49)
节点池动态调度(企业集群核心需求): - model.Node 新增 Labels CSV;Node.HasLabel / LabelSet 辅助方法 - model.BackupTask 新增 NodePoolTag;与 NodeID 互斥(校验层拒绝同时设置) - BackupExecutionService.selectPoolNode:匹配标签的在线节点中选"运行中任务最少" 并列按 ID 升序稳定;空池返回 NODE_POOL_EMPTY 让用户立即感知 - 选中节点仅写 BackupRecord,不回写 task.NodeID —— 每次执行重选实现真轮转均衡 Grafana Dashboard(v2.1 指标的可视化闭环): - deploy/grafana/backupx-dashboard.json:11 个面板覆盖概览/时序/容量/集群 - deploy/grafana/README.md:Prometheus 抓取配置 + 告警建议 - release workflow 打包 grafana/ + nginx.conf 到 tar.gz 前端: - 节点列表:Agent 版本 vs Master 不一致时橙红 Tag + Tooltip 提示升级 - 节点列表新增"标签/节点池"列,支持 CSV 编辑 + 并发/带宽一起改 - 任务表单新增 NodePoolTag 输入框,与节点选择器互斥禁用 测试: - model/node_label_test.go:HasLabel / LabelSet / nil 安全 - service/node_pool_scheduler_test.go:负载最低优先 / 空池错误 / nil repo 降级 - go test ./... + npm run build 全绿
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
# v2.2.0 节点池与可视化运维闭环 (2026-04-21)
|
||||
|
||||
## 背景
|
||||
|
||||
v2.1 暴露了 Prometheus `/metrics` + 节点级带宽限速,SRE 已经拿到"看"的能力。本轮补齐"调度"和"可视化"的闭环:
|
||||
|
||||
1. **节点池**:任务不再只能绑定固定节点,还可以按标签动态调度
|
||||
2. **Grafana Dashboard**:v2.1 指标从"裸数据"升级为开箱即用的运维视图
|
||||
3. **Agent 版本漂移 UI**:节点列表一眼看出哪台 Agent 落后于 Master
|
||||
|
||||
## 范围
|
||||
|
||||
- `model.Node.Labels` (CSV) + `model.BackupTask.NodePoolTag`
|
||||
- `BackupExecutionService.selectPoolNode()` — 标签匹配 + 当前运行任务数最少原则
|
||||
- `deploy/grafana/backupx-dashboard.json` — 11 面板对接 v2.1 指标
|
||||
- 前端节点列表显示版本漂移 + 标签/池;任务表单支持节点池输入
|
||||
|
||||
## 架构
|
||||
|
||||
### 1. 节点池调度
|
||||
|
||||
```
|
||||
task.NodeID == 0 && task.NodePoolTag != ""
|
||||
↓
|
||||
selectPoolNode(ctx, tag):
|
||||
1. nodeRepo.List() 过滤 status=online AND HasLabel(tag)
|
||||
2. 无候选 → 返回 NODE_POOL_EMPTY 错误(任务失败,用户立即感知)
|
||||
3. 按 countRunningOnNode(id) 升序选最小负载者
|
||||
4. 并列按 ID 稳定(可预期)
|
||||
↓
|
||||
record.NodeID = chosen.ID (仅本次运行,不回写 task)
|
||||
task.NodeID = chosen.ID (供后续 route/agent 路由逻辑使用)
|
||||
```
|
||||
|
||||
**互斥规则**:`NodeID > 0` 与 `NodePoolTag != ""` 在 Create/Update 校验中被拒绝(`BACKUP_TASK_INVALID`)。固定节点 = 显式路由,节点池 = 动态路由,两者语义互斥。
|
||||
|
||||
**调度不回写 task**:池选出的节点 ID 仅写入 BackupRecord(审计追溯),task.NodeID 仍为 0。这样下次执行会**重新选**负载最低者,实现真正的轮转均衡。
|
||||
|
||||
### 2. Grafana Dashboard
|
||||
|
||||
11 个面板,按语义分组:
|
||||
|
||||
| 区域 | 面板 |
|
||||
|------|------|
|
||||
| 概览(4 stat) | 运行中任务数 / SLA 违约数 / 在线节点数 / 24h 成功率 / 应用版本 |
|
||||
| 时序(4) | 任务执行速率(按状态堆叠)、P50/P95/P99 耗时、产出字节速率、验证/恢复/复制成功率 |
|
||||
| 容量(1) | 存储目标用量 TopN 柱状图 |
|
||||
| 集群(1) | 节点在线状态表(值 0/1 → 红/绿色文本映射) |
|
||||
|
||||
设计要点:
|
||||
- `DS_PROMETHEUS` 为 template variable,导入时让用户选数据源
|
||||
- 默认 refresh `30s`,与服务端 collector 采样周期一致
|
||||
- SLA 违约 stat 阈值 ≥1 即红色,直接可接 AlertManager
|
||||
|
||||
### 3. Agent 版本漂移 UI
|
||||
|
||||
```
|
||||
renderAgentVersion(agentVer, masterVer):
|
||||
空 agentVer → "-"(未上报)
|
||||
agentVer == masterVer → 原样显示
|
||||
不同 → 橙红 Tag "<agentVer> ≠ <masterVer>" + Tooltip 建议升级
|
||||
```
|
||||
|
||||
`masterVer` 通过 `/api/system/info` 已有接口获得,前端无需新增 API。
|
||||
|
||||
## 测试
|
||||
|
||||
- `model/node_label_test.go` — HasLabel / LabelSet / nil 安全
|
||||
- `service/node_pool_scheduler_test.go` — 负载最低 / 空池报错 / nil repo 降级
|
||||
- 前端 `npm run build` 通过
|
||||
|
||||
## 风险与应对
|
||||
|
||||
| 风险 | 应对 |
|
||||
|------|------|
|
||||
| 节点池在所有节点离线时任务失败 | 明确返回 `NODE_POOL_EMPTY`,用户立即感知并切换固定节点 |
|
||||
| 运行任务数统计成瓶颈 | countRunningOnNode 走 BackupRecord.List({status:running}),规模大时可引入节点级 semaphore 计数器 |
|
||||
| Labels 格式笔误(重复、空格) | `normalizeLabels` 规整 CSV 再入库;前端 Tag 渲染自动 trim |
|
||||
| 版本漂移 UI 误报 dev 分支 | Master 版本取自 main.version ldflags;dev 构建显示 "dev",不会匹配任何 Agent 版本,纯显示意义 |
|
||||
|
||||
## 下轮候选
|
||||
|
||||
- Agent 二进制自更新(远程下发 + 签名验证)
|
||||
- 任务运行前的"节点可达性预检"(TCP/HTTP 探针)
|
||||
- Grafana Loki 集成:把 backup 日志流接入 Loki,配合 Tempo 做端到端追踪
|
||||
Reference in New Issue
Block a user