Repository navigation
feat: add Task-native budget enforcement via TaskBudget and TaskRecord CRDs - #1426
Conversation
|
cc @knechtionscoding updated a bit based on your PR to introduce a new validation webhook to prevent invalid resources from being accepted. Can you review this? |
|
/kelos review |
|
🤖 Kelos Task Status Task |
|
🤖 Kelos Reviewer Agent @gjkim42 Review SummaryVerdict: REQUEST CHANGES (sticky comment only) Findings Overview
FindingsCorrectness
API Compatibility
Key takeaways
|
There was a problem hiding this comment.
8 issues found across 45 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="api/v1alpha2/task_types.go">
<violation number="1" location="api/v1alpha2/task_types.go:421">
P2: v1alpha1 clients can accidentally erase the new Task budget/accounting status fields on status updates, because the conversion path does not preserve v1alpha2-only `status.usage` or `status.conditions`. Consider extending conversion to preserve these hub-only status fields (for example via annotations or explicit carry-forward) while v1alpha1 remains served.</violation>
</file>
Tip: cubic can generate docs of your entire codebase and keep them up to date. Try it here.
Re-trigger cubic
| // Usage contains structured cost and token usage populated from results | ||
| // when the Task reaches a terminal phase. | ||
| // +optional | ||
| Usage *TaskUsage `json:"usage,omitempty"` |
There was a problem hiding this comment.
P2: v1alpha1 clients can accidentally erase the new Task budget/accounting status fields on status updates, because the conversion path does not preserve v1alpha2-only status.usage or status.conditions. Consider extending conversion to preserve these hub-only status fields (for example via annotations or explicit carry-forward) while v1alpha1 remains served.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At api/v1alpha2/task_types.go, line 421:
<comment>v1alpha1 clients can accidentally erase the new Task budget/accounting status fields on status updates, because the conversion path does not preserve v1alpha2-only `status.usage` or `status.conditions`. Consider extending conversion to preserve these hub-only status fields (for example via annotations or explicit carry-forward) while v1alpha1 remains served.</comment>
<file context>
@@ -412,6 +414,37 @@ type TaskStatus struct {
+ // Usage contains structured cost and token usage populated from results
+ // when the Task reaches a terminal phase.
+ // +optional
+ Usage *TaskUsage `json:"usage,omitempty"`
+
+ // Conditions provides detailed status information.
</file context>
There was a problem hiding this comment.
Valid, but intentionally not addressed in this update. This batch excludes conversion-related changes, so the v1alpha1 carry-forward/preservation work should stay open for a separate follow-up.
There was a problem hiding this comment.
That’s fair — the conversion carry-forward gap is still the right issue, just out of scope for this batch. The parent comment still applies for the v1alpha1↔v1alpha2 status conversion path, and it should stay open as a separate follow-up.
9d9b9d2 to
940e7ed
Compare
|
/kelos glm-review |
|
🤖 Kelos Task Status Task |
940e7ed to
98bdb0e
Compare
|
/kelos glm-review |
|
🤖 Kelos Task Status Task |
|
🤖 Kelos GLM Reviewer Agent @gjkim42 Review SummaryVerdict: APPROVE Findings Overview
FindingsCorrectness / Conventions
Suggestions
Key takeaways
|
98bdb0e to
87e71bd
Compare
…d CRDs Replace TaskSpawner-owned budgetPolicy with Task-native budget enforcement that applies to any Task. Add TaskBudget and TaskRecord CRDs, structured Task usage accounting, validating admission for TaskBudget selectors, durable TaskRecord creation and retry paths, and budget-aware controller behavior for Job-backed and worker-pool Tasks. Include generated CRDs, Helm manifests, docs, examples, unit tests, integration tests, and e2e coverage for TaskBudget admission, TaskBudget validating webhook rejection, TaskRecord validation, worker-pool accounting, CRD staging, and compatibility behavior. Closes #977 Co-authored-by: Gunju Kim <gjkim042@gmail.com>
87e71bd to
a57b205
Compare
What type of PR is this?
/kind feature
What this PR does / why we need it:
Replaces the TaskSpawner-owned
budgetPolicywith a Task-native design that enforces spending controls on any Task regardless of how it was created (CLI, YAML, webhook, or TaskSpawner).The original approach tied cost governance to the TaskSpawner, which left direct Tasks outside the model. This redesign makes budget enforcement a first-class Task concern via three new API surfaces:
New CRDs:
TaskBudget— namespace-scoped policy that gates Task admission using label selectors. Supports daily period accounting (timezone-aware) with cost and token limits. Blocked Tasks stay inWaitingphase with aBudgetBlockedcondition until the period resets.TaskRecord— immutable terminal record created when a Task completes. Survives Task TTL deletion (no ownerReference) and serves as the durable accounting source for budget enforcement.New Task.status fields:
status.usage— structuredTaskUsage(costUSDasresource.Quantity,inputTokens,outputTokens) populated fromstatus.resultson completion.status.conditions— typed conditions includingBudgetBlocked.Admission semantics:
TaskBudget.spec.taskSelectormatches Tasks by label (usesmetav1.LabelSelector)TaskRecordusage within the current periodDegradedcondition on the TaskBudgetTaskSpawner integration:
taskTemplate.metadata.labelsBudgetPolicy,CostBudget,PeriodBudget,BudgetStatus,HighCostTaskRecordtypes; spawner-side enforcement;accumulateSpawnerCost;kelos_spawner_budget_*Prometheus gauges;TaskCountExhausted/TaskBudgetExhausted/CostBudgetExceededconditionsDesign decisions:
resource.Quantityfor cost fields (type-safe, integrates with k8s tooling)BudgetActionenum withBlockas sole value (future-proofs forWarnetc.)NowFuncon reconciler for deterministic testingFollow-up fixes in this update:
TaskBudget.spec.taskSelectorvalidation.kelos-controllerbinary through the existingkelos-webhookService; no separate binary is required.make update/make verifyso the chart includes the generatedValidatingWebhookConfiguration.TaskBudgetselector.TaskBudgethas an invalid period configuration.TaskRecordcreation for unchanged terminal Job-backed Tasks.TaskRecordcreation fails, while returning the error so reconciliation retries the record.TaskRecordlabels, so later Task label mutation cannot move recorded usage out of the matching budget.TaskRecordtype/model from the referencedWorkerPool.spec.worker, without writing deprecated Task fields.TaskRecord.specandTaskRecord.spec.completionTimein the CRD schema.BudgetBlocked=True.TaskBudgetExhaustedTaskSpawner condition alias alongsideMaxTotalTasksReachedfor compatibility.Which issue(s) this PR is related to:
Fixes #977
Special notes for your reviewer:
make updateand included.TaskRecordSpecis immutable after creation (XValidation:self == oldSelf).sumPeriodUsagepushes label filtering server-side viaclient.MatchingLabelsSelector; only time filtering is client-side.TaskBudget.spec.taskSelectorvalues are rejected by the validating admission webhook on create/update.usageFromResults,computePeriodBoundaries,checkLimitsExceeded,createTaskRecord(including idempotency, label snapshot behavior, and worker-pool metadata), validating webhook rejection, e2e validating webhook rejection coverage,TaskRecordAPI validation, terminal TaskRecord retry, worker-pool assignment cleanup after record failures, worker-pool budget wakeup filtering, TaskSpawner condition aliases, install CRD staging lists, and invalid stored period fail-closed behavior.examples/14-task-budget/taskbudget.yaml.Validation:
git diff --checkmake testmake test-integrationmake verifygo test ./test/e2e -run TestDoesNotExistDoes this PR introduce a user-facing change?