- Add Workspace domain (entity, repository, service, handler, DTO) - Add multi-tenant K8s client with tenant binding and quota management - Add K8s diagnostics client (instance diagnostics) - Add authorization middleware (authz package) - Restructure frontend to feature-based architecture (features/) - Add User Management page in configuration - Add AccessDenied page and route guards - Refactor shared components (form inputs, layout, UI) - Update Tailwind config for new design system - Add comprehensive documentation (docs/, tasks/, plans) - Improve cluster service with better kubeconfig handling - Add tests for crypto, config, helm client, tenant binding
5.6 KiB
5.6 KiB
OCDP 第二次测试报告
测试日期: 2026-05-11 测试环境: http://10.6.80.114:18080
测试1: 资源配额限额
测试方法
使用 test-user-b(quota: cpu=2, mem=4Gi, gpu=0, gpumem=0)在 k3s 集群部署 nginx chart
测试结果
| 测试 | 操作 | 预期 | 实际 | 结论 |
|---|---|---|---|---|
| Test A | 部署 nginx(默认值,在配额内) | 成功 | 部署完成,状态 deployed | ✅ |
| Test B | 部署 nginx(requests.cpu=2, mem=4Gi, replica=5,超配额) | 被配额阻止 | Helm release 创建成功,所有 Pod 被 ResourceQuota 阻塞,状态永远 stuck 在 pending-install | ⚠️ 部分通过 |
| Test C | 部署 vllm-serve(gpuLimit=1,gpu配额=0) | 被配额阻止 | Helm release 创建成功,Pod 被 ResourceQuota 阻塞,状态 pending-install | ⚠️ 部分通过 |
关键发现
1. 没有 API 层的预检查配额验证
- 后端 API 无条件接受所有部署请求,不检查是否超配额
- 所有超配额请求返回 HTTP 200 + status: pending-install
- 后端日志中没有任何配额相关的条目
2. K8s ResourceQuota 在 Pod 级别执行
tenant-quotaResourceQuota 对象确实存在并执行限制- 当 Pod 超配额时,K8s 明确拒绝创建并给出错误消息
- 但 Helm release、Service、Deployment、ReplicaSet 仍然被创建
3. 实例永远 stuck 在 "pending-install"
- 超配额的实例永远不会转换到 deployed/failed/error
- OCDP 平台不检测 ResourceQuota 拒绝事件
- 唯一知道失败的方式是直接查 K8s events
4. GPU 配额绕过
- gpu=0 的用户可以提交需要 GPU 的 chart 部署
- K8s ResourceQuota 最终会阻止,但 Helm release 等资源已被创建
5. 有效的 ResourceQuota 配置
apiVersion: v1
kind: ResourceQuota
metadata:
name: tenant-quota
namespace: ocdp-u-test-b
spec:
hard:
requests.cpu: "2"
requests.memory: 4Gi
requests.nvidia.com/gpu: "0"
requests.nvidia.com/gpumem: "0"
建议
- 添加 API 层预检查配额验证 — 在接受部署前检查请求资源是否超过用户配额
- 处理 pending-install 超时 — 监控 Helm release 创建后 Pod 是否 stuck,更新状态为 failed
- GPU 配额预检查 — 如果 chart 需要 GPU 而用户 gpu=0,在 API 层拒绝
- UI 配额指示器 — 在部署表单上显示剩余配额
测试2: values.yaml 覆盖优先级
测试方法
使用 test-user-c(quota: cpu=4, mem=8Gi, gpu=1, gpumem=5000)部署 vllm-serve:0.6.0 chart
测试结果
| 方法 | 提交方式 | 是否部署成功 | 存储的值 | 结论 |
|---|---|---|---|---|
| 方法1 | values JSON 字段 |
✅ | cpuRequest=2, gpuMem=10000 | JSON 值被准确接受和存储 |
| 方法2 | valuesYaml 字符串 |
✅ | cpuRequest=4, gpuMem=10000 | YAML 被正确解析为结构化 values |
| 方法3 | 同时提供 values + valuesYaml(冲突) |
✅ 无任何错误/警告 | values JSON 全胜 | values JSON 静默覆盖 valuesYaml |
| 方法4 | 不提供任何 values(使用 chart 默认) | ✅ | 仅 namespace | chart 默认值不存储在 API 响应中 |
优先级最终结论
| 优先级 | 来源 | 说明 |
|---|---|---|
| 最高 | values JSON 字段 |
请求体中的结构化 JSON |
| 中 | valuesYaml 字符串 |
请求体中的 YAML 字符串 |
| 最低 | Chart 内置 values.yaml | Helm chart 打包的默认值 |
冲突测试详细结果
当同时提供 values 和 valuesYaml 且值冲突时:
valuesJSON 字段完全覆盖valuesYaml- 没有任何错误或警告返回给用户
- 两者被合并到统一的 DB
values字段
gpuMem=10000 行为
- 整数值
10000在valuesJSON 和valuesYaml中都被正确接受 - 无单位转换(作为整数 MB 标量存储)
- 符合项目规范
建议
- 记录优先级顺序 — 用户需知道同时提供两者时 values JSON 优先
- 添加冲突警告 — 当两个字段存在冲突值时应返回警告
- 考虑废弃一个字段 — values 和 valuesYaml 语义重复易混淆
测试3: 前端 UI 溢出/滚动/刷新
测试方法
Playwright + 源码分析,测试 1920/768/375 三个视口
测试结果
总体结论: PASS — 没有导致功能问题的关键溢出问题
| 测试项 | 结果 | 详情 |
|---|---|---|
| 水平溢出 | ✅ 无问题 | 所有视口均无水平溢出 |
| 文本截断 | ⚠️ 1 个低风险 | InstanceCard h3 标题 truncate 无 title tooltip |
| 响应式设计 | ✅ 正确 | sm/md/lg/xl 断点覆盖完整 |
| 滚动行为 | ✅ 流畅 | Sidebar 和内容区独立滚动,overscroll-contain 防滚动穿透 |
| 模态框布局 | ✅ 正确 | body scroll lock + 内容独立滚动 |
| 页面刷新 | ✅ 正常 | 受保护路由正确重定向到登录页 |
| 颜色对比度 | ⚠️ 1 个中风险 | 登录页错误文本 red-400 在白色背景上仅 2.5:1 (WCAG AA 要求 4.5:1) |
通过的细分项
- Chart Browser 全高 + overflow-y-auto 布局 ✅
- InstanceCard 操作按钮网格 grid-cols-2/3/5 响应正确 ✅
- Tabs 支持 overflow-x-auto 水平滚动 ✅
- 用户管理表格 overflow-x-auto ✅
- iOS 触摸滚动 (
-webkit-overflow-scrolling: touch) 已配置 ✅
建议
- 将登录页错误文本从 text-red-400 改为 text-red-600/700
- InstanceCard h3 标题添加 title 属性
综合建议
- 添加 API 层配额预检查
- 处理 pending-install 超时 + 状态更新
- 记录 values 覆盖优先级并添加冲突警告
- 统一 values JSON/YAML 的 API 设计