Skip to content

Commit 740b2c9

Browse files
sunya-chk8s-publishing-bot
authored andcommitted
KEP-5075: API updates
Signed-off-by: Sunyanan Choochotkaew <sunyanan.choochotkaew1@ibm.com> Kubernetes-commit: 5ad969588d5d79ad900d0c237398e0352d958a74
1 parent dd1e234 commit 740b2c9

File tree

3 files changed

+660
-9
lines changed

3 files changed

+660
-9
lines changed

resource/v1/types.go

Lines changed: 220 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,15 @@ type Device struct {
383383
// +listType=atomic
384384
// +featureGate=DRADeviceBindingConditions,DRAResourceClaimDeviceStatus
385385
BindingFailureConditions []string `json:"bindingFailureConditions,omitempty" protobuf:"bytes,11,rep,name=bindingFailureConditions"`
386+
387+
// AllowMultipleAllocations marks whether the device is allowed to be allocated to multiple DeviceRequests.
388+
//
389+
// If AllowMultipleAllocations is set to true, the device can be allocated more than once,
390+
// and all of its capacity is consumable, regardless of whether the requestPolicy is defined or not.
391+
//
392+
// +optional
393+
// +featureGate=DRAConsumableCapacity
394+
AllowMultipleAllocations *bool `json:"allowMultipleAllocations,omitempty" protobuf:"bytes,12,opt,name=allowMultipleAllocations"`
386395
}
387396

388397
// DeviceCounterConsumption defines a set of counters that
@@ -407,13 +416,28 @@ type DeviceCounterConsumption struct {
407416

408417
// DeviceCapacity describes a quantity associated with a device.
409418
type DeviceCapacity struct {
410-
// Value defines how much of a certain device capacity is available.
419+
// Value defines how much of a certain capacity that device has.
420+
//
421+
// This field reflects the fixed total capacity and does not change.
422+
// The consumed amount is tracked separately by scheduler
423+
// and does not affect this value.
411424
//
412425
// +required
413426
Value resource.Quantity `json:"value" protobuf:"bytes,1,rep,name=value"`
414427

415-
// potential future addition: fields which define how to "consume"
416-
// capacity (= share a single device between different consumers).
428+
// RequestPolicy defines how this DeviceCapacity must be consumed
429+
// when the device is allowed to be shared by multiple allocations.
430+
//
431+
// The Device must have allowMultipleAllocations set to true in order to set a requestPolicy.
432+
//
433+
// If unset, capacity requests are unconstrained:
434+
// requests can consume any amount of capacity, as long as the total consumed
435+
// across all allocations does not exceed the device's defined capacity.
436+
// If request is also unset, default is the full capacity value.
437+
//
438+
// +optional
439+
// +featureGate=DRAConsumableCapacity
440+
RequestPolicy *CapacityRequestPolicy `json:"requestPolicy,omitempty" protobuf:"bytes,2,opt,name=requestPolicy"`
417441
}
418442

419443
// Counter describes a quantity associated with a device.
@@ -424,6 +448,86 @@ type Counter struct {
424448
Value resource.Quantity `json:"value" protobuf:"bytes,1,rep,name=value"`
425449
}
426450

451+
// CapacityRequestPolicy defines how requests consume device capacity.
452+
//
453+
// Must not set more than one ValidRequestValues.
454+
type CapacityRequestPolicy struct {
455+
// Default specifies how much of this capacity is consumed by a request
456+
// that does not contain an entry for it in DeviceRequest's Capacity.
457+
//
458+
// +optional
459+
Default *resource.Quantity `json:"default" protobuf:"bytes,1,opt,name=default"`
460+
461+
// ValidValues defines a set of acceptable quantity values in consuming requests.
462+
//
463+
// Must not contain more than 10 entries.
464+
// Must be sorted in ascending order.
465+
//
466+
// If this field is set,
467+
// Default must be defined and it must be included in ValidValues list.
468+
//
469+
// If the requested amount does not match any valid value but smaller than some valid values,
470+
// the scheduler calculates the smallest valid value that is greater than or equal to the request.
471+
// That is: min(ceil(requestedValue) ∈ validValues), where requestedValue ≤ max(validValues).
472+
//
473+
// If the requested amount exceeds all valid values, the request violates the policy,
474+
// and this device cannot be allocated.
475+
//
476+
// +optional
477+
// +listType=atomic
478+
// +oneOf=ValidRequestValues
479+
ValidValues []resource.Quantity `json:"validValues,omitempty" protobuf:"bytes,3,opt,name=validValues"`
480+
481+
// ValidRange defines an acceptable quantity value range in consuming requests.
482+
//
483+
// If this field is set,
484+
// Default must be defined and it must fall within the defined ValidRange.
485+
//
486+
// If the requested amount does not fall within the defined range, the request violates the policy,
487+
// and this device cannot be allocated.
488+
//
489+
// If the request doesn't contain this capacity entry, Default value is used.
490+
//
491+
// +optional
492+
// +oneOf=ValidRequestValues
493+
ValidRange *CapacityRequestPolicyRange `json:"validRange,omitempty" protobuf:"bytes,4,opt,name=validRange"`
494+
}
495+
496+
// CapacityRequestPolicyRange defines a valid range for consumable capacity values.
497+
//
498+
// - If the requested amount is less than Min, it is rounded up to the Min value.
499+
// - If Step is set and the requested amount is between Min and Max but not aligned with Step,
500+
// it will be rounded up to the next value equal to Min + (n * Step).
501+
// - If Step is not set, the requested amount is used as-is if it falls within the range Min to Max (if set).
502+
// - If the requested or rounded amount exceeds Max (if set), the request does not satisfy the policy,
503+
// and the device cannot be allocated.
504+
type CapacityRequestPolicyRange struct {
505+
// Min specifies the minimum capacity allowed for a consumption request.
506+
//
507+
// Min must be greater than or equal to zero,
508+
// and less than or equal to the capacity value.
509+
// requestPolicy.default must be more than or equal to the minimum.
510+
//
511+
// +required
512+
Min *resource.Quantity `json:"min,omitempty" protobuf:"bytes,1,opt,name=min"`
513+
514+
// Max defines the upper limit for capacity that can be requested.
515+
//
516+
// Max must be less than or equal to the capacity value.
517+
// Min and requestPolicy.default must be less than or equal to the maximum.
518+
//
519+
// +optional
520+
Max *resource.Quantity `json:"max,omitempty" protobuf:"bytes,2,opt,name=max"`
521+
522+
// Step defines the step size between valid capacity amounts within the range.
523+
//
524+
// Max (if set) and requestPolicy.default must be a multiple of Step.
525+
// Min + Step must be less than or equal to the capacity value.
526+
//
527+
// +optional
528+
Step *resource.Quantity `json:"step,omitempty" protobuf:"bytes,3,opt,name=step"`
529+
}
530+
427531
// Limit for the sum of the number of entries in both attributes and capacity.
428532
const ResourceSliceMaxAttributesAndCapacitiesPerDevice = 32
429533

@@ -797,6 +901,23 @@ type ExactDeviceRequest struct {
797901
// +listType=atomic
798902
// +featureGate=DRADeviceTaints
799903
Tolerations []DeviceToleration `json:"tolerations,omitempty" protobuf:"bytes,6,opt,name=tolerations"`
904+
905+
// Capacity define resource requirements against each capacity.
906+
//
907+
// If this field is unset and the device supports multiple allocations,
908+
// the default value will be applied to each capacity according to requestPolicy.
909+
// For the capacity that has no requestPolicy, default is the full capacity value.
910+
//
911+
// Applies to each device allocation.
912+
// If Count > 1,
913+
// the request fails if there aren't enough devices that meet the requirements.
914+
// If AllocationMode is set to All,
915+
// the request fails if there are devices that otherwise match the request,
916+
// and have this capacity, with a value >= the requested amount, but which cannot be allocated to this request.
917+
//
918+
// +optional
919+
// +featureGate=DRAConsumableCapacity
920+
Capacity *CapacityRequirements `json:"capacity,omitempty" protobuf:"bytes,7,opt,name=capacity"`
800921
}
801922

802923
// DeviceSubRequest describes a request for device provided in the
@@ -891,6 +1012,52 @@ type DeviceSubRequest struct {
8911012
// +listType=atomic
8921013
// +featureGate=DRADeviceTaints
8931014
Tolerations []DeviceToleration `json:"tolerations,omitempty" protobuf:"bytes,6,opt,name=tolerations"`
1015+
1016+
// Capacity define resource requirements against each capacity.
1017+
//
1018+
// If this field is unset and the device supports multiple allocations,
1019+
// the default value will be applied to each capacity according to requestPolicy.
1020+
// For the capacity that has no requestPolicy, default is the full capacity value.
1021+
//
1022+
// Applies to each device allocation.
1023+
// If Count > 1,
1024+
// the request fails if there aren't enough devices that meet the requirements.
1025+
// If AllocationMode is set to All,
1026+
// the request fails if there are devices that otherwise match the request,
1027+
// and have this capacity, with a value >= the requested amount, but which cannot be allocated to this request.
1028+
//
1029+
// +optional
1030+
// +featureGate=DRAConsumableCapacity
1031+
Capacity *CapacityRequirements `json:"capacity,omitempty" protobuf:"bytes,7,opt,name=capacity"`
1032+
}
1033+
1034+
// CapacityRequirements defines the capacity requirements for a specific device request.
1035+
type CapacityRequirements struct {
1036+
// Requests represent individual device resource requests for distinct resources,
1037+
// all of which must be provided by the device.
1038+
//
1039+
// This value is used as an additional filtering condition against the available capacity on the device.
1040+
// This is semantically equivalent to a CEL selector with
1041+
// `device.capacity[<domain>].<name>.compareTo(quantity(<request quantity>)) >= 0`.
1042+
// For example, device.capacity['test-driver.cdi.k8s.io'].counters.compareTo(quantity('2')) >= 0.
1043+
//
1044+
// When a requestPolicy is defined, the requested amount is adjusted upward
1045+
// to the nearest valid value based on the policy.
1046+
// If the requested amount cannot be adjusted to a valid value—because it exceeds what the requestPolicy allows—
1047+
// the device is considered ineligible for allocation.
1048+
//
1049+
// For any capacity that is not explicitly requested:
1050+
// - If no requestPolicy is set, the default consumed capacity is equal to the full device capacity
1051+
// (i.e., the whole device is claimed).
1052+
// - If a requestPolicy is set, the default consumed capacity is determined according to that policy.
1053+
//
1054+
// If the device allows multiple allocation,
1055+
// the aggregated amount across all requests must not exceed the capacity value.
1056+
// The consumed capacity, which may be adjusted based on the requestPolicy if defined,
1057+
// is recorded in the resource claim’s status.devices[*].consumedCapacity field.
1058+
//
1059+
// +optional
1060+
Requests map[QualifiedName]resource.Quantity `json:"requests,omitempty" protobuf:"bytes,1,rep,name=requests,castkey=QualifiedName"`
8941061
}
8951062

8961063
const (
@@ -930,6 +1097,8 @@ type CELDeviceSelector struct {
9301097
// (e.g. device.attributes["dra.example.com"] evaluates to an object with all
9311098
// of the attributes which were prefixed by "dra.example.com".
9321099
// - capacity (map[string]object): the device's capacities, grouped by prefix.
1100+
// - allowMultipleAllocations (bool): the allowMultipleAllocations property of the device
1101+
// (v1.34+ with the DRAConsumableCapacity feature enabled).
9331102
//
9341103
// Example: Consider a device with driver="dra.example.com", which exposes
9351104
// two attributes named "model" and "ext.example.com/family" and which
@@ -1043,6 +1212,22 @@ type DeviceConstraint struct {
10431212
// criteria.
10441213
//
10451214
// MatchExpression string
1215+
1216+
// DistinctAttribute requires that all devices in question have this
1217+
// attribute and that its type and value are unique across those devices.
1218+
//
1219+
// This acts as the inverse of MatchAttribute.
1220+
//
1221+
// This constraint is used to avoid allocating multiple requests to the same device
1222+
// by ensuring attribute-level differentiation.
1223+
//
1224+
// This is useful for scenarios where resource requests must be fulfilled by separate physical devices.
1225+
// For example, a container requests two network interfaces that must be allocated from two different physical NICs.
1226+
//
1227+
// +optional
1228+
// +oneOf=ConstraintType
1229+
// +featureGate=DRAConsumableCapacity
1230+
DistinctAttribute *FullyQualifiedName `json:"distinctAttribute,omitempty" protobuf:"bytes,3,opt,name=distinctAttribute"`
10461231
}
10471232

10481233
// DeviceClaimConfiguration is used for configuration parameters in DeviceClaim.
@@ -1204,6 +1389,7 @@ type ResourceClaimStatus struct {
12041389
// +listMapKey=driver
12051390
// +listMapKey=device
12061391
// +listMapKey=pool
1392+
// +listMapKey=shareID
12071393
// +featureGate=DRAResourceClaimDeviceStatus
12081394
Devices []AllocatedDeviceStatus `json:"devices,omitempty" protobuf:"bytes,4,opt,name=devices"`
12091395
}
@@ -1370,6 +1556,28 @@ type DeviceRequestAllocationResult struct {
13701556
// +listType=atomic
13711557
// +featureGate=DRADeviceBindingConditions,DRAResourceClaimDeviceStatus
13721558
BindingFailureConditions []string `json:"bindingFailureConditions,omitempty" protobuf:"bytes,8,rep,name=bindingFailureConditions"`
1559+
1560+
// ShareID uniquely identifies an individual allocation share of the device,
1561+
// used when the device supports multiple simultaneous allocations.
1562+
// It serves as an additional map key to differentiate concurrent shares
1563+
// of the same device.
1564+
//
1565+
// +optional
1566+
// +featureGate=DRAConsumableCapacity
1567+
ShareID *types.UID `json:"shareID,omitempty" protobuf:"bytes,9,opt,name=shareID"`
1568+
1569+
// ConsumedCapacity tracks the amount of capacity consumed per device as part of the claim request.
1570+
// The consumed amount may differ from the requested amount: it is rounded up to the nearest valid
1571+
// value based on the device’s requestPolicy if applicable (i.e., may not be less than the requested amount).
1572+
//
1573+
// The total consumed capacity for each device must not exceed the DeviceCapacity's Value.
1574+
//
1575+
// This field is populated only for devices that allow multiple allocations.
1576+
// All capacity entries are included, even if the consumed amount is zero.
1577+
//
1578+
// +optional
1579+
// +featureGate=DRAConsumableCapacity
1580+
ConsumedCapacity map[QualifiedName]resource.Quantity `json:"consumedCapacity,omitempty" protobuf:"bytes,10,rep,name=consumedCapacity"`
13731581
}
13741582

13751583
// DeviceAllocationConfiguration gets embedded in an AllocationResult.
@@ -1574,6 +1782,9 @@ const (
15741782

15751783
// AllocatedDeviceStatus contains the status of an allocated device, if the
15761784
// driver chooses to report it. This may include driver-specific information.
1785+
//
1786+
// The combination of Driver, Pool, Device, and ShareID must match the corresponding key
1787+
// in Status.Allocation.Devices.
15771788
type AllocatedDeviceStatus struct {
15781789
// Driver specifies the name of the DRA driver whose kubelet
15791790
// plugin should be invoked to process the allocation once the claim is
@@ -1600,6 +1811,12 @@ type AllocatedDeviceStatus struct {
16001811
// +required
16011812
Device string `json:"device" protobuf:"bytes,3,rep,name=device"`
16021813

1814+
// ShareID uniquely identifies an individual allocation share of the device.
1815+
//
1816+
// +optional
1817+
// +featureGate=DRAConsumableCapacity
1818+
ShareID *string `json:"shareID,omitempty" protobuf:"bytes,7,opt,name=shareID"`
1819+
16031820
// Conditions contains the latest observation of the device's state.
16041821
// If the device has been configured according to the class and claim
16051822
// config references, the `Ready` condition should be True.

0 commit comments

Comments
 (0)