Skip to content

fix(scheduler): enforce ResourceQuota for every device backend - #2347

Merged
hami-robot[bot] merged 2 commits into
Project-HAMi:masterfrom
Lakshya77089:fix/multi-vendor-resource-quota
Aug 5, 2026
Merged

fix(scheduler): enforce ResourceQuota for every device backend#2347
hami-robot[bot] merged 2 commits into
Project-HAMi:masterfrom
Lakshya77089:fix/multi-vendor-resource-quota

Conversation

@Lakshya77089

@Lakshya77089 Lakshya77089 commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

What type of PR is this?

/kind bug

What this PR does / why we need it:

fitResourceQuota in the admission webhook only ever looked at NVIDIA:

// Only supports NVIDIA
if deviceName != nvidia.NvidiaGPUDevice {
    continue
}

So a namespace ResourceQuota on cambricon.com/mlu.smlu.vmemory,
huawei.com/Ascend910B-memory, hygon.com/dcumem or any other vendor resource
was accepted by the apiserver and then ignored. Pods were admitted no matter how
much of that quota the namespace had already used. QuotaManager itself is
device agnostic and works fine when called directly, so the gap is entirely in
the wiring.

Two commits:

  1. refactor(device): name the vmemory scaling constants — no behaviour change,
    pulled out so the second diff is readable.
  2. fix(scheduler): enforce ResourceQuota for every device backend — the fix.

The unit problem, and why the loop could not just be widened

This is where the earlier attempt in #2218 came unstuck, and @mesutoezdil's
review there is what shaped this patch. Several backends scale the memory value
from the pod spec before recording it as used:

backend scale
nvidia, ascend, hygon configured memoryFactor
cambricon, iluvatar 256
mthreads 512
metax sgpu 1024

Recorded usage is in scaled units. A ResourceQuota limit is written in
unscaled ones. Compare them directly and a pod asking for 50 units of MLU
vmemory against a 100 unit limit is measured as 12800 against 100 and denied,
even though it is well inside quota. Hardcoding memoryFactor = 1 for
non-NVIDIA backends, which is what #2218 did, produces exactly that.

So each backend now reports its own scale through a new
ResourceNames.MemoryFactor, and FitQuota raises the limit by it — the same
thing it already did for NVIDIA. Backends that do not scale leave it zero.

The webhook also stops re-reading the container spec by hand and asks the
backend instead:

req := dev.GenerateResourceRequests(&pod.Spec.Containers[i])
memoryReq += int64(req.Memreq) * int64(req.Nums)
coresReq  += int64(req.Coresreq) * int64(req.Nums)

That is the same call the scheduler makes on the Fit path, so admission and the
scheduler now work from identical numbers, including per-backend defaults and
Ascend's template rounding. It also drops about 25 lines of duplicated
limits/requests parsing.

Tests

TestFitResourceQuotaNonNvidia, TestFitResourceQuotaCountsEveryDevice and
TestFitResourceQuotaAscendMemoryFactor in pkg/scheduler/webhook_test.go.
They cover deny and allow for MLU memory, MLU cores, DCU memory with
memoryFactor: 2, Ascend with memoryFactor: 4, multi-device requests, and a
namespace with no quota. All five deny cases fail on master and pass with this
change.

TestFitResourceQuotaAscendMemoryFactor asserts the backend actually registered
before running, because the existing TestFitResourceQuota/request_ascend case
passes vacuously today — Ascend is behind --enable-ascend and was never in
DevicesMap for that test.

Which issue(s) this PR fixes:
Fixes #2157

Special notes for your reviewer:

Two behaviour changes worth a second look:

  • NVIDIA memory quota now counts defaultMemory when a pod asks for
    nvidia.com/gpu without nvidia.com/gpumem. The old code only counted memory
    the pod named explicitly, which under-counted against what the scheduler
    actually records. Default config has defaultMemory: 0, so most deployments
    see no difference.
  • Backends that default cores when none are requested (cambricon defaults to
    100) now have those cores counted. Same reasoning: that is what ends up in
    Usedcores.

Deliberately left out, happy to add if you would rather see them here:

Not validated on real hardware. The change is confined to the scheduler
extender's admission path and is covered by unit tests, which CONTRIBUTING
allows for scheduler-scoped changes.

Does this PR introduce a user-facing change?:

ResourceQuota limits on non-NVIDIA accelerator memory and core resources are now
enforced at admission instead of being silently ignored.

AI assistance disclosure: this change was developed with Claude Code — codebase
exploration, working through the per-backend unit scaling, the tests, and this
description. Flagging the extent up front per CONTRIBUTING.

@hami-robot hami-robot Bot added kind/bug Something isn't working dco-signoff: no labels Aug 4, 2026
@hami-robot
hami-robot Bot requested review from archlitchi and wawa0210 August 4, 2026 09:25
@hami-robot

hami-robot Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Welcome @Lakshya77089! It looks like this is your first PR to Project-HAMi/HAMi 🎉

@hami-robot hami-robot Bot added the size/L label Aug 4, 2026
@coderabbitai

coderabbitai Bot commented Aug 4, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR adds MemoryFactor to ResourceNames, exposes it across device backends, and replaces hardcoded memory conversion values with named constants. The webhook now validates quota usage for all supported backends through backend-generated resource requests.

Changes

MemoryFactor propagation and generalized quota enforcement

Layer / File(s) Summary
ResourceNames memory-factor contract
pkg/device/devices.go
Adds ResourceNames.MemoryFactor and documents its use in memory scaling and quota checks.
Backend memory-factor propagation
pkg/device/ascend/device.go, pkg/device/cambricon/device.go, pkg/device/hygon/device.go, pkg/device/iluvatar/device.go, pkg/device/metax/sdevice.go, pkg/device/mthreads/device.go, pkg/device/nvidia/device.go
Defines backend conversion constants, replaces hardcoded multipliers, and reports MemoryFactor through GetResourceNames.
Generic webhook quota validation
pkg/scheduler/webhook.go
Uses GenerateResourceRequests for quota-capable backends, aggregates memory and core requests, and applies backend-provided memory factors.
Cross-backend quota tests
pkg/scheduler/webhook_test.go
Adds Cambricon, Hygon, and Ascend quota tests for scaling, over-quota requests, unquotaed namespaces, and per-device multiplication.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Pod
  participant Webhook as fitResourceQuota
  participant Backend as Device Backend
  participant QuotaManager
  Pod->>Webhook: submit pod specification
  Webhook->>Backend: GenerateResourceRequests(container)
  Backend-->>Webhook: memory, core, MemoryFactor
  Webhook->>QuotaManager: FitQuota(namespace, memory, core, MemoryFactor)
  QuotaManager-->>Webhook: allow or deny
  Webhook-->>Pod: admission decision
Loading

Possibly related PRs

Suggested reviewers: archlitchi, wawa0210

Poem

A rabbit checks each memory fare,
For every backend, fair and square.
Factors guide each quota call,
Ascend and MLU count them all.
Core and memory join the queue,
The webhook knows what pods can do. 🐇

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 57.14% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The webhook now enforces vendor memory and core quotas across registered backends, with backend scaling and coverage tests for issue #2157.
Out of Scope Changes check ✅ Passed The changes remain within scope by updating backend memory metadata, webhook quota evaluation, and related tests.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: enforcing ResourceQuota for all device backends.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai
coderabbitai Bot requested a review from DSFans2014 August 4, 2026 09:26
@Lakshya77089
Lakshya77089 force-pushed the fix/multi-vendor-resource-quota branch from 645bc5b to 5cb42f4 Compare August 4, 2026 09:28
cambricon, iluvatar, mthreads and metax each multiply the vmemory value
from the pod spec by a fixed number to get the MiB accounted internally.
The numbers were bare literals repeated between GenerateResourceRequests
and GetNodeDevices. Give each backend a named MemoryFactor constant so
the scale is stated once.

No behaviour change.

Signed-off-by: Lakshya77089 <lakshyasharma7708@gmail.com>
fitResourceQuota skipped every backend except NVIDIA, so a namespace
ResourceQuota on cambricon, ascend, hygon or any other vendor's memory
and core resources was accepted by the apiserver and then ignored.

Units are why this is not simply a wider loop. Backends scale the pod's
memory value before recording it as used, by a configured memoryFactor
for nvidia, ascend and hygon and by a fixed 256, 512 or 1024 elsewhere,
while a ResourceQuota limit is unscaled. Each backend now reports its
scale through ResourceNames.MemoryFactor, and the webhook calls the
backend's GenerateResourceRequests rather than parsing the container
spec, so admission and the scheduler work from the same numbers.

Fixes Project-HAMi#2157

Signed-off-by: Lakshya77089 <lakshyasharma7708@gmail.com>
@Lakshya77089
Lakshya77089 force-pushed the fix/multi-vendor-resource-quota branch from 5cb42f4 to e9454b6 Compare August 4, 2026 09:34
@codecov

codecov Bot commented Aug 4, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 84.61538% with 4 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
pkg/device/cambricon/device.go 66.66% 1 Missing ⚠️
pkg/device/iluvatar/device.go 50.00% 1 Missing ⚠️
pkg/device/metax/sdevice.go 50.00% 1 Missing ⚠️
pkg/device/mthreads/device.go 66.66% 1 Missing ⚠️
Flag Coverage Δ
unittests 60.96% <84.61%> (-0.03%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
pkg/device/ascend/device.go 83.56% <100.00%> (+0.03%) ⬆️
pkg/device/devices.go 91.35% <ø> (ø)
pkg/device/hygon/device.go 92.64% <100.00%> (+0.03%) ⬆️
pkg/device/nvidia/device.go 96.95% <100.00%> (+<0.01%) ⬆️
pkg/scheduler/webhook.go 83.95% <100.00%> (+1.65%) ⬆️
pkg/device/cambricon/device.go 83.26% <66.66%> (-0.33%) ⬇️
pkg/device/iluvatar/device.go 57.72% <50.00%> (-0.27%) ⬇️
pkg/device/metax/sdevice.go 76.81% <50.00%> (-0.16%) ⬇️
pkg/device/mthreads/device.go 86.25% <66.66%> (-0.37%) ⬇️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@mesutoezdil

Copy link
Copy Markdown
Contributor

/lgtm

@mesutoezdil

Copy link
Copy Markdown
Contributor

fit() path is still nvidia only for quota, non-nvidia has a race window between admission and scheduling. pls open a followup issue instead of letting fixes #2157 close it fully.

@archlitchi archlitchi left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/lgtm

@hami-robot

hami-robot Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: archlitchi, Lakshya77089

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] ResourceQuota enforcement only applies to NVIDIA devices, not other accelerator backends

3 participants