Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changes/unreleased/fixed-20261013-151729.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
kind: Fixed
body: |-
DRA claims with admin access no longer count as GPU usage
custom:
Author: "brokenlander"
Issue: "26"
16 changes: 10 additions & 6 deletions utilities/resources/dra.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"k8s.io/client-go/rest"
draclient "k8s.io/dynamic-resource-allocation/client"
resourceinstall "k8s.io/kubernetes/pkg/apis/resource/install"
"k8s.io/utils/ptr"
"sigs.k8s.io/controller-runtime/pkg/client"

commonmath "github.com/kai-scheduler/api/utilities/math"
Expand Down Expand Up @@ -160,13 +161,20 @@ func IsGPUDeviceClass(deviceClassName string) bool {
// Returns empty string if no GPU device class is found.
func getGPUDeviceClassNameFromClaim(claim *resourceapi.ResourceClaim) string {
for _, request := range claim.Spec.Devices.Requests {
if request.Exactly != nil && IsGPUDeviceClass(request.Exactly.DeviceClassName) {
if isGPUConsumingRequest(request) {
return request.Exactly.DeviceClassName
}
}
return ""
}

// isGPUConsumingRequest excludes admin access requests: they share the device and consume no GPU capacity.
func isGPUConsumingRequest(request resourceapi.DeviceRequest) bool {
return request.Exactly != nil &&
IsGPUDeviceClass(request.Exactly.DeviceClassName) &&
!ptr.Deref(request.Exactly.AdminAccess, false)
}

// countGPUDevicesFromClaim counts GPU devices from a ResourceClaim.
// Returns the total count of GPU devices requested by this claim.
//
Expand All @@ -177,11 +185,7 @@ func countGPUDevicesFromClaim(claim *resourceapi.ResourceClaim) int64 {
totalCount := int64(0)

for _, request := range claim.Spec.Devices.Requests {
if request.Exactly == nil {
continue
}

if !IsGPUDeviceClass(request.Exactly.DeviceClassName) {
if !isGPUConsumingRequest(request) {
continue
}

Expand Down
85 changes: 85 additions & 0 deletions utilities/resources/dra_gpu_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,91 @@ var _ = Describe("DRA GPU Extraction", func() {
Expect(count).To(Equal(int64(0))) // Unknown mode skipped
})
})

Context("when GPU requests use admin access", func() {
adminRequest := func(name string, mode resourceapi.DeviceAllocationMode, count int64) resourceapi.DeviceRequest {
return resourceapi.DeviceRequest{
Name: name,
Exactly: &resourceapi.ExactDeviceRequest{
DeviceClassName: constants.NvidiaGpuResource,
AllocationMode: mode,
Count: count,
AdminAccess: ptr.To(true),
},
}
}

It("should not count an ExactCount admin access request", func() {
claim := &resourceapi.ResourceClaim{
Spec: resourceapi.ResourceClaimSpec{
Devices: resourceapi.DeviceClaim{
Requests: []resourceapi.DeviceRequest{
adminRequest("validation-gpu", resourceapi.DeviceAllocationModeExactCount, 1),
},
},
},
}

Expect(countGPUDevicesFromClaim(claim)).To(Equal(int64(0)))
})

It("should not count an All admin access request", func() {
claim := &resourceapi.ResourceClaim{
Spec: resourceapi.ResourceClaimSpec{
Devices: resourceapi.DeviceClaim{
Requests: []resourceapi.DeviceRequest{
adminRequest("admin-gpus", resourceapi.DeviceAllocationModeAll, 0),
},
},
},
}

Expect(countGPUDevicesFromClaim(claim)).To(Equal(int64(0)))
})

It("should count only the non-admin requests of a mixed claim", func() {
claim := &resourceapi.ResourceClaim{
Spec: resourceapi.ResourceClaimSpec{
Devices: resourceapi.DeviceClaim{
Requests: []resourceapi.DeviceRequest{
adminRequest("admin-gpus", resourceapi.DeviceAllocationModeAll, 0),
{
Name: "gpu",
Exactly: &resourceapi.ExactDeviceRequest{
DeviceClassName: constants.NvidiaGpuResource,
AllocationMode: resourceapi.DeviceAllocationModeExactCount,
Count: 2,
AdminAccess: ptr.To(false),
},
},
},
},
},
}

Expect(countGPUDevicesFromClaim(claim)).To(Equal(int64(2)))
})

It("should leave admin access claims out of the per device class totals", func() {
adminClaim := func(name string, mode resourceapi.DeviceAllocationMode, count int64) *resourceapi.ResourceClaim {
return &resourceapi.ResourceClaim{
ObjectMeta: metav1.ObjectMeta{Name: name},
Spec: resourceapi.ResourceClaimSpec{
Devices: resourceapi.DeviceClaim{
Requests: []resourceapi.DeviceRequest{adminRequest(name, mode, count)},
},
},
}
}
claims := []*resourceapi.ResourceClaim{
adminClaim("validator", resourceapi.DeviceAllocationModeExactCount, 1),
adminClaim("dcgm-exporter", resourceapi.DeviceAllocationModeAll, 0),
}

Expect(ExtractDRAGPUResourcesFromClaims(claims)).To(BeEmpty())
Expect(DRAGPUResourceListFromClaims(claims)).To(BeEmpty())
})
})
})

Describe("ExtractDRAGPUResources", func() {
Expand Down
Loading