Dale Richardson created YUNIKORN-3380:
-----------------------------------------

             Summary: RemoveAllAllocations leaks user/group tracked usage when 
a release-all arrives with pending asks
                 Key: YUNIKORN-3380
                 URL: https://issues.apache.org/jira/browse/YUNIKORN-3380
             Project: Apache YuniKorn
          Issue Type: Bug
          Components: core - scheduler
            Reporter: Dale Richardson


A release-all (AllocationRelease with an empty allocation key) that is processed
while the application still has a pending ask permanently leaks the 
application's
allocated resources into the user/group tracker. The leaked amount reduces the
user's headroom until the scheduler restarts.

h3. Mechanism

{{Application.RemoveAllAllocations}} (application.go:2111):

{code}
if ugm.GetUserManager().GetUserTracker(sa.user.User) != nil && 
resources.IsZero(sa.pending) {
    sa.decUserResourceUsage(resources.Add(sa.allocatedResource, 
sa.allocatedPlaceholder), true)
}
sa.allocatedResource = resources.NewResource()   // wiped unconditionally
sa.allocatedPlaceholder = resources.NewResource()
{code}

The tracker decrement is gated on IsZero(sa.pending), but the totals are wiped
right after regardless. With pending non-zero the decrement is skipped and can
never happen (the totals are already zero). On the release-all path,
{{removeAllocation}} then drops the asks (partition.go:1585), so pending ends at
zero and the state looks clean everywhere except inside the tracker.

The app-removal path is NOT affected: {{removeApplication}} removes all asks 
first
(partition.go:422), so pending is already zero when RemoveAllAllocations runs 
and
the decrement fires.

h3. Reproduction

App with one running allocation and one pending ask; deliver an empty-key
release-all; the user and group trackers permanently report the leaked usage 
with
no owning application. Subsequent asks by that user are rejected with
NotEnoughUserQuota once the leak eats the limit. {{TestRemoveAppAllocs}} 
exercises
the same call only with no pending asks, which is why it is uncaught. Reproduced
against master via a partition-accounting property test (its user/group 
invariant
fires on this within seconds once release-all is generated).

h3. Reachability (checked)

Not emitted by the current Kubernetes shim. App removal uses the 
RemoveApplication
request (the asks-first path, no leak); per-task releases always carry the pod 
UID
as the allocation key (si_helper.go:154). {{removeAllocation}} is driven only by
inbound RM releases (context.go:779). The empty-key release-all branch
(partition.go:1461) is a deliberately-supported SI message, so the bug is latent
in the core/SI contract and reachable by any RM that sends it (or by a future
k8shim change), but not by the shim as it stands today.

h3. Impact

Silent, permanent per-occurrence quota corruption in clusters using user/group
limits, cleared only by restart. Latent today; correctness bug in a supported SI
code path.

h3. Fix sketch

Decrement the tracker guarded only by tracker existence (drop the 
IsZero(pending)
condition) before the totals are wiped; the pending state of asks is irrelevant 
to
returning resources that were tracked as allocated.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to