Skip to content

Fix exposed service Kueue admission race - #633

Draft
gmolto wants to merge 1 commit into
develfrom
fix/kueue-exposed-admission-wait
Draft

Fix exposed service Kueue admission race#633
gmolto wants to merge 1 commit into
develfrom
fix/kueue-exposed-admission-wait

Conversation

@gmolto

@gmolto gmolto commented Aug 15, 2026

Copy link
Copy Markdown
Member

Summary

  • wait for exposed-service Kueue workloads to transition to Admitted=True instead of treating the first non-admitted snapshot as a definitive rejection
  • reuse the existing 30-second workload admission watcher and timeout
  • scope workload matching by namespace as well as name to avoid cross-namespace collisions
  • return an explicit timeout error when admission does not complete

Problem

The issue was detected while running the OSCAR metrics population Robot suite against a local cluster. The suite created four regular services successfully, but creation of the exposed nginx service intermittently returned HTTP 500.

Manager logs showed the generic message:

Error checking workload admission: change the cpu/memory requests

The Kueue events showed that the workload was initially Pending while the controller evaluated or waited for quota. OSCAR checked the workload immediately after creating it and interpreted the absence of Admitted=True as a permanent rejection. It then deleted the workload and failed service creation before Kueue could publish a later admission update.

This is a race between the synchronous exposed-service creation path and Kueue's asynchronous status reconciliation. A workload that is not admitted in the first snapshot is not necessarily rejected.

Root cause

CheckWorkloadAdmited started and synchronized an informer, read the workload once, and returned an error whenever that snapshot did not already contain Admitted=True. The update handler did not wait for or act on subsequent status transitions.

The codebase already had onlyCheckWorkloadAdmited, which checks the initial informer store and then waits for an admission update until a configurable timeout. The exposed-service path was not using it.

Change

CheckWorkloadAdmited now delegates admission waiting to onlyCheckWorkloadAdmited with the existing 30-second default timeout. If admission succeeds, deployment activation continues as before. If it does not complete within the timeout, the workload is cleaned up and the returned error identifies the timeout.

The shared helper now receives the workload namespace and requires both namespace and name to match, preventing an admitted workload with the same name in another user namespace from satisfying the check.

Impact

Exposed-service creation continues immediately when Kueue has already admitted the workload. When Kueue reconciliation takes longer, the API waits only for the actual delay, up to 30 seconds, instead of returning a premature HTTP 500.

Requests that remain pending because quota is genuinely unavailable still fail after the timeout and preserve the existing cleanup behavior.

Validation

  • go test ./...
  • rebuilt and deployed OSCAR in a local cluster
  • reran the metrics population suite and confirmed that exposed-service creation waits for Kueue admission instead of failing on the first pending snapshot

@gmolto gmolto self-assigned this Aug 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant