完善预排队资源限制与作业准入校验#398
Conversation
YiD11
commented
Apr 28, 2026
- 新增作业准入校验,提交前基于节点可用资源、亲和性、污点容忍等约束判断作业是否可放置。
- 调整队列资源限制模型
- 将预排队候选作业数改为全局系统配置
- 提交普通作业时区分“单次请求超限”和“当前使用量超限”:请求本身超限直接拒绝,使用量超限则进入预排队。
There was a problem hiding this comment.
Pull request overview
本 PR 旨在完善 Prequeue/队列配额体系:将“预排队候选作业数”提升为全局系统配置、调整队列配额模型(简化为仅保留 quota)、并在作业提交前新增基于调度约束的准入校验,同时同步更新前端管理界面与多语言文案。
Changes:
- 后端新增作业准入校验模块,并在作业提交流程中接入;同时将 prequeueCandidateSize 迁移为全局 Prequeue 配置项。
- 队列配额(queue quota)模型/接口收敛:移除 per-queue 的 enabled 与 prequeueCandidateSize 字段,迁移数据库字段并更新 swagger。
- 前端管理端同步:在账户(default)中配置/展示“队内上限(queueLimit)”,调整平台设置页的 Prequeue 配置项,更新表格分页与多语言。
Reviewed changes
Copilot reviewed 35 out of 35 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| frontend/src/utils/quota.ts | Quota 表单结构新增 queueLimit,并提供表单与 queue-quota 的转换函数 |
| frontend/src/services/api/system-config.ts | Prequeue 配置接口新增 prequeueCandidateSize 字段 |
| frontend/src/services/api/queue-quota.ts | QueueQuota 接口类型移除 enabled / prequeueCandidateSize 等字段 |
| frontend/src/routes/admin/more/index.tsx | 平台设置页移除旧“用户资源限制”管理,改为维护全局 prequeueCandidateSize |
| frontend/src/routes/admin/more/-components/user-resource-limit.tsx | 删除旧的用户资源限制 UI 组件 |
| frontend/src/routes/admin/more/-components/prequeue-settings.tsx | Prequeue 配置表单新增候选作业数输入项 |
| frontend/src/routes/admin/accounts/-components/account-table.tsx | 账户表格新增“队内上限”列并读取 default queue quota 展示 |
| frontend/src/routes/admin/accounts/-components/account-form-component.tsx | default 账户支持编辑/保存 default queue quota(queueLimit)并做 hydration/invalidate |
| frontend/src/i18n/locales/zhCN/translation.json | 新增/调整队内上限、Prequeue 候选作业数、弹性(backfill)相关文案及 toast 文案 |
| frontend/src/i18n/locales/enUS/translation.json | 同步新增/调整对应英文文案 |
| frontend/src/i18n/locales/ja/translation.json | 同步新增/调整对应日文文案 |
| frontend/src/i18n/locales/ko/translation.json | 同步新增/调整对应韩文文案 |
| frontend/src/components/query-table/index.tsx | 表格排序/过滤/全局搜索变更时重置页码,并关闭 autoResetPageIndex |
| backend/pkg/vcjob/admission/admission.go | 新增作业准入校验:基于节点约束与资源进行放置模拟 |
| backend/pkg/utils/resource.go | 资源工具增强:复制、覆盖判断、缺口计算、汇总展示、按副本累加等 |
| backend/pkg/reconciler/vcjob-reconciler.go | 事件/终止状态采集触发条件改为 isReleasedJobPhase |
| backend/pkg/prequeuewatcher/scheduling.go | 移除本地 node 约束匹配逻辑,复用 vcjob admission 的约束判断;可用资源计算保留 |
| backend/pkg/prequeuewatcher/resources.go | 复用 utils.ResourceListCovers,移除重复实现 |
| backend/pkg/prequeuewatcher/preemption.go | 复用 admission 的约束判断与 utils.ResourceDeficit;细化过滤条件 |
| backend/pkg/prequeuewatcher/activation.go | 激活批次使用全局 prequeueCandidateSize 限制候选扫描与激活数量 |
| backend/internal/service/vcjob/runtime.go | 资源统计改用 utils.CalculateReplicatedResources 复用逻辑 |
| backend/internal/service/prequeue_service.go | 队列配额结构/解析逻辑调整;新增 CheckRequestedResourceLimit 以区分“单次请求超限” |
| backend/internal/service/config_service.go | PrequeueRuntimeConfig 新增 prequeue_candidate_size 配置项并纳入校验/序列化 |
| backend/internal/handler/system_config.go | Prequeue 配置接口新增字段并强制 required,gt=0 校验 |
| backend/internal/handler/queue_quota.go | QueueQuota API 请求/响应移除 enabled 与 prequeueCandidateSize 字段 |
| backend/internal/handler/vcjob/tensorflow.go | 资源统计改用 utils.CalculateReplicatedResources,移除 aitaskctl 依赖 |
| backend/internal/handler/vcjob/pytorch.go | 同上:资源统计改用 utils.CalculateReplicatedResources |
| backend/internal/handler/vcjob/lifecycle.go | 提交流程接入 admission 校验与队列配额“请求超限/使用超限”区分逻辑 |
| backend/docs/swagger.yaml | Swagger 定义同步:新增 prequeueCandidateSize、调整 queue quota 结构 |
| backend/docs/swagger.json | Swagger JSON 同步更新 |
| backend/docs/docs.go | swag 生成模板同步更新 |
| backend/dao/query/queue_quotas.gen.go | gorm-gen 查询字段同步移除 enabled / prequeue_candidate_size |
| backend/dao/model/queue_quota.go | QueueQuotaLimit 模型移除 enabled / prequeueCandidateSize 字段 |
| backend/dao/model/prequeue_config.go | Prequeue 配置新增 prequeue_candidate_size key 与默认值常量 |
| backend/cmd/gorm-gen/models/migrate.go | 新增迁移:删除 queue_quotas 表的 enabled 与 prequeue_candidate_size 列 |
| type="string" | ||
| placeholder={t('accountForm.queueLimitPlaceholder')} | ||
| className="font-mono" | ||
| {...form.register(`resources.${index}.queueLimit`, { | ||
| valueAsNumber: true, |
There was a problem hiding this comment.
【核心规范】该输入框使用了无效的 HTML input 类型 type="string",但同时又启用了 valueAsNumber。浏览器会把未知类型当作 text 处理,用户输入非数字或清空时会被转成 NaN,最终 convertFormToQueueQuota 会忽略该字段,导致“队内上限”无法稳定保存。建议改为 type="number"(并设置 min/step),同时对空值用 setValueAs/onChange 显式转成 undefined。
| remaining := make([]v1.ResourceList, len(nodeList.Items)) | ||
| for i := range nodeList.Items { | ||
| remaining[i] = utils.CopyResources(nodeList.Items[i].Status.Allocatable) | ||
| } |
There was a problem hiding this comment.
【核心规范】这里用 node.Status.Allocatable 作为“剩余可用资源”进行准入判断,但 allocatable 是节点可分配总量,不包含当前已被 Pod 请求占用的资源;因此可能会误判“可准入”,提交后仍长期 Pending,和 PR 描述的“基于节点可用资源”不一致。建议改为基于 allocatable - 已分配(可参考 prequeuewatcher 的按节点列 Pod 再 SumRequests 的实现)计算 available 后再做放置模拟。
| scheduleTypeInt, err := strconv.ParseInt( | ||
| job.Annotations[vcjobservice.AnnotationKeyScheduleType], 10, 64, | ||
| ) | ||
| if err != nil { | ||
| return fmt.Errorf("invalid schedule type annotation value: %w", err) | ||
| return 0, fmt.Errorf("invalid schedule type annotation value: %w", err) |
There was a problem hiding this comment.
【核心规范】调度类型解析这里直接 strconv.ParseInt 读取注解,注解缺失(空字符串)会直接报错;同时也不兼容历史上可能存在的字符串值(例如 backfill),而代码库里已有 vcjobservice.ParseJobScheduleMetadata / model.ParseScheduleType 处理默认值与兼容格式。建议复用已有解析函数,避免因注解格式/缺失导致作业提交被拒绝。
| score float64 | ||
| } | ||
|
|
||
| func CheckJobAdmission(ctx context.Context, k8sClient client.Client, job *batch.Job) (*Result, error) { |
There was a problem hiding this comment.
【优化建议】新增的作业准入放置模拟逻辑(资源计算 + 亲和/污点匹配 + best-fit 选择)属于关键调度路径,建议补充单测覆盖典型场景(nodeSelector/required nodeAffinity、NoSchedule taint + toleration、多 task/多副本、资源不足的拒绝原因)。可以参考 backend/pkg/prequeuewatcher/watcher_test.go 使用 controller-runtime fake client 构造 Node/Pod/Job。