From 0e29aa2dc18465f7194ac03cb5d509a10969d2d9 Mon Sep 17 00:00:00 2001 From: hezhaohui Date: Tue, 14 Jul 2026 15:01:17 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E8=A1=A5=E5=85=85=E9=A1=B9=E7=9B=AE?= =?UTF-8?q?=E6=96=87=E6=A1=A3=E4=BD=93=E7=B3=BB=EF=BC=8C=E5=AE=8C=E5=96=84?= =?UTF-8?q?=20AI=20=E5=B7=A5=E5=85=B7=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 变更内容: - 新增 AGENTS.md:为 Codex 等 AI 工具提供项目开发指南 - 更新 CLAUDE.md:优化文档阅读层级结构 - 新增 docs/ref/平台需求文档-v3.md:平台整体需求和功能范围 - 新增 docs/ref/架构文档-v3.md:系统架构设计和技术选型 文档阅读层级(P1-P4): - P1: MVP 方案文档(优先阅读) - P2: 原型文档(交互细节) - P3: 架构文档(整体设计) - P4: 需求文档(需求范围) 只有需要时才往下阅读下一层级文档。 --- AGENTS.md | 38 ++ CLAUDE.md | 39 +- docs/ref/平台需求文档-v3.md | 429 +++++++++++++++ docs/ref/架构文档-v3.md | 1008 +++++++++++++++++++++++++++++++++++ 4 files changed, 1499 insertions(+), 15 deletions(-) create mode 100644 AGENTS.md create mode 100644 docs/ref/平台需求文档-v3.md create mode 100644 docs/ref/架构文档-v3.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..268a4a0 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,38 @@ +# AGENTS.md + +## MVP 实现阶段指南 + +在 MVP 实现阶段,解决问题时请遵循以下文档阅读层级(由高到低,只有需要时才往下阅读): + +### 文档阅读层级 + +- **P1 - MVP 方案文档** (`docs/mvp-skeleton-plan.md`) + - 项目骨架结构、模块划分、接口定义 + - 技术实现要点和代码规范 + - **优先阅读**:大部分问题应首先在此文档中寻找答案 + +- **P2 - 原型文档** (`docs/ref/xinfra-prototype.v3.html`) + - 完整的页面交互流程和 UI 规范 + - 组件行为、状态管理、API 调用时机 + - 异常处理和用户体验细节 + - **当需要理解具体交互时阅读** + +- **P3 - 架构文档** (`docs/ref/架构文档-v3.md`) + - 系统架构设计和技术选型 + - 模块划分和依赖关系 + - 数据流向和接口规范 + - **当需要理解整体架构时阅读** + +- **P4 - 需求文档** (`docs/ref/平台需求文档-v3.md`) + - 平台整体需求和功能范围 + - 用户故事和验收标准 + - **当需要明确需求范围时阅读** + +### 实现原则 + +- **先读文档,再看代码**:理解设计意图后再动手实现 +- **层级优先**:P1 能解决的问题不要去看 P2、P3、P4 +- 严格遵循 MVP 文档中定义的目录结构和模块划分 +- 参考原型文档中的交互流程和状态管理 +- 保持代码简洁,聚焦 MVP 核心功能 +- 遵循项目既定的技术栈和编码规范 diff --git a/CLAUDE.md b/CLAUDE.md index 68129b8..a4c155a 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -2,27 +2,36 @@ ## MVP 实现阶段指南 -在 MVP 实现阶段,解决问题时请遵循以下阅读优先级: +在 MVP 实现阶段,解决问题时请遵循以下文档阅读层级(由高到低,只有需要时才往下阅读): -### 1. 优先阅读文档 +### 文档阅读层级 -1. **MVP 方案文档** (`docs/mvp-skeleton-plan.md`) - - 项目骨架结构、模块划分、接口定义 - - 技术实现要点和代码规范 +- **P1 - MVP 方案文档** (`docs/mvp-skeleton-plan.md`) + - 项目骨架结构、模块划分、接口定义 + - 技术实现要点和代码规范 + - **优先阅读**:大部分问题应首先在此文档中寻找答案 -2. **原型文档** (`docs/ref/xinfra-prototype.v3.html`) - - 完整的页面交互流程和 UI 规范 - - 组件行为、状态管理、API 调用时机 - - 异常处理和用户体验细节 +- **P2 - 原型文档** (`docs/ref/xinfra-prototype.v3.html`) + - 完整的页面交互流程和 UI 规范 + - 组件行为、状态管理、API 调用时机 + - 异常处理和用户体验细节 + - **当需要理解具体交互时阅读** -### 2. 理解优先级 +- **P3 - 架构文档** (`docs/ref/架构文档-v3.md`) + - 系统架构设计和技术选型 + - 模块划分和依赖关系 + - 数据流向和接口规范 + - **当需要理解整体架构时阅读** + +- **P4 - 需求文档** (`docs/ref/平台需求文档-v3.md`) + - 平台整体需求和功能范围 + - 用户故事和验收标准 + - **当需要明确需求范围时阅读** + +### 实现原则 - **先读文档,再看代码**:理解设计意图后再动手实现 -- **原型优先**:当实现细节与原型冲突时,以原型为准 -- **MVP 文档优先**:当架构决策有疑问时,以 MVP 文档为准 - -### 3. 实现原则 - +- **层级优先**:P1 能解决的问题不要去看 P2、P3、P4 - 严格遵循 MVP 文档中定义的目录结构和模块划分 - 参考原型文档中的交互流程和状态管理 - 保持代码简洁,聚焦 MVP 核心功能 diff --git a/docs/ref/平台需求文档-v3.md b/docs/ref/平台需求文档-v3.md new file mode 100644 index 0000000..d4ebd8e --- /dev/null +++ b/docs/ref/平台需求文档-v3.md @@ -0,0 +1,429 @@ +# XINFRA 平台需求文档 + +## 概述 + +XINFRA 是面向多业务线、七机房混合云的统一基础设施管理平台,为 Kodo、LAS、灵矽、LTOKEN、MAAS 等业务线提供容器资源调度、基础服务交付、资源台账、监控告警、配置管理的一站式操作面。 + +**核心目标**: + +| # | 目标 | 说明 | +|---|------|------| +| 1 | 统一纳管 | 所有基础设施操作收敛到平台化界面,屏蔽多机房、多云差异,降低命令行直接操作风险 | +| 2 | 多机房资源池化 | 七机房 RKE2 集群统一纳管,实现跨机房调度与服务发现 | +| 3 | 标准化交付 | 基础组件(MySQL、Redis 等)通过服务卡片 + Ansible Playbook 实现一键标准化部署 | +| 4 | 安全合规 | 主系统登录与运维操作全程审计、SQL 上线必须经过审核、LDAP 统一认证与 SSO | +| 5 | 效率提升 | CD 自动化部署,Ansible 实现基础设施即代码,任务中心实时追踪 | +| 6 | 可观测性 | 整合 Zabbix + VictoriaMetrics + Nightingale + qpass,资源大盘与监控告警全局可见 | + +**设计原则**: + +- **最小权限**:子系统操作默认走 RBAC,主系统以 LDAP 身份 + 管理员角色区分权限,APIKey 遵循最小授权范围 +- **审计留痕**:主系统记录登录事件和运维操作日志,子系统各自维护操作审计 +- **机房就近**:服务部署和数据访问遵循机房就近原则,降低跨机房延迟 +- **平台化自治**:自助申请资源、自助发布、自助诊断,减少人工工单流转 +- **复用优先**:监控、告警等能力优先复用已有基础设施(VictoriaMetrics / Grafana / Zabbix / Nightingale),主系统只自建无法被替代的能力 +- **数据一致性**:资源同步采用"已存在跳过更新"策略,保护人工维护的资产数据,防止被云平台同步覆盖 + +--- + +## 角色模型 + +主系统采用**二维角色模型**:权限维度 × 业务线维度。 + +### 权限维度 + +| 权限角色 | 权限范围 | +|---------|---------| +| 超级管理员 | 全平台所有模块的读写权限,包括集群管理、运维终端、账号权限管理、审计全局查看 | +| 业务操作员 | 本业务线内资源的申请、部署、配置变更;可操作 Wayne/CloudDM/CacheCloud/Apollo 中本业务线的资源 | +| 日志操作员 | 本业务线的日志查看、告警查看、审计记录查看;无写入/变更权限 | +| 访客 | 只读查看资源大盘、服务目录、告警概览;不可执行任何操作 | + +### 业务线维度 + +| 业务线 | 说明 | +|--------|------| +| Kodo | 七牛云存储 | +| LAS | 七牛云直播 | +| 灵矽 | 七牛云 IoT | +| LTOKEN | 七牛云 Token 服务 | +| MAAS | 七牛云模型即服务 | + +### 权限矩阵 + +| 模块 | 超级管理员 | 业务操作员 | 日志操作员 | 访客 | +|------|-----------|-----------|-----------|------| +| 资源大盘 | ✓ 全局 | ✓ 本业务线 | ✓ 本业务线 | ✓ 全局只读 | +| 告警看板 | ✓ 全局 | ✓ 本业务线 | ✓ 本业务线 | ✓ 只读 | +| 集群与节点管理 | ✓ 读写 | ○ 只读 | ○ 只读 | ✗ | +| 多租户管理 | ✓ 读写 | ✗ | ✗ | ✗ | +| Wayne 部署 | ✓ 读写 | ✓ 本业务线 | ○ 只读 | ✗ | +| CloudDM SQL 审核 | ✓ 读写 | ✓ 本业务线 | ○ 只读 | ✗ | +| CacheCloud 缓存 | ✓ 读写 | ✓ 本业务线 | ○ 只读 | ✗ | +| Apollo 配置 | ✓ 读写 | ✓ 本业务线 | ○ 只读 | ✗ | +| 任务中心 | ✓ 全局 | ✓ 本业务线 | ✓ 本业务线 | ✗ | +| 资源台账 | ✓ 读写 | ○ 只读 | ○ 只读 | ✗ | +| 审计面板 | ✓ 全局 | ✗ | ✓ 本业务线 | ✗ | +| 运维终端 | ✓ 仅管理员 | ✗ | ✗ | ✗ | + +> ✓ = 读写权限,○ = 只读权限,✗ = 无权限 + +--- + +## 功能需求 + +### Phase 1 — MVP(当前阶段) + +> 最小可用集:多租户认证 + 子系统对接 + +#### 1.1 平台基础能力 + +##### 统一子系统导航 + +> 作为所有相关子系统的单一入口门户,利用 LDAP 统一账号实现 SSO,用户无需记忆多个地址和重复认证。 + +- [ ] P0 — 已集成系统卡片展示:系统图标、名称、简要说明及 LDAP/SSO 接入状态(已接入/改造中),预留打开链接 +- [ ] P0 — 已集成系统包括:Wayne、CloudDM、CacheCloud、qpass、Grafana、Apollo +- [ ] P0 — SSO 跳转:点击卡片通过 LDAP SSO 跳转至对应子系统,无需重复登录 + +--- + +##### 审计面板(主系统) + +> 记录主系统自身的登录事件和运维操作日志,不聚合子系统操作审计。 + +- [ ] P0 — 登录审计:记录每次 LDAP SSO 登录事件(操作人、时间、来源 IP、目标子系统),支持按时间/操作人/子系统筛选查询 +- [ ] P0 — 运维操作审计:记录主系统运维终端的操作(Ansible Playbook 执行、节点加入、配置变更等),支持按时间/操作人/操作类型筛选 +- [ ] P0 — 权限控制:管理员角色可查看全局;普通用户仅查看自身登录记录 +- [ ] P0 — 审计面板集成到主系统统一门户,无需独立部署 + +--- + +#### 1.2 子系统对接 + +##### Wayne — 容器编排与多集群管理 + +> 底层基于 RKE2 构建七机房 K8s 集群,上层通过 Wayne 平台提供统一的容器管理入口。开发人员通过 Wayne UI 或 API 完成服务部署,无需直接操作 kubectl。 + +**RKE2 集群约束**(基础设施依赖): + +| 约束项 | 说明 | +|--------|------| +| CNI 插件 | Calico BGP(每集群独立 AS 号) | +| 容器运行时 | containerd(不依赖 Docker) | +| 离线部署 | 支持 Air-gap 环境 | +| 集群规模 | 七机房各一套独立集群 | +| 安全加固 | 已通过 CIS Benchmark,默认启用加密和审计 | + +**Wayne 多集群管理**: + +- [ ] P0 — 支持多集群统一管理,通过 Client-Go 连接各机房 RKE2 集群 +- [ ] P0 — 提供表单式(基础模式)和 YAML/JSON 编辑(高级模式)两种 K8s 对象创建方式 +- [ ] P0 — 发布历史记录与一键回滚能力 +- [ ] P0 — 完整审计模块,每次操作留痕,支持自定义 Webhook 回调 +- [ ] P0 — APIKey 开放接口,支持 CI/CD 流水线调用 +- [ ] P0 — 认证支持 DB 内置 + LDAP 混合模式 + +--- + +##### CloudDM / open-cdm — 数据库管理与 SQL 审核 + +> 覆盖数据查询、权限管控、SQL 审核、数据脱敏的全链路能力。所有生产库 SQL 操作必须经过工单流程,无直连通道。 + +- [ ] P0 — 支持 Console + Sidecar 集群部署模式,保证高可用 +- [ ] P0 — 支持 20+ 数据源类型(MySQL、Oracle、PG、ClickHouse、Redis、MongoDB 等) +- [ ] P0 — 内置 54 条 SQL 审核规则,支持规则脚本自定义扩展 +- [ ] P0 — SQL 上线工单流程:编写 → 预检 → DBA 审核 → 执行,支持手动/立即/定时三种执行方式 +- [ ] P0 — 权限控制:资源权限(实例/库/Schema/表粒度)+ 功能权限(RBAC),支持申请/赋予/临时权限 +- [ ] P1 — 数据脱敏能力,对查询结果中的敏感字段进行隐藏或转换 +- [ ] P1 — 数据库 CI/CD:支持 Git Push / WebHook / HttpCall 三种触发方式 +- [ ] P0 — 统一认证:对接企业 LDAP +- [ ] P0 — 全程审计留痕,工单流转记录可追溯 + +--- + +##### CacheCloud — 缓存管理 + +> 支持 Standalone、Sentinel、Cluster 三种 Redis 架构的一站式管理。所有 Redis 场景通过 CacheCloud 统一实例申请和管理。 + +- [ ] P0 — 支持三种 Redis 架构:Standalone(测试)、Sentinel(生产常规,内存 ≤ 6GB)、Cluster(大数据量,内存 > 6GB) +- [ ] P0 — Agent 代理部署在每个宿主机上,管理 Redis 实例生命周期 +- [ ] P0 — 接入层 Nginx 双机房部署 + Virtual IP 双向漂移,保证高可用 +- [ ] P0 — 客户端接入支持 REST API(通用)、Java Jedis/Lettuce SDK、Python 接入 +- [ ] P1 — 跨机房部署(Cross-Room):支持双活,客户端 SDK 自动双写双读和机房切换 +- [ ] P0 — 运维能力:全局统计、工单审批、应用运维、实例运维、数据迁移 +- [ ] P1 — 诊断工具:慢查询分析、连接数诊断、Bigkey 检测 +- [ ] P0 — 报警组件:支持邮件、微信、HTTP 接口集成 +- [ ] P1 — 临时实例自动回收策略,防止资源浪费 + +--- + +##### Apollo — 配置中心管理 + +> 对 Apollo 配置中心进行统一接入和管理,实现在单一 Portal 管理所有机房的配置,确保配置的灰度发布、回滚与变更审计。 + +- [ ] P0 — 核心指标展示:已接入机房数、Apollo Cluster 数量、配置项总数、Namespace 数、接入业务线及同步状态 +- [ ] P0 — 统一入口:提供 Apollo Portal 快捷入口(内部域名 `apollo.xinfra.internal`),LDAP SSO 单点登录 +- [ ] P0 — 机房列表:展示每个机房的 Apollo Cluster、Config Service 地址、承载方式(容器化 K8s Service)、接入业务线和配置项数、运行状态(运行中/灰度接入/建设中/待启动) + +**部署架构约束**: +- Portal + Admin Service:YZH 主中心统一部署 +- Config Service:按机房独立部署(yzh/xs/jf/dallas 等),容器化运行在 K8s 内 +- 数据同步:ConfigDB/PortalDB 部署在 YZH,各机房 Config Service 本地缓存全量配置,网络抖动时降级提供本地缓存 + +--- + +##### CD 自动化部署 + +> 通过 API 接口触发 Wayne 平台执行自动化部署,CI 部分由团队已有 CI 系统负责。 + +- [ ] P0 — 提供 REST API 接口,供外部 CI 系统调用触发 Wayne 部署,传入镜像 tag 和目标环境 +- [ ] P0 — 部署支持多环境(dev / staging / prod),生产环境需审批卡点 +- [ ] P1 — 部署失败时支持自动回滚到上一个稳定版本 +- [ ] P1 — 部署状态回调:支持 Webhook 回调通知外部 CI 系统部署结果 + +> [!info] CI 编译构建由团队已有 CI 系统负责,本平台仅提供 CD 部署接口。 + +--- + + + + +### Phase 2 — 完整版 + +> 监控、配置、任务、基础服务交付的完整能力 + +#### 2.1 监控与可观测性 + +##### 资源大盘 + +> 为平台管理员及业务负责人提供跨机房、多云容器资源的全局快照与健康视图。 + +- [ ] P0 — 展示核心指标:RKE2 集群数量、在线机房数、节点总数及近期增量、CPU 总核数/已分配/分配率、组件实例总数及分类(MySQL、Redis、其他)、进行中的自动化任务数量 +- [ ] P0 — 集群拓扑:以机房为维度,显示各机房节点池方格图(node grid),每个方格代表一台物理机/节点,颜色区分业务线(Kodo、LAS 等),空闲节点用虚线框表示 +- [ ] P0 — 最近任务:列表展示最近 5 条 ansible-playbook 任务的执行状态(成功/执行中/失败)和耗时,快速跳转至任务中心 +- [ ] P1 — 刷新机制:页面自动显示"最近更新于 xx 秒前",支持手动刷新 + +--- + +##### 资源状态看板与告警 + +> 整合物理机、虚机、基础服务三层的健康状态,通过夜莺(Nightingale)统一告警引擎将多源告警标准化展示,提供自上而下的故障定位入口。 + +数据源: +- 物理机硬件 & 网络设备健康:Zabbix(IPMI/温度/电源/风扇/存储) +- 虚机 & 容器 & 业务层指标:VictoriaMetrics(K8s/主机指标/服务可用性探活) +- Nightingale 作为统一告警聚合层,负责去重、收敛、分级(P0/P1/…),按 disaster/high/average 等原始级别映射,推送至 qpass 告警通道 + +- [ ] P0 — 核心统计:物理机总数、虚机总数、基础组件实例总数;P0(Disaster)、P1(High) 及 average 级别告警数量,标注来自 Zabbix 或 VictoriaMetrics +- [ ] P0 — 物理机状态:按机房汇总在线数、健康率(带进度条),标识正常/告警/严重状态 +- [ ] P0 — 虚机状态:按业务线展示 LAS 资源池中的虚机数、CPU 均值及告警状态 +- [ ] P0 — 基础服务状态:覆盖 MySQL、Redis(CacheCloud)、PostgreSQL、openresty 网关等,显示实例数、异常数、可用率 +- [ ] P0 — 当前告警详情:表格列出所有 P0/P1 及 average 级别的实时告警,含级别标签、来源、原始级别、目标对象、告警内容、发生时间 + +--- + +##### 监控、日志与告警集成 + +> 集成公司现有监控与日志基础设施的状态和主要入口,方便从平台直接掌握各子系统健康度。 + +- [ ] P0 — VictoriaMetrics 指标概览:展示七机房采集节点数、活跃时序数量、Prometheus 接口状态、已建 Grafana 仪表盘数 +- [ ] P0 — Zabbix 硬件监控:物理机监控覆盖率、当前告警数、网络设备健康度、存储健康度 +- [ ] P1 — 统一日志与告警流水:以实时日志流形式展示关键系统事件(CMDB 同步、Zabbix 告警、VictoriaMetrics 抓取、ELK 日志接入、qpass 合并推送),类似运维公告板 + +--- + +#### 2.2 配置与任务管理 + +##### 任务中心与自动化执行 + +> 集中展现所有通过 xinfra 发起的 Ansible Playbook 任务或 Wayne 发布任务的执行历史,提供实时日志输出。 + +- [ ] P0 — 任务列表:任务状态(执行中/成功/失败)、任务名称、所用 playbook 名称或任务描述;执行中的任务高亮显示 +- [ ] P0 — 实时日志:通过 WebSocket 流式输出 ansible-playbook 的执行日志,格式包含时间戳、TASK 名称和结果状态(ok/changed/failed),模拟终端输出效果,支持自动滚动 +- [ ] P0 — 历史查询:任务列表支持分页,可查看过往所有任务的执行结果,便于审计和排障 + +--- + +#### 2.3 基础服务与资源管理 + +##### 集群与节点管理 + +> 管理全平台 RKE2 集群的生命周期及节点信息,支持新节点的自动加入。 + +- [ ] P0 — 集群列表:展示集群名称、所在机房/区域、健康状态、节点数、CPU 使用率(进度条)、RKE2 版本、Calico 配置(AS 号等);对存在告警的集群高亮提醒 +- [ ] P0 — 节点列表(集群内):节点主机名、内网 IP、业务线标签(如 `business-line=kodo`)及对应 Taint、节点规格(CPU/内存)、CPU/Mem 使用率(进度条)、节点状态(Ready/资源告警/空闲) +- [ ] P0 — 节点加入向导:通过弹窗交互完成新节点加入——选择目标集群 → 输入节点 IP → 指定归属业务线(自动注入 node-label 和 taint)→ 提交后后台调用 `roles/rke2-node-join` playbook,完成内核参数初始化、containerd 安装、标签/污点写入、加入集群并等待 Ready + +--- + +##### 资源台账管理(CMDB 多云同步) + +> 以 SINA CMDB 为基础数据底座,统一纳管物理机与虚机资源,并通过阿里云、AWS、七牛 LAS 的 OpenAPI 同步云上虚机,形成全量、唯一、可追溯的资源台账。 + +- [ ] P0 — 资源来源统计:资源总数(物理机 + 虚机),各来源(SINA CMDB、阿里云同步、AWS 同步、七牛 LAS 同步)的数量及最近一次同步状态 +- [ ] P0 — 资源台账列表:主机名、资产编号、资源类型(物理机/虚机)、机房/区域、内网 IP、规格、归属业务线、数据来源标签、生命周期状态(production/idle/retired) +- [ ] P0 — 组合筛选:支持按资源类型、数据来源、业务线、状态等条件组合筛选,以及关键字搜索 +- [ ] P0 — 同步与去重策略:各云平台定时增量同步,已存在记录跳过更新(保护 CMDB 人工维护字段),不存在则新增并标记来源 +- [ ] P1 — 创建虚机入口:提供"+ 创建虚机"按钮,跳转或触发七牛 LAS 平台的虚机申请/创建流程(对接 LAS API) + +--- + +##### 服务目录管理(Consul 同步) + +> 聚合各机房已有的 Consul 注册中心服务信息,提供跨机房的服务名、IP、业务标签、健康状态的统一检索视图,不改变各机房 Consul 自身的注册发现链路。 + +- [ ] P0 — 同步机制:定时调用各机房 Consul Catalog API(`/v1/catalog/services`、`/v1/health/service`),按 Datacenter 维度拉取全量服务并汇总入库。同步间隔采用差异化策略:国内机房(YZH/XS/JF)30 秒,海外机房(达拉斯/新加坡/香港/东南亚)根据网络延迟适当延长(建议 60-120 秒),具体间隔待实测后确定 +- [ ] P0 — 服务台账:服务名、所在机房/Datacenter、业务标签、总实例数、健康实例数、示例 IP、整体健康状态 +- [ ] P0 — 筛选与搜索:支持按机房、业务标签、健康状态筛选,以及服务名/IP 搜索 +- [ ] P0 — 统计面板:接入 Consul Datacenter 数量、服务总数(去重)、服务实例总数、健康实例占比、最近同步状态 + +--- + +##### 基础服务目录与一键部署 + +> 将标准化基础组件封装为服务卡片,用户通过界面选择参数,后台调用 Ansible Playbook 自动完成部署和子系统注册。 + +服务卡片规格: + +| 服务 | 可配参数 | 部署后自动注册 | +|------|---------|--------------| +| MySQL | 业务线、架构模式(一主两从/一主一从/单实例)、规格(CPU/内存/磁盘)、版本(8.0/5.7)、实例名称 | open-cdm 数据源 | +| Redis | 业务线、架构模式(Cluster/Sentinel/Standalone)、规格(8G/16G 等)、版本(7.2)、实例名称 | CacheCloud 应用创建 API | +| openresty | 业务线、规格、路由规则 | — | +| dpvs | 业务线、规格、负载策略 | — | +| PgSQL | 业务线、架构模式(流复制主从)、规格、版本 | open-cdm(二期) | + +- [ ] P0 — 服务卡片展示:每个基础组件以卡片形式展示,点击弹出多步骤向导(基础信息 → 规格网络 → 确认部署) +- [ ] P0 — 参数预览:底部实时预览生成的 playbook 调用参数(YAML 格式) +- [ ] P0 — 自动注册:部署完成后自动调用子系统 API 完成注册(MySQL → open-cdm,Redis → CacheCloud) +- [ ] P1 — 扩展性:预留"接入新服务"卡片,允许通过封装新的 Ansible Playbook 并注册到平台扩展服务目录 + +--- + +##### 组件实例台账 + +> 提供所有已部署基础组件的统一台账,展示实例与子系统的关联关系,支持快速检索和运维管理。 + +- [ ] P0 — 列表信息:实例名、组件类型及版本、归属业务线、所在集群、运行状态、子系统注册状态(如 `open-cdm ✓`、`CacheCloud ✓` 或同步中) +- [ ] P0 — 管理操作:提供"管理"快捷操作,可跳转至对应子系统或发起运维任务 +- [ ] P0 — 分页与搜索:支持按实例名称、类型等过滤,分页能力 + +--- + +#### 2.4 Phase 2 验收标准 + +- [ ] 资源大盘:页面加载后 3s 内展示全局指标数据;节点方格图能正确反映各业务线的资源分布 +- [ ] 告警看板:告警数据与 Nightingale 实时同步,延迟 < 30s;支持按级别、来源、机房筛选告警 +- [ ] 集群管理:集群列表数据实时刷新,告警集群高亮标识 +- [ ] 节点加入:节点加入向导从提交到 Ready < 10 分钟 +- [ ] CMDB 同步:同步后资源台账与各云平台实际资源一致,去重逻辑验证通过 +- [ ] Consul 同步:7 个 Datacenter 全部接入;国内机房数据 30 秒内同步 +- [ ] 基础服务部署:MySQL 一键部署单实例 < 5 分钟;Redis 一键部署 Standalone < 3 分钟 +- [ ] 任务中心:执行中任务日志实时推送,延迟 < 1s +- [ ] 部署回滚:回滚操作可在 1 分钟内完成 + +--- + +### Phase 3 — 运维增强 + +> etcd 集群运维、高级监控、运维工具 + +#### 3.1 etcd 集群运维 + +##### etcd 集群部署(kubeadm + etcd operator) + +- [ ] P0 — 集群模板:支持按规格(3/5/7 节点)、磁盘类型(NVMe/SSD)、存储配额生成部署配置 +- [ ] P0 — 部署流程:调用 kubeadm init / etcd-operator API,支持滚动部署和健康检查 +- [ ] P1 — 故障恢复:检测到节点故障时自动替换,数据从健康节点同步 +- [ ] P1 — 滚动升级:支持 etcd 版本升级,逐节点替换并验证 +- [ ] P2 — 自动扩缩:根据集群负载自动调整节点数 + +--- + +#### 3.2 高级监控 + +- [ ] P1 — 告警规则自定义:支持用户自定义监控告警规则 +- [ ] P2 — 异常检测:基于历史数据的智能异常检测 +- [ ] P2 — 容量预测:基于趋势预测资源使用峰值 + +--- + +#### 3.3 运维工具 + +- [ ] P2 — 可视化拓扑:服务依赖关系可视化 +- [ ] P1 — 批量操作:支持批量节点管理、批量配置下发 +- [ ] P2 — 运维工作流:复杂运维操作的流程编排 + +--- + +#### 3.4 Phase 3 验收标准 + +- [ ] etcd 部署:3 节点集群部署 < 15 分钟 +- [ ] 故障恢复:节点故障后自动替换,数据不丢失 +- [ ] 滚动升级:升级过程零停机 +- [ ] 告警规则:用户可自定义告警规则并生效 + +--- + +## 非功能需求 + +### 性能 + +| 指标 | 要求 | +|------|------| +| 资源大盘加载 | P95 < 3s | +| Wayne 页面操作响应 | P95 < 2s | +| CloudDM SQL 审核预检 | 单条 SQL < 3s | +| CacheCloud 实例创建 | Sentinel < 5min,Cluster < 10min | +| 基础服务一键部署 | MySQL/Redis < 15min | +| 任务中心日志推送延迟 | < 1s | +| CI/CD 流水线端到端(代码提交到部署完成) | < 10min(dev 环境) | + +### 可用性 + +| 指标 | 要求 | +|------|------| +| 平台核心服务(Wayne、CloudDM、CacheCloud) | SLA ≥ 99.9% | +| 单集群控制面 | SLA ≥ 99.95% | +| 跨机房网络互联 | SLA ≥ 99.99% | +| Apollo Config Service(单机房故障不影响其他机房) | 本地缓存降级可用 | + +### 多租户隔离 + +- 通过节点标签 + Taint + ResourceQuota 实现业务线间的资源强隔离和配额限制 +- 同一业务线内通过 LimitRange 限制单 Pod 资源上限 + +### 安全 + +- 平台强制 LDAP 认证,所有子系统通过 SSO 统一入口 +- 主系统登录事件与运维操作全程记录审计日志 +- 敏感数据(Secret、密码)加密存储 +- 生产环境禁止使用默认凭证 +- RKE2 默认启用安全审计和加密 +- 网络平面通过 BGP 和防火墙控制 + +### 高可用与容灾 + +- 每个机房独立 RKE2 集群和 Apollo Config Service,单机房故障不影响其他机房 +- 配置下发依赖本地缓存降级 +- 监控告警具备跨机房聚合能力 + +### 可观测性 + +- 各子系统暴露 Metrics 接口,接入 VictoriaMetrics + Grafana +- 关键操作日志统一收集到 ELK 日志平台 +- 告警通道统一(Nightingale → qpass → 企业 IM) + +### 可扩展性 + +- 基础服务目录支持通过封装新 Playbook 快速接入新组件 +- 资源管理支持新增云平台同步源 +- 服务管理可横向扩展至更多 Consul 数据中心 +- 新机房接入时,RKE2 集群部署和 Wayne 注册可在 1 天内完成 + +### 实时性 + +- 任务日志通过 WebSocket 实时推送 +- 监控指标和告警近实时更新 +- 服务同步间隔 30 秒 \ No newline at end of file diff --git a/docs/ref/架构文档-v3.md b/docs/ref/架构文档-v3.md new file mode 100644 index 0000000..8c64786 --- /dev/null +++ b/docs/ref/架构文档-v3.md @@ -0,0 +1,1008 @@ +## 概述 + +本文档定义 XINFRA MVP 阶段的代码骨架结构、模块划分、接口定义和技术实现要点。 + +**技术栈锁定**: +- **后端**: Go 1.21+ / Gin +- **前端**: Vue 3.3+ / Element Plus / Vite +- **数据库**: MySQL 8.0 +- **缓存**: Redis +- **部署**: K8s + Nginx + +**MVP 范围**: +1. 认证(LDAP + SAML + OAuth 2.0) +2. 统一子系统导航(卡片展示 + OAuth 2.0 跳转) +3. 审计面板(登录审计 + 主系统 Ansible 运维操作审计) +4. 子系统对接(仅 OAuth 2.0 跳转,主系统后端向前端返回 Mock 数据) +5. Ansible 调度基础模块 + +> 前端 MVP 参考平台需求文档 #30,无需在 MVP 中实现后端 +--- + +## 项目目录结构 + +``` +xinfra/ +├── frontend/ # 前端 Vue 3 项目,提供用户界面和交互 +│ ├── src/ +│ │ ├── api/ # 封装后端 API 请求,统一处理请求/响应和错误 +│ │ │ ├── auth.ts # 认证相关接口:登录、登出、获取用户信息 +│ │ │ ├── audit.ts # 审计相关接口:查询登录审计、运维操作审计 +│ │ │ ├── subsystem.ts # 子系统相关接口:获取子系统列表、SSO 跳转 URL +│ │ │ └── request.ts # Axios 实例封装:请求拦截器(Token 注入)、响应拦截器(错误处理) +│ │ ├── components/ # 可复用的 UI 组件,按功能模块组织 +│ │ │ ├── Layout/ # 页面布局组件:定义整体页面骨架结构 +│ │ │ │ ├── AppHeader.vue # 顶部导航栏:显示 Logo、用户名、退出登录 +│ │ │ │ ├── AppSidebar.vue # 侧边菜单栏:导航菜单项(仪表盘、子系统、审计) +│ │ │ │ └── AppMain.vue # 主内容区:包裹路由视图的容器 +│ │ │ ├── SubsystemCard.vue # 子系统卡片:展示子系统图标、名称、状态,点击触发 SSO 跳转 +│ │ │ └── AuditLogTable.vue # 审计日志表格:展示审计记录列表,支持分页和筛选 +│ │ ├── composables/ # Vue 3 组合式函数,封装可复用的业务逻辑 +│ │ │ └── useAuth.ts # 认证状态管理:登录、登出、Token 校验、路由守卫 +│ │ ├── layouts/ # 页面布局定义,不同页面可使用不同布局 +│ │ │ └── DefaultLayout.vue # 默认布局:包含顶栏 + 侧边栏 + 内容区 +│ │ ├── router/ # 前端路由配置,定义页面路由映射和导航规则 +│ │ │ └── index.ts # 路由实例:路由表定义、路由守卫(未登录重定向) +│ │ ├── stores/ # Pinia 状态管理,跨组件共享全局状态 +│ │ │ ├── auth.ts # 认证状态:存储 Token、用户信息,提供登录/登出 actions +│ │ │ └── user.ts # 用户信息状态:缓存当前登录用户的详细信息 +│ │ ├── views/ # 页面视图组件,一个文件对应一个完整页面 +│ │ │ ├── auth/ # 认证相关页面 +│ │ │ │ └── Login.vue # 登录页:用户名密码表单、LDAP 认证入口 +│ │ │ ├── dashboard/ # 仪表盘页面 +│ │ │ │ └── Index.vue # 首页仪表盘:系统概览、快捷入口 +│ │ │ ├── subsystem/ # 子系统导航页面 +│ │ │ │ └── Navigation.vue # 子系统导航页:6 个子系统卡片网格展示 +│ │ │ └── audit/ # 审计面板页面 +│ │ │ ├── LoginAudit.vue # 登录审计页:查询登录记录、按时间/IP/结果筛选 +│ │ │ └── OpsAudit.vue # 运维操作审计页:查询操作记录、按类型/状态筛选 +│ │ ├── utils/ # 通用工具函数,不依赖业务逻辑 +│ │ │ └── auth.ts # 认证工具:Token 解析、过期校验、本地存储读写 +│ │ ├── App.vue # 根组件:挂载路由视图,全局样式和 Provider +│ │ └── main.ts # 入口文件:初始化 Vue 应用、注册插件(Pinia、Router、Element Plus) +│ ├── public/ # 静态资源目录,构建时原样复制到 dist +│ ├── index.html # HTML 入口模板,Vite 注入构建后的 JS/CSS +│ ├── vite.config.ts # Vite 构建配置:插件、别名、代理、构建选项 +│ ├── tsconfig.json # TypeScript 配置:编译选项、路径映射 +│ └── package.json # 依赖管理:项目依赖列表、脚本命令 +│ +├── server/ # 后端 Go 项目,提供 RESTful API 服务 +│ ├── cmd/ # 程序入口目录 +│ │ └── server/ +│ │ └── main.go # 服务启动入口:初始化配置、数据库、路由,启动 HTTP 服务 +│ ├── internal/ # 内部包,不对外暴露,按分层架构组织 +│ │ ├── config/ # 配置管理模块 +│ │ │ └── config.go # 配置加载:读取 YAML 配置文件,支持环境变量覆盖 +│ │ ├── handler/ # HTTP 处理器层(Controller),接收请求、校验参数、调用 Service +│ │ │ ├── auth.go # 认证处理器:处理登录/登出/用户信息请求 +│ │ │ ├── audit.go # 审计处理器:处理登录审计/运维操作审计查询请求 +│ │ │ ├── subsystem.go # 子系统处理器:处理子系统列表/SSO URL 生成请求 +│ │ │ ├── task.go # 任务处理器:处理 Ansible 任务创建/状态查询请求 +│ │ │ └── response.go # 统一响应:定义标准 JSON 响应格式和错误码 +│ │ ├── middleware/ # HTTP 中间件,在请求处理前后执行通用逻辑 +│ │ │ ├── auth.go # 认证中间件:校验 JWT Token,注入用户信息到 Context +│ │ │ ├── logger.go # 日志中间件:记录请求方法、路径、耗时、状态码 +│ │ │ └── audit.go # 审计中间件:自动记录非 GET 请求的操作审计日志 +│ │ ├── model/ # 数据模型层,定义数据库表结构和业务实体 +│ │ │ ├── user.go # 用户模型:对应 users 表,定义用户字段和状态枚举 +│ │ │ ├── audit.go # 审计模型:对应 login_audit / ops_audit 表 +│ │ │ └── subsystem.go # 子系统模型:对应 subsystems 表,定义子系统信息 +│ │ ├── repository/ # 数据访问层(DAO),封装数据库 CRUD 操作 +│ │ │ ├── user.go # 用户仓储:用户查询、创建、更新、LDAP DN 映射 +│ │ │ └── audit.go # 审计仓储:审计记录插入、分页查询、条件筛选 +│ │ ├── service/ # 业务逻辑层,编排 Repository,实现核心业务 +│ │ │ ├── auth.go # 认证服务:LDAP 认证、本地降级认证、JWT 生成 +│ │ │ ├── ldap.go # LDAP 服务:封装 LDAP 连接、查询、认证逻辑 +│ │ │ ├── audit.go # 审计服务:记录登录审计、运维操作审计 +│ │ │ ├── subsystem.go # 子系统服务:子系统查询、OAuth 2.0 SSO URL 生成 +│ │ │ └── ansible.go # Ansible 调度服务:创建任务、执行 Playbook、推送日志 +│ │ ├── websocket/ # WebSocket 实时推送模块 +│ │ │ └── hub.go # WebSocket Hub:管理客户端连接,广播 Ansible 任务日志 +│ │ └── router/ # 路由注册模块 +│ │ └── router.go # 路由注册:定义 API 路由表,绑定 Handler 和 Middleware +│ ├── pkg/ # 可复用的公共包,可被外部项目引用 +│ │ ├── ldap/ # LDAP 客户端封装 +│ │ │ └── client.go # LDAP 客户端:连接管理、用户认证、属性查询 +│ │ ├── sso/ # SSO 协议处理 +│ │ │ ├── oauth2.go # OAuth 2.0 客户端:主系统↔子系统的 Authorization Code 流程 +│ │ │ └── saml.go # SAML 处理:主系统↔LDAP 的 SAML 断言生成和验证 +│ │ └── database/ # 数据库连接管理 +│ │ └── mysql.go # MySQL 连接池:初始化连接、健康检查、优雅关闭 +│ ├── migrations/ # 数据库迁移脚本,按版本管理表结构变更 +│ │ └── 001_init.sql # 初始化迁移:创建 users / subsystems / audit / ansible_tasks 表 +│ └── go.mod # Go 模块定义:模块路径、依赖版本管理 +│ +├── deploy/ # 部署配置,包含容器化和编排所需文件 +│ ├── docker/ # Docker 构建配置 +│ │ ├── Dockerfile.frontend # 前端镜像:基于 Node 构建 + Nginx 托管静态文件 +│ │ └── Dockerfile.server # 后端镜像:基于 Go 编译 + 运行时最小镜像 +│ └── k8s/ # Kubernetes 部署配置 +│ ├── frontend.yaml # 前端 Deployment:副本数、Service、环境变量配置 +│ ├── server.yaml # 后端 Deployment:副本数、Service、Secret 挂载 +│ └── ingress.yaml # Ingress 配置:域名路由规则、TLS 证书 +│ +├── docs/ # 项目文档目录 +│ └── mvp-skeleton-plan.md # MVP 方案文档:本文件,定义代码骨架和实现要点 +│ +├── .gitignore # Git 忽略规则:排除编译产物、依赖、环境配置 +├── Makefile # 构建脚本:定义 build / run / test / docker 等快捷命令 +└── README.md # 项目说明:项目介绍、快速启动、开发指南 +``` + + +--- + +## 模块划分与职责 + +### 后端模块 + +| 模块 | 职责 | 说明 | +|------|------|------| +| `cmd/server` | 服务启动入口 | 初始化配置、数据库、路由,启动 HTTP 服务 | +| `internal/config` | 配置管理 | 加载 YAML 配置,支持环境变量覆盖 | +| `internal/handler` | HTTP 处理器 | 处理请求,调用 Service 层,返回响应 | +| `internal/middleware` | 中间件 | 认证、日志、审计等中间件 | +| `internal/model` | 数据模型 | 定义数据库表结构和业务实体 | +| `internal/repository` | 数据访问层 | 封装数据库操作,实现 CRUD | +| `internal/service` | 业务逻辑层 | 核心业务逻辑,编排 Repository | +| `internal/websocket` | WebSocket 实时推送 | Ansible 任务日志实时推送 | +| `internal/router` | 路由配置 | 定义 API 路由和处理器映射 | +| `pkg/ldap` | LDAP 客户端 | 封装 LDAP 查询和认证 | +| `pkg/sso` | SSO 处理 | OAuth 2.0(主系统↔子系统)+ SAML(主系统↔LDAP) | +| `pkg/database` | 数据库连接 | MySQL 连接池管理 | + +### 前端模块 + +| 模块 | 职责 | 说明 | +|------|------|------| +| `api/` | API 请求 | 封装后端接口调用,统一错误处理 | +| `components/` | 通用组件 | 可复用的 UI 组件 | +| `composables/` | 组合式函数 | 封装可复用的逻辑(认证) | +| `layouts/` | 页面布局 | 定义页面整体布局结构 | +| `router/` | 路由配置 | 定义前端路由 | +| `stores/` | 状态管理 | Pinia 全局状态管理 | +| `views/` | 页面视图 | 具体页面实现 | +| `utils/` | 工具函数 | 通用工具函数 | + +--- + +## 错误码定义 + +### HTTP 状态码 + +| 状态码 | 说明 | +|--------|------| +| 200 | 成功 | +| 400 | 请求参数错误 | +| 401 | 未认证(Token 缺失或无效) | +| 403 | 无权限访问 | +| 404 | 资源不存在 | +| 500 | 服务器内部错误 | + +### 业务错误码 + +| 错误码 | 说明 | +|--------|------| +| 10001 | LDAP 认证失败 | +| 10002 | 用户名或密码错误 | +| 10003 | Token 已过期 | +| 10004 | 子系统未配置 SSO | +| 10005 | SSO 跳转生成失败 | +| 20001 | Ansible 任务创建失败 | +| 20002 | Ansible 任务执行超时 | + +### 错误响应格式 + +```json +{ + "code": 10001, + "message": "LDAP 认证失败", + "details": "连接 LDAP 服务器超时" +} +``` + +--- + +## 安全设计 + +### 敏感配置管理 + +| 配置项 | 存储方式 | 说明 | +|--------|----------|------| +| JWT Secret | K8s Secret | 通过环境变量注入 | +| LDAP Bind Password | K8s Secret | 通过环境变量注入 | +| DB Password | K8s Secret | 通过环境变量注入 | +| Redis Password | K8s Secret | 通过环境变量注入 | +| OAuth2 Client Secret | K8s Secret | 各子系统的 OAuth2 密钥 | + +### 安全措施 + +- **传输加密**:所有 API 通信强制 HTTPS +- **Token 安全**:JWT 使用 RS256 签名,过期时间 1 小时 +- **密码策略**:LDAP 统一管理,本地账户密码 bcrypt 加密 +- **审计日志**:所有敏感操作记录审计日志 + +--- + +## 接口定义 + +### 1. 认证模块 API + +#### POST /api/v1/auth/login +```go +// 请求 +{ + "username": "string", // 用户名 + "password": "string" // 密码 +} + +// 响应 +{ + "code": 0, + "message": "success", + "data": { + "token": "string", // JWT Token + "expires_in": 3600, // 过期时间(秒) + "user": { + "id": 1, + "username": "string", + "display_name": "string", + "email": "string", + "business_line": "kodo" // 业务线 + } + } +} +``` + +#### POST /api/v1/auth/logout +```go +// 请求头 +Authorization: Bearer + +// 响应 +{ + "code": 0, + "message": "success" +} +``` + +#### GET /api/v1/auth/userinfo +```go +// 请求头 +Authorization: Bearer + +// 响应 +{ + "code": 0, + "message": "success", + "data": { + "id": 1, + "username": "string", + "display_name": "string", + "email": "string", + "business_line": "kodo" + } +} +``` + +### 2. 子系统模块 API + +#### GET /api/v1/subsystems +```go +// 响应 +{ + "code": 0, + "message": "success", + "data": [ + { + "id": 1, + "name": "Wayne", + "description": "多集群容器管理平台", + "icon": "wayne.svg", + "url": "https://wayne.qiniu.com", + "status": "integrated", // integrated / integrating + "sso_enabled": true + }, + { + "id": 2, + "name": "CloudDM", + "description": "数据库管理与SQL审核", + "icon": "clouddm.svg", + "url": "https://clouddm.qiniu.com", + "status": "integrated", + "sso_enabled": true + }, + { + "id": 3, + "name": "CacheCloud", + "description": "Redis 云管理平台", + "icon": "cachecloud.svg", + "url": "https://cachecloud.qiniu.com", + "status": "integrated", + "sso_enabled": true + }, + { + "id": 4, + "name": "Apollo", + "description": "配置中心", + "icon": "apollo.svg", + "url": "https://apollo.xinfra.internal", + "status": "integrated", + "sso_enabled": true + }, + { + "id": 5, + "name": "qpass", + "description": "密码管理平台", + "icon": "qpass.svg", + "url": "https://qpass.xinfra.internal", + "status": "integrated", + "sso_enabled": true + }, + { + "id": 6, + "name": "Grafana", + "description": "监控可视化平台", + "icon": "grafana.svg", + "url": "https://grafana.xinfra.internal", + "status": "integrated", + "sso_enabled": true + } + ] +} +``` + +#### GET /api/v1/subsystems/:id/sso-url +```go +// 响应 +{ + "code": 0, + "message": "success", + "data": { + "sso_url": "https://wayne.qiniu.com/sso/callback?code=xxx&state=yyy", + "expires_in": 300 + } +} +``` + +### 3. 审计模块 API + +#### GET /api/v1/audit/login +```go +// 查询参数 +?user_id=1&start_time=2024-01-01T00:00:00Z&end_time=2024-01-31T23:59:59Z&page=1&page_size=20 + +// 响应 +{ + "code": 0, + "message": "success", + "data": { + "total": 100, + "items": [ + { + "id": 1, + "user_id": 1, + "username": "zhangsan", + "login_time": "2024-01-15T10:30:00Z", + "source_ip": "10.0.0.1", + "target_system": "Wayne", + "status": "success" + } + ] + } +} +``` + +#### GET /api/v1/audit/operations +```go +// 查询参数 +?user_id=1&operation_type=ansible&page=1&page_size=20 + +// 响应 +{ + "code": 0, + "message": "success", + "data": { + "total": 50, + "items": [ + { + "id": 1, + "user_id": 1, + "username": "zhangsan", + "operation_type": "ansible", + "operation": "执行 playbook: node-join", + "target": "node-10.0.0.5", + "status": "success", + "created_at": "2024-01-15T10:35:00Z" + } + ] + } +} +``` + +### 4. Ansible 调度模块 API + +#### POST /api/v1/tasks/ansible/execute +```go +// 请求 +{ + "playbook": "node-join.yml", + "targets": ["node-10.0.0.5", "node-10.0.0.6"], + "extra_vars": { + "cluster": "prod" + } +} + +// 响应 +{ + "code": 0, + "message": "success", + "data": { + "task_id": "task-uuid-xxx", + "status": "running" + } +} +``` + +#### GET /api/v1/tasks/:id +```go +// 响应 +{ + "code": 0, + "message": "success", + "data": { + "task_id": "task-uuid-xxx", + "playbook": "node-join.yml", + "targets": ["node-10.0.0.5", "node-10.0.0.6"], + "status": "running", // pending / running / success / failed + "created_at": "2024-01-15T10:35:00Z", + "started_at": "2024-01-15T10:35:01Z", + "finished_at": null + } +} +``` + +#### WebSocket /ws/tasks/:id/logs +``` +// 实时推送 Ansible 执行日志 +// 消息格式: +{ + "type": "log", + "data": { + "timestamp": "2024-01-15T10:35:02Z", + "host": "node-10.0.0.5", + "task": "Gathering Facts", + "status": "ok", + "message": "ok: [node-10.0.0.5]" + } +} +``` + +--- + +## 数据库设计 + +### 核心表结构 + +```sql +-- 用户表 +CREATE TABLE users ( + id BIGINT AUTO_INCREMENT PRIMARY KEY, + username VARCHAR(64) NOT NULL UNIQUE, + display_name VARCHAR(128), + email VARCHAR(128), + password_hash VARCHAR(256), + business_line VARCHAR(32), + ldap_dn VARCHAR(256), + status ENUM('active', 'disabled') DEFAULT 'active', + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP +); + +-- 子系统表 +CREATE TABLE subsystems ( + id BIGINT AUTO_INCREMENT PRIMARY KEY, + name VARCHAR(64) NOT NULL, + description TEXT, + icon VARCHAR(128), + url VARCHAR(256), + status ENUM('integrated', 'integrating') DEFAULT 'integrating', + sso_enabled BOOLEAN DEFAULT FALSE, + sort_order INT DEFAULT 0, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP +); + +-- 登录审计表 +CREATE TABLE login_audit ( + id BIGINT AUTO_INCREMENT PRIMARY KEY, + user_id BIGINT, + username VARCHAR(64), + login_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + source_ip VARCHAR(64), + target_system VARCHAR(64), + status ENUM('success', 'failed') DEFAULT 'success', + INDEX idx_user_id (user_id), + INDEX idx_login_time (login_time) +); + +-- 运维操作审计表 +CREATE TABLE ops_audit ( + id BIGINT AUTO_INCREMENT PRIMARY KEY, + user_id BIGINT, + username VARCHAR(64), + operation_type VARCHAR(32), + operation TEXT, + target VARCHAR(256), + status ENUM('success', 'failed', 'running') DEFAULT 'running', + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + INDEX idx_user_id (user_id), + INDEX idx_created_at (created_at) +); + +-- Ansible 任务表 +CREATE TABLE ansible_tasks ( + id VARCHAR(64) PRIMARY KEY, + user_id BIGINT, + username VARCHAR(64), + playbook VARCHAR(128), + targets JSON, + extra_vars JSON, + status ENUM('pending', 'running', 'success', 'failed') DEFAULT 'pending', + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + started_at TIMESTAMP NULL, + finished_at TIMESTAMP NULL, + INDEX idx_user_id (user_id), + INDEX idx_status (status) +); +``` + +--- + +## 关键模块实现要点 + +### 1. 认证模块 (auth) + +**后端实现**: +```go +// internal/service/auth.go +type AuthService struct { + userRepo repository.UserRepository + ldapClient *ldap.Client + auditService *AuditService +} + +// Login 用户登录 +func (s *AuthService) Login(username, password string) (*LoginResponse, error) { + // 1. 尝试 LDAP 认证 + user, err := s.ldapClient.Authenticate(username, password) + if err != nil { + // 2. 降级到本地数据库认证 + user, err = s.userRepo.FindByUsername(username) + if err != nil { + return nil, err + } + if !s.checkPassword(password, user.PasswordHash) { + return nil, ErrInvalidCredentials + } + } + + // 3. 生成 JWT Token(无状态,不存储 session) + token, err := s.generateToken(user) + if err != nil { + return nil, err + } + + // 4. 记录登录审计 + s.auditService.RecordLogin(user.ID, username, "main", "success") + + return &LoginResponse{ + Token: token, + ExpiresIn: 3600, + User: user, + }, nil +} +``` + +**前端实现**: +```typescript +// frontend/src/composables/useAuth.ts +export function useAuth() { + const authStore = useAuthStore() + + const login = async (username: string, password: string) => { + const response = await authApi.login({ username, password }) + authStore.setToken(response.token) + authStore.setUser(response.user) + return response + } + + const logout = async () => { + await authApi.logout() + authStore.clearAuth() + router.push('/login') + } + + const checkAuth = () => { + const token = authStore.token + if (!token) { + router.push('/login') + return false + } + return true + } + + return { login, logout, checkAuth } +} +``` + +### 2. SSO 跳转模块(OAuth 2.0) + +**后端实现**: +```go +// internal/service/subsystem.go +type SubsystemService struct { + subsystemRepo repository.SubsystemRepository + oauth2Client *sso.OAuth2Client +} + +// GetSSOURL 获取子系统 SSO 跳转 URL(OAuth 2.0 Authorization Code) +func (s *SubsystemService) GetSSOURL(subsystemID int64, user *model.User) (string, error) { + subsystem, err := s.subsystemRepo.FindByID(subsystemID) + if err != nil { + return "", err + } + + if !subsystem.SSOEnabled { + return subsystem.URL, nil + } + + // 生成 OAuth 2.0 Authorization Code + code, state, err := s.oauth2Client.GenerateAuthCode(subsystem, user) + if err != nil { + return "", err + } + + // 构建 SSO 跳转 URL + ssoURL := fmt.Sprintf("%s/sso/callback?code=%s&state=%s", + subsystem.URL, code, state) + + // 记录 SSO 跳转审计 + s.auditService.RecordLogin(user.ID, user.Username, subsystem.Name, "success") + + return ssoURL, nil +} +``` + +**前端实现**: +```typescript +// frontend/src/components/SubsystemCard.vue + + + +``` + +### 3. Ansible 调度模块 + +**后端实现**: +```go +// internal/service/ansible.go +type AnsibleService struct { + taskRepo repository.TaskRepository + auditService *AuditService + wsHub *websocket.Hub +} + +// ExecutePlaybook 执行 Ansible Playbook +func (s *AnsibleService) ExecutePlaybook(req *ExecuteRequest, user *model.User) (*AnsibleTask, error) { + task := &AnsibleTask{ + ID: generateUUID(), + UserID: user.ID, + Username: user.Username, + Playbook: req.Playbook, + Targets: req.Targets, + ExtraVars: req.ExtraVars, + Status: "pending", + } + + if err := s.taskRepo.Create(task); err != nil { + return nil, err + } + + // 异步执行 Ansible + go s.runPlaybook(task) + + return task, nil +} + +// runPlaybook 异步执行并推送日志 +func (s *AnsibleService) runPlaybook(task *AnsibleTask) { + // 调用 ansible-playbook 命令 + // 通过 WebSocket 实时推送日志到前端 + // 更新任务状态 +} +``` + +**WebSocket Hub**: +```go +// internal/websocket/hub.go +type Hub struct { + clients map[string]map[*Client]bool + broadcast chan *Message + register chan *Client + unregister chan *Client +} + +// SubscribeTaskLogs 订阅任务日志 +func (h *Hub) SubscribeTaskLogs(taskID string, client *Client) { + h.register <- &Client{taskID: taskID, conn: client.conn} +} +``` + +### 4. 审计模块 + +**后端实现**: +```go +// internal/middleware/audit.go +func AuditMiddleware(auditService *service.AuditService) gin.HandlerFunc { + return func(c *gin.Context) { + // 记录请求开始 + startTime := time.Now() + + // 处理请求 + c.Next() + + // 记录操作审计 + if c.Request.Method != "GET" { + user, _ := c.Get("user") + if user != nil { + auditService.RecordOperation( + user.(*model.User).ID, + user.(*model.User).Username, + c.Request.Method, + c.Request.URL.Path, + c.ClientIP(), + c.Writer.Status(), + ) + } + } + + // 记录请求耗时 + duration := time.Since(startTime) + log.Printf("Method: %s, Path: %s, Duration: %v", + c.Request.Method, c.Request.URL.Path, duration) + } +} +``` + +--- + +## 配置文件 + +### 后端配置 (config.yaml) +```yaml +server: + host: "0.0.0.0" + port: 8080 + mode: "release" # debug / release / test + +database: + host: "mysql" + port: 3306 + username: "xinfra" + password: "${DB_PASSWORD}" + database: "xinfra" + max_open_conns: 100 + max_idle_conns: 10 + +redis: + host: "redis" + port: 6379 + password: "${REDIS_PASSWORD}" + db: 0 + +ldap: + host: "ldap.qiniu.com" + port: 389 + base_dn: "dc=qiniu,dc=com" + bind_dn: "cn=admin,dc=qiniu,dc=com" + bind_password: "${LDAP_PASSWORD}" + +jwt: + secret: "${JWT_SECRET}" + expires_in: 3600 + +subsystems: + - name: "Wayne" + url: "https://wayne.qiniu.com" + sso_enabled: true + - name: "CloudDM" + url: "https://clouddm.qiniu.com" + sso_enabled: true + - name: "CacheCloud" + url: "https://cachecloud.qiniu.com" + sso_enabled: true + - name: "Apollo" + url: "https://apollo.xinfra.internal" + sso_enabled: true + - name: "qpass" + url: "https://qpass.xinfra.internal" + sso_enabled: true + - name: "Grafana" + url: "https://grafana.xinfra.internal" + sso_enabled: true +``` + +### 前端配置 (vite.config.ts) +```typescript +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import { resolve } from 'path' + +export default defineConfig({ + plugins: [vue()], + resolve: { + alias: { + '@': resolve(__dirname, 'src'), + }, + }, + server: { + port: 3000, + proxy: { + '/api': { + target: 'http://localhost:8080', + changeOrigin: true, + }, + }, + }, + build: { + outDir: 'dist', + sourcemap: false, + }, +}) +``` + +--- + +## MVP 验收标准 + +| # | 验收项 | 验收标准 | +|---|--------|----------| +| 1 | LDAP 登录 | 用户可通过 LDAP 账号密码登录主系统,登录成功后跳转首页 | +| 2 | 本地降级登录 | LDAP 不可用时,支持本地数据库账号密码登录 | +| 3 | 6 个子系统卡片展示 | 首页展示 Wayne、CloudDM、CacheCloud、Apollo、qpass、Grafana 6 个子系统卡片 | +| 4 | SSO 跳转 | 点击子系统卡片,通过 OAuth 2.0 跳转到子系统,免登录 | +| 5 | 登录审计 | 可查询所有用户的登录记录,包括时间、IP、目标系统、结果 | +| 6 | 运维操作审计 | 可查询运维操作记录,包括操作类型、目标、结果 | +| 7 | Ansible 调度基础 | 可执行 Ansible Playbook,实时查看执行日志 | +| 8 | API 错误处理 | 所有 API 返回标准错误码和错误信息 | + +--- + +## 开发任务清单 + +### Phase 1: 基础框架搭建 (2天) + +- [ ] 初始化前后端项目结构 +- [ ] 配置开发环境 (Makefile, docker-compose) +- [ ] 实现基础中间件 (Logger, Recovery) +- [ ] 配置数据库连接和迁移 +- [ ] 实现统一响应格式 +- [ ] 实现错误码定义 + +### Phase 2: 认证模块 (3天) + +- [ ] 实现 LDAP 客户端 +- [ ] 实现用户登录/登出 API +- [ ] 实现 JWT Token 生成和验证(无状态) +- [ ] 实现认证中间件 +- [ ] 实现 OAuth 2.0 + SAML SSO 协议 +- [ ] 实现前端登录页面 +- [ ] 实现前端路由守卫 + +### Phase 3: 子系统导航 (2天) + +- [ ] 实现子系统 CRUD API +- [ ] 实现 OAuth 2.0 Authorization Code 生成 +- [ ] 实现 SSO 跳转逻辑(6 个子系统) +- [ ] 实现子系统卡片组件 +- [ ] 实现子系统导航页面 + +### Phase 4: 审计模块 (1.5天) + +- [ ] 实现审计数据模型 +- [ ] 实现审计记录 API +- [ ] 实现审计查询 API +- [ ] 实现审计中间件 +- [ ] 实现登录审计页面 +- [ ] 实现运维操作审计页面 + +### Phase 5: Ansible 调度基础模块 + WebSocket (1天) + +- [ ] 实现 Ansible 调度服务 +- [ ] 实现任务 API +- [ ] 实现 WebSocket 日志推送 +- [ ] 实现任务执行日志前端展示 + +### Phase 6: 部署配置 + 测试 (0.5天) + +- [ ] 编写 Dockerfile +- [ ] 编写 Kubernetes 配置(含 Secret 管理) +- [ ] 编写部署文档 +- [ ] 集成测试 + +--- + +## 技术要点 + +### 1. 认证流程 + +``` +用户输入用户名密码 + ↓ +主系统后端接收请求 + ↓ +尝试 LDAP 认证 + ↓ (失败) +降级到本地数据库认证 + ↓ +生成 JWT Token(无状态,不存储 session) + ↓ +记录登录审计 + ↓ +返回 Token 给前端 + ↓ +前端存储 Token,跳转首页 +``` + +### 2. SSO 跳转流程(OAuth 2.0) + +``` +用户点击子系统卡片 + ↓ +前端请求 /api/v1/subsystems/:id/sso-url + ↓ +后端验证用户 Token + ↓ +生成 OAuth 2.0 Authorization Code + ↓ +记录 SSO 跳转审计 + ↓ +返回 SSO URL 给前端 + ↓ +前端打开新窗口跳转(子系统通过 Code 换取 Token) +``` + +**SSO 协议分工**: +- **主系统 ↔ 子系统**:OAuth 2.0 Authorization Code 流程 +- **主系统 ↔ LDAP**:SAML 协议 + + + +