diff --git a/.gitignore b/.gitignore index d6f7fcf..d42dadf 100644 --- a/.gitignore +++ b/.gitignore @@ -48,3 +48,8 @@ docker-compose.override.yml # Kubernetes secrets (local dev) *-secret.yaml + +# Documentation & local dev config (not tracked in repo) +docs/ +CLAUDE.md +AGENTS.md diff --git a/AGENTS.md b/AGENTS.md deleted file mode 100644 index bd8ba3b..0000000 --- a/AGENTS.md +++ /dev/null @@ -1,43 +0,0 @@ -# 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 核心功能 -- 遵循项目既定的技术栈和编码规范 - -### Git 操作规范 - -- **禁止自动提交**:除非用户明确指示,否则不要执行 `git commit` -- **Commit Message**:使用多行格式,包含 type、scope、subject 和详细 body diff --git a/CLAUDE.md b/CLAUDE.md deleted file mode 100644 index 011172e..0000000 --- a/CLAUDE.md +++ /dev/null @@ -1,43 +0,0 @@ -# CLAUDE.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 核心功能 -- 遵循项目既定的技术栈和编码规范 - -### Git 操作规范 - -- **禁止自动提交**:除非用户明确指示,否则不要执行 `git commit` -- **Commit Message**:使用多行格式,包含 type、scope、subject 和详细 body diff --git a/docs/.gitkeep b/docs/.gitkeep deleted file mode 100644 index f6ff00e..0000000 --- a/docs/.gitkeep +++ /dev/null @@ -1,6 +0,0 @@ -# 项目文档目录 - -存放项目相关文档: -- mvp-skeleton-plan.md: MVP 方案文档,定义代码骨架和实现要点 -- api.md: API 接口文档 -- deployment.md: 部署文档 diff --git a/docs/mvp-skeleton-plan.md b/docs/mvp-skeleton-plan.md deleted file mode 100644 index 4474221..0000000 --- a/docs/mvp-skeleton-plan.md +++ /dev/null @@ -1,1006 +0,0 @@ -# MVP 方案文档 - -## 概述 - -本文档定义 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 协议 \ No newline at end of file diff --git a/docs/ref/xinfra-prototype.v3.html b/docs/ref/xinfra-prototype.v3.html deleted file mode 100644 index 3c0a488..0000000 --- a/docs/ref/xinfra-prototype.v3.html +++ /dev/null @@ -1,1174 +0,0 @@ - - - - -xinfra · 统一基础设施平台 - - - - -
-
-
xi
xinfra 统一基础设施平台
- ● 生产环境 -
- -
-
王
-
-
王晓东
-
LDAP · Kodo业务线
-
-
-
- - - -
- - -
-
-

资源大盘

跨机房 / 多云容器资源统一视图 · 最近更新于 12 秒前

- -
- -
-
RKE2 集群
3
3 机房在线
-
节点总数
128
↑ 6 本周新增
-
CPU 已分配
61%
2,048 / 3,360 核
-
组件实例
214
MySQL 38 · Redis 92 · 其他 84
-
进行中任务
2
1 个待关注
-
- -
-
-

集群拓扑 · 按机房 / 业务线标签

node-label 调度视图
-
-
-
IDC-华北机房46节点
-
-
-
-
IDC-华东机房52节点
-
-
-
-
阿里云-华南30节点
-
-
-
-
- Kodo业务线 - LAS业务线 - 灵矽业务线 - 空闲 -
-
- -
-

最近任务

查看全部 →
-
- - - - - - -
● 成功MySQL 主从部署2m14s
● 执行中RKE2 节点加入38s
● 成功Redis Cluster 部署3m02s
● 失败openresty 网关部署41s
● 成功业务线标签同步5s
-
-
-
-
- - -
-
-

资源状态看板

物理机 / 虚机 / 基础服务状态汇总 · 夜莺(Nightingale)统一告警引擎对接 Zabbix + VictoriaMetrics · 最近更新于 18 秒前

- -
- -
-
物理机总数
186
186 / 186 监控覆盖
-
虚机总数(LAS)
512
↑ 14 本周新增
-
基础组件实例
214
MySQL 38 · Redis 92 · 其他 84
-
P0 / Disaster 告警
1
来自 VictoriaMetrics
-
P1 / High 告警
5
来自 Zabbix · 4 条 / VM · 1 条
-
- -
-

告警来源接入 · 夜莺统一告警

Nightingale ← Zabbix / VictoriaMetrics
-
-
-
-
Zabbix 物理机 / 硬件层
-
IPMI · 温度 · 电源 · 风扇
-
网络设备 · 存储健康度
-
事件级别:disaster / high / average
-
-
-
VictoriaMetrics 虚机 / 容器 / 业务层
-
K8s / 容器 / 主机指标
-
基础服务可用性探活
-
告警级别:P0 / P1 / P2
-
-
-
夜莺 Nightingale 统一告警引擎
-
按 P0/P1 或 disaster/high/average 过滤聚合
-
去重 · 收敛 · 分级推送
-
下游:qpass 统一告警通道
-
-
-
-
- -
-
-

物理机状态 · 按机房

数据源:Zabbix
-
- - - - - - -
机房总数在线健康率状态
YZH 机房787898%● 正常
XS 机房646391%● 1 条告警
JF 机房2222100%● 正常
海外 IDC(4)222186%● 1 条严重
-
-
- -
-

虚机状态 · LAS 资源池

数据源:VictoriaMetrics
-
- - - - - - -
业务线虚机数CPU 均值状态
Kodo21864%● 正常
LAS16482%● 1 条告警
灵矽9657%● 正常
共享池 / 未分配3431%● 正常
-
-
-
- -
-

基础服务状态汇总

MySQL / Redis / 中间件 · 探活数据源:VictoriaMetrics
-
- - - - - - - -
服务类型实例数异常可用率状态
MySQL380100%● 正常
Redis(CacheCloud)92198.9%● 1 条告警
PostgreSQL120100%● 正常
openresty 网关260100%● 正常
其他中间件460100%● 正常
-
-
- -
-

当前告警 · P0/P1(disaster / high / average)

夜莺聚合 · 已去重
-
- - - - - - - - -
级别来源原始级别对象告警内容时间
P0VictoriaMetricsdisastersg-las-overseas-007磁盘只读 / IO 错误,节点不可写07:38:55
P1Zabbixhighyzh-las-014风扇转速低于阈值(FAN_6: 1920 RPM)07:35:12
P1Zabbixhighxs-bm-291电源冗余丢失(PSU2 离线)07:21:40
P1VictoriaMetricshighredis-ads-feature-cluster-02慢查询比例超阈值(>5%,持续5分钟)07:18:03
averageZabbixaverageoverseas-dallas-idc专线延迟抖动超基线(WireGuard ↔ AWS US)07:10:22
averageZabbixaveragejf-bm-118CPU 温度接近阈值(76℃ / 80℃)06:58:47
-
-
-
- - - -
-
-

集群 / 节点

按机房切分的 RKE2 集群,Calico BGP 扁平网络

- -
-
-
- - - - - - - -
集群机房 / 区域状态节点CPU 使用RKE2 版本Calico
rke2-bj-prod-01华北 · IDC● 健康4664%v1.28.9+rke2r1BGP AS64512
rke2-sh-prod-01华东 · IDC● 健康5271%v1.28.9+rke2r1BGP AS64513
rke2-ali-sz-01阿里云 · 华南● 1 节点告警3083%v1.28.6+rke2r1BGP AS64514
-
-
- -
-

rke2-bj-prod-01 · 节点列表(节选)

node-label 多租户隔离
-
- - - - - - - - -
节点IP业务线标签污点 Taint规格CPU / Mem状态
bj-node-01410.21.4.14business-line=kodokodo:NoSchedule64C/256G58%● Ready
bj-node-01510.21.4.15business-line=kodokodo:NoSchedule64C/256G62%● Ready
bj-node-03110.21.4.31business-line=laslas:NoSchedule32C/128G88%● 资源告警
bj-node-04810.21.4.48未分配—32C/128G4%● Ready · 空闲
-
-
-
- - -
-
-

业务线 / 配额

LDAP 部门信息自动同步生成,节点标签 + ResourceQuota 双重隔离

-
-
-
- - - - - - - - - -
业务线LDAP 部门归属节点数CPU 配额已用命名空间负责人
kodo · Kodo业务线ou=kodo,dc=company,dc=com421,344 核58%ns-kodo-prod王晓东
las · LAS业务线ou=las,dc=company,dc=com381,216 核85%ns-las-prod李雯
lingxi · 灵矽业务线ou=lingxi,dc=company,dc=com26832 核47%ns-lingxi-prod张昊
ltoken · LTOKEN业务线ou=ltoken,dc=company,dc=com14448 核33%ns-ltoken-prod陈思
maas · MAAS业务线ou=maas,dc=company,dc=com8256 核21%ns-maas-prod赵帆
-
-
-
- 隔离策略说明:节点标签(nodeAffinity + taints)决定 Pod 只能调度到归属业务线的物理节点上;ResourceQuota / LimitRange 在此基础上限制命名空间内的资源上限,二者结合避免单一业务线在自己的节点池内无限占用资源。 -
-
- - -
-
-

基础服务目录

点击卡片,通过封装好的 ansible-playbook 一键部署标准化基础服务

-
-
-
-
My

MySQL

-
一主多从,自动注册进 open-cdm 数据源,支持 LDAP 账号统一审核 SQL 上线。
-
roles/mysql-deployv8.0.36
-
-
-
Rd

Redis

-
支持 Standalone / Sentinel / Cluster,部署完成后自动注册进 CacheCloud。
-
roles/redis-deployv7.2
-
-
-
Or

openresty

-
容器化部署在 K8s 内,作为业务边缘网关,支持灰度路由配置。
-
roles/openresty-deployv1.25
-
-
-
Dp

dpvs

-
四层负载均衡,直接管理宿主机网络命名空间,不纳入容器编排。
-
roles/dpvs-deployv1.9
-
-
-
Pg

PgSQL

-
流复制主从架构,规划中 · 第二期接入 open-cdm 统一审核体系。
-
roles/pgsql-deploy规划中
-
-
-
+

接入新服务

-
封装新的 ansible-playbook,注册进基础服务目录
-
-
-
-
- - -
-
-

组件实例

所有基础组件实例的统一台账,关联 CMDB / 子系统注册状态

-
-
-
- - - - - - - - - - -
实例类型业务线所在集群状态子系统注册
mysql-kodo-order-01MySQL 8.0 主从kodorke2-bj-prod-01● 运行中open-cdm ✓
redis-las-feature-clusterRedis Clusterlasrke2-sh-prod-01● 运行中CacheCloud ✓
redis-lingxi-sessionRedis Sentinellingxirke2-ali-sz-01● 同步中CacheCloud 同步中…
mysql-las-billing-01MySQL 8.0 主从lasrke2-sh-prod-01● 运行中open-cdm ✓
mysql-ltoken-account-01MySQL 8.0 主从ltokenrke2-bj-prod-01● 运行中open-cdm ✓
redis-maas-infer-cache-01Redis Standalonemaasrke2-ali-sz-01● 运行中CacheCloud ✓
- -
-
-
- - -
-
-

资源管理

统一纳管物理机与虚机资源 · 基础数据来自 SINA CMDB,云上虚机由阿里云 / AWS / 七牛 LAS 增量同步回写

- -
- -
-
资源总数
658
物理机 146 · 虚机 512
-
SINA CMDB
368
物理机 146 · 虚机 222
-
阿里云同步
154
ECS · 增量同步
-
AWS / 七牛 LAS 同步
136
AWS 58 · 七牛 LAS 78
-
最近一次同步
● 正常
07:39:10 · 新增 3 条
-
- -
- - - - - -
- -
-

资源台账 · 物理机 / 虚机

SINA CMDB asset items + 云厂商同步增量
-
- - - - - - - - - - - -
主机名资产编号类型机房 / 区域内网 IP规格业务线数据来源状态
xs291SERV00003502物理机华东·杭州下沙10.34.37.5220C/192G/13.52TkodoSINA CMDB● production
yzh-las-014SERV00004187虚机华北·YZH10.21.4.21432C/128G/4.0TlasSINA CMDB● production
jf-bm-118SERV00004290物理机华南·JF10.45.2.1816C/64G/2.0TlingxiSINA CMDB● production
ali-ecs-sz-0231—虚机阿里云·华南172.18.4.3116C/64G/500Gltoken阿里云同步● production
aws-us-i-0a13fe2—虚机AWS · 美国10.66.2.128C/32G/200GmaasAWS 同步● production
sg-las-007SERV00004511虚机七牛 LAS · 新加坡10.88.1.0716C/64G/2.0Tlas七牛 LAS 同步● idle
hk-bm-001SERV00004602物理机香港 IDC10.90.0.118C/32G/1.0T未分配SINA CMDB● production
- -
-
- -
- 同步与去重策略:SINA CMDB 作为物理机 / 虚机的基础数据底座;阿里云、AWS、七牛 LAS 的虚机资源由各云 OpenAPI 定时增量同步回写。同步时先以唯一标识(资产编号 / 实例 ID / 内网 IP)查询数据库中是否已存在记录:已存在则跳过更新,保留 CMDB 侧人工维护的字段;不存在则新增记录并标记对应数据来源(SINA CMDB / 阿里云同步 / AWS 同步 / 七牛 LAS 同步),避免重复纳管与覆盖人工修正数据。 -
-
- - -
-
-

服务管理

同步全部机房 Consul 注册中心服务目录,统一查看服务名 / 服务 IP / 业务标签 / 实例数

- -
- -
-
接入 Consul Datacenter
7
国内 3 · 海外 4
-
服务总数
186
去重后唯一服务名
-
服务实例总数
842
所有机房注册 IP 汇总
-
健康实例占比
98.6%
12 个实例 critical
-
最近同步
● 正常
07:41:05 · 间隔 30s
-
- -
- - - - -
- -
-

服务台账 · 按 Consul Datacenter 同步

数据源:Consul Catalog API(/v1/catalog/services · /v1/health/service)
-
- - - - - - - - - - - -
服务名机房 / Datacenter业务标签实例数健康实例示例 IP状态
kodo-gateway-svcYZHkodo1212 / 1210.21.4.51● 健康
kodo-upload-svcXSkodo1010 / 1010.34.37.66● 健康
las-search-apiXSlas1817 / 1810.34.37.20● 部分异常
las-order-svc达拉斯 IDClas55 / 510.66.2.20● 健康
lingxi-render-svcJFlingxi66 / 610.45.2.30● 健康
ltoken-wallet-svcYZHltoken88 / 810.21.4.88● 健康
maas-infer-svc新加坡 IDCmaas43 / 410.88.1.40● 部分异常
- -
-
- -
- 同步方式:xinfra 定时调用各机房 Consul 集群的 Catalog API(/v1/catalog/services、/v1/health/service)按 Datacenter 维度拉取服务目录,汇总服务名、注册 IP、健康检查状态以及 Consul service tag 中携带的业务标签(kodo / las / lingxi / ltoken / maas),实现跨机房服务的统一查看与健康巡检,不改变各机房 Consul 自身的注册与发现链路。 -
-
-
-
-

监控 / 日志 / 告警

VictoriaMetrics 指标 · Zabbix 硬件状态 · ELK 日志中心 · 夜莺(Nightingale)统一告警引擎对接 qpass

-
-
-
-

VictoriaMetrics · 指标概览

K8s / 容器 / 业务指标
-
- - - - - -
七机房采集节点数128
活跃时序数量42.6M
Prometheus 接口接入● 正常
Grafana 仪表盘数37
-
-
-
-

Zabbix · 硬件健康

IPMI / 温度 / 电源 / 风扇
-
- - - - - -
物理机监控覆盖186 / 186
当前告警● 2 条(风扇转速异常)
网络设备健康● 正常
存储健康度● 正常
-
-
-
-
-

日志 + 统一告警

Filebeat → Kafka → ES → Kibana · VM + Zabbix → qpass
-
-
07:39:10CMDB 采集器同步完成:xs291 · 华东-杭州下沙机房
-
07:38:55[Zabbix] 告警:yzh-las-014 风扇转速低于阈值(FAN_6: 1920 RPM)
-
07:38:02[VictoriaMetrics] 七机房抓取任务全部正常
-
07:35:41[ELK] sg-las-007 应用日志接入 Kafka topic:las-sg-app
-
07:30:00[qpass] 告警已合并推送:1 条硬件告警 + 0 条业务告警
-
-
-
- - -
-
-

任务中心

所有 ansible-playbook / Wayne 发布任务的执行记录与实时日志

-
-
-
-

任务列表

-
- - - - - - - -
● 执行中RKE2 节点加入 · bj-node-061roles/rke2-node-join
● 成功MySQL 主从部署 · kodoroles/mysql-deploy
● 成功Redis Cluster 部署 · lasroles/redis-deploy
● 失败openresty 网关部署roles/openresty-deploy
● 成功业务线标签同步 · LDAPinternal/label-sync
● 成功MySQL 主从部署 · ltokenroles/mysql-deploy
- -
-
-
-

实时日志 · RKE2 节点加入

WebSocket 流式输出
-
-
10:42:01PLAY [rke2-node-join] **********************
-
10:42:02TASK [初始化内核参数] ...
-
10:42:04ok: [bj-node-061]
-
10:42:05TASK [安装 containerd] ...
-
10:42:18ok: [bj-node-061]
-
10:42:19TASK [写入 RKE2 node-labels: business-line=kodo] ...
-
10:42:20changed: [bj-node-061] => labels applied
-
10:42:21TASK [加入集群 rke2-bj-prod-01] ...
-
10:42:33▌ 等待节点 Ready...
-
-
-
-
- - -
-
-

配置中心管理

Apollo 配置中心(携程开源)· 按机房部署 Config Service Cluster,Portal 统一入口管理

- ● 运行中 -
- -
-
接入机房数
3 / 7
国内 3 已接入 · 海外 4 建设中
-
Apollo Cluster
7
按机房 1:1 划分
-
配置项总数
1,260
Namespace 38 个
-
接入业务线
2 / 5
kodo · las 已接入
-
同步状态
● 正常
最近发布 09:12:30
-
- -
-

统一入口

Apollo Portal · LDAP 单点登录
-
-
-

Apollo Portal

apollo.xinfra.internal
-

统一管理 7 个机房 Config Service Cluster 的配置发布、灰度、回滚与变更审计,所有机房配置项均可在此单一入口检索与编辑,发布后由各机房 Config Service 就近下发。

-
LDAP 原生配置接入 · 已上线
- 打开 Apollo Portal ↗ -
-
-
- -
-

部署架构说明

Config Service / Admin Service / Portal
-
-
-
-
Portal + Admin Service YZH 主中心统一部署
-
配置发布、权限、审计统一入口
-
LDAP 账号统一登录
-
跨机房管理所有 Cluster
-
-
-
Config Service 每机房独立集群
-
Cluster = 机房标识(yzh / xs / jf ...)
-
客户端就近读取,降低跨机房延迟
-
单机房故障不影响其他机房取配置
-
-
-
配置数据同步 MySQL 主从 + 缓存
-
ConfigDB / PortalDB 部署在 YZH
-
各机房 Config Service 本地缓存全量配置
-
网络抖动时仍可降级提供本地缓存配置
-
-
-
-
- -
-

机房配置中心列表

Cluster 维度 · Config Service 部署明细
-
- - - - - - - - - - - -
机房 / 区域Apollo ClusterConfig Service 地址承载方式接入业务线配置项数状态
YZH 机房cluster=yzhconfig-yzh.xinfra.internal:8080容器化 · K8s Servicekodo486● 运行中
XS 机房cluster=xsconfig-xs.xinfra.internal:8080容器化 · K8s Servicelas398● 运行中
JF 机房cluster=jfconfig-jf.xinfra.internal:8080容器化 · K8s Service灵矽376● 灰度接入中
达拉斯 IDCcluster=dallas—容器化 · K8s Service—0● 建设中
新加坡 IDCcluster=singapore—容器化 · K8s Service—0● 建设中
香港 IDCcluster=hk—容器化 · K8s Service—0● 待启动
东南亚 IDCcluster=sea—容器化 · K8s Service—0● 待启动
-
-
- -
- 使用说明:YZH / XS 两机房已正式运行,kodo / las 业务线配置已接入;JF 机房处于灰度接入阶段。所有机房的配置统一通过 Apollo Portal 单一入口检索、编辑与发布,发布后由对应机房 Config Service 就近下发给客户端,机房间故障隔离、互不影响。达拉斯、新加坡、香港、东南亚四个海外机房按第三期规划陆续建设 Config Service 集群,建成后接入对应业务线配置。 -
-
- - -
-
-

子系统导航

统一 LDAP 账号,点击即用免二次登录(同账号同密码)

-
-
-
-

Wayne

多集群发布平台
-

业务容器发布、命名空间与配额管理,复用 Wayne 原生多租户能力。

-
LDAP 原生配置接入 · 零代码
-
-
-

open-cdm

SQL 审核与变更平台
-

数据库 SQL 上线统一审核,支持 LDAP 用户组到角色的自动映射。

-
LDAP 原生配置接入 · 零代码
-
-
-

CacheCloud

Redis 统一管理平台
-

Redis 实例全生命周期管理,登录与监控运维统一入口。

-
LDAP 接入改造中 · 预计 3 天
-
-
-

qpass

统一告警 / 值班平台
-

夜莺、Zabbix、VictoriaMetrics 告警统一收敛与值班通知,按 P0/P1 分级推送。

-
LDAP 原生配置接入 · 零代码
-
-
-

Grafana

指标可视化平台
-

对接 VictoriaMetrics 数据源,K8s / 容器 / 业务指标统一仪表盘展示。

-
LDAP 原生配置接入 · 零代码
-
-
-

Apollo

配置中心(携程开源)
-

统一配置管理,按机房 Cluster 隔离,支持灰度发布、版本回滚与变更审计。

-
LDAP 接入改造中 · 规划中
-
-
-
- -
-
- - -
- -
- - -
- -
- - -
- -
- -
- - - - - - - diff --git a/docs/ref/平台需求文档-v3.md b/docs/ref/平台需求文档-v3.md deleted file mode 100644 index d4ebd8e..0000000 --- a/docs/ref/平台需求文档-v3.md +++ /dev/null @@ -1,429 +0,0 @@ -# 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 deleted file mode 100644 index 8c64786..0000000 --- a/docs/ref/架构文档-v3.md +++ /dev/null @@ -1,1008 +0,0 @@ -## 概述 - -本文档定义 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 协议 - - - -