diff --git a/.changes/unreleased/Added-20260805-142800.yaml b/.changes/unreleased/Added-20260805-142800.yaml new file mode 100644 index 0000000..38384fb --- /dev/null +++ b/.changes/unreleased/Added-20260805-142800.yaml @@ -0,0 +1,2 @@ +kind: Added +body: Add PriorityClassName, GoMemLimit(Ratio) and ExtendedResourceClaimAllocation types diff --git a/kai/v1/global.go b/kai/v1/global.go index 0a6e15f..b28a47a 100644 --- a/kai/v1/global.go +++ b/kai/v1/global.go @@ -56,6 +56,11 @@ type GlobalConfig struct { // +kubebuilder:validation:Optional DaemonsetsTolerations []v1.Toleration `json:"daemonsetsTolerations,omitempty"` + // PriorityClassName defines the priority class for KAI operators & services. + // An empty value leaves the pods without a priority class. + // +kubebuilder:validation:Optional + PriorityClassName *string `json:"priorityClassName,omitempty"` + // ReplicaCount specifies the number of replicas of services that have no specific replicas configuration // +kubebuilder:validation:Optional ReplicaCount *int32 `json:"replicaCount,omitempty"` @@ -130,6 +135,7 @@ func (g *GlobalConfig) SetDefaultWhereNeeded() { g.RequireDefaultPodAntiAffinityTerm = common.SetDefault(g.RequireDefaultPodAntiAffinityTerm, ptr.To(false)) g.JSONLog = common.SetDefault(g.JSONLog, ptr.To(false)) + g.PriorityClassName = common.SetDefault(g.PriorityClassName, ptr.To("")) if g.VPA == nil { g.VPA = &common.VPASpec{} diff --git a/kai/v1/schedulingshard_types.go b/kai/v1/schedulingshard_types.go index 1fcd943..45fba28 100644 --- a/kai/v1/schedulingshard_types.go +++ b/kai/v1/schedulingshard_types.go @@ -20,6 +20,7 @@ import ( "strconv" "time" + "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/utils/ptr" @@ -95,6 +96,18 @@ type SchedulingShardSpec struct { // +kubebuilder:validation:Optional Args map[string]string `json:"args,omitempty"` + // GoMemLimitRatio is the fraction of the scheduler container memory limit + // applied as GOMEMLIMIT. Defaults to 0.9. + // +kubebuilder:validation:Optional + // +kubebuilder:validation:ExclusiveMinimum=true + // +kubebuilder:validation:Minimum=0 + // +kubebuilder:validation:Maximum=1 + GoMemLimitRatio *float64 `json:"goMemLimitRatio,omitempty"` + + // GoMemLimit overrides automatic cgroup-derived GOMEMLIMIT for this shard. + // +kubebuilder:validation:Optional + GoMemLimit *resource.Quantity `json:"goMemLimit,omitempty"` + // PlacementStrategy is the placement scheduler strategy // +kubebuilder:validation:Optional PlacementStrategy *PlacementStrategy `json:"placementStrategy,omitempty"` @@ -146,6 +159,8 @@ type SchedulingShardSpec struct { } func (s *SchedulingShardSpec) SetDefaultsWhereNeeded() { + s.GoMemLimitRatio = common.SetDefault(s.GoMemLimitRatio, ptr.To(0.9)) + s.PlacementStrategy = common.SetDefault(s.PlacementStrategy, &PlacementStrategy{}) s.PlacementStrategy.SetDefaultWhereNeeded() diff --git a/kai/v1/zz_generated.deepcopy.go b/kai/v1/zz_generated.deepcopy.go index 700d209..fc67930 100644 --- a/kai/v1/zz_generated.deepcopy.go +++ b/kai/v1/zz_generated.deepcopy.go @@ -294,6 +294,11 @@ func (in *GlobalConfig) DeepCopyInto(out *GlobalConfig) { *out = new(bool) **out = **in } + if in.PriorityClassName != nil { + in, out := &in.PriorityClassName, &out.PriorityClassName + *out = new(string) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GlobalConfig. @@ -496,6 +501,16 @@ func (in *SchedulingShardSpec) DeepCopyInto(out *SchedulingShardSpec) { (*out)[key] = val } } + if in.GoMemLimitRatio != nil { + in, out := &in.GoMemLimitRatio, &out.GoMemLimitRatio + *out = new(float64) + **out = **in + } + if in.GoMemLimit != nil { + in, out := &in.GoMemLimit, &out.GoMemLimit + x := (*in).DeepCopy() + *out = &x + } if in.PlacementStrategy != nil { in, out := &in.PlacementStrategy, &out.PlacementStrategy *out = new(PlacementStrategy) diff --git a/scheduling/v1alpha2/bindrequest_types.go b/scheduling/v1alpha2/bindrequest_types.go index 6f49e2a..1b7a201 100644 --- a/scheduling/v1alpha2/bindrequest_types.go +++ b/scheduling/v1alpha2/bindrequest_types.go @@ -4,7 +4,8 @@ package v1alpha2 import ( - v1 "k8s.io/api/resource/v1" + corev1 "k8s.io/api/core/v1" + resourceapi "k8s.io/api/resource/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -29,6 +30,10 @@ type BindRequestSpec struct { // ResourceClaims is the list of resource claims that need to be bound for this pod ResourceClaimAllocations []ResourceClaimAllocation `json:"resourceClaimAllocations,omitempty"` + // ExtendedResourceClaimAllocation holds the allocation for the synthetic DRA claim + // created to satisfy extended resource requests backed by a DeviceClass. + ExtendedResourceClaimAllocation *ExtendedResourceClaimAllocation `json:"extendedResourceClaimAllocation,omitempty"` + // PredictedNUMAZones is the scheduler's predicted NUMA placement of the pod's resources on the // selected node. PredictedNUMAZones []NUMAZonePlacement `json:"predictedNUMAZones,omitempty"` @@ -51,7 +56,20 @@ type ResourceClaimAllocation struct { Name string `json:"name,omitempty"` // Allocation is the desired allocation of the resource claim - Allocation *v1.AllocationResult `json:"allocation,omitempty"` + Allocation *resourceapi.AllocationResult `json:"allocation,omitempty"` +} + +// ExtendedResourceClaimAllocation carries the scheduler's allocation decision for +// the synthetic ResourceClaim created to back DRA-extended-resource requests. +type ExtendedResourceClaimAllocation struct { + // Allocation is the allocation result from the DRA allocator. + Allocation *resourceapi.AllocationResult `json:"allocation,omitempty"` + + // DeviceRequests are the per-container device requests placed in the claim Spec. + DeviceRequests []resourceapi.DeviceRequest `json:"deviceRequests,omitempty"` + + // ContainerMappings maps each container's extended resource request to a DeviceRequest name. + ContainerMappings []corev1.ContainerExtendedResourceRequest `json:"containerMappings,omitempty"` } const ( diff --git a/scheduling/v1alpha2/zz_generated.deepcopy.go b/scheduling/v1alpha2/zz_generated.deepcopy.go index abc7093..bc08104 100644 --- a/scheduling/v1alpha2/zz_generated.deepcopy.go +++ b/scheduling/v1alpha2/zz_generated.deepcopy.go @@ -11,7 +11,7 @@ package v1alpha2 import ( corev1 "k8s.io/api/core/v1" - "k8s.io/api/resource/v1" + resourceapi "k8s.io/api/resource/v1" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -94,6 +94,11 @@ func (in *BindRequestSpec) DeepCopyInto(out *BindRequestSpec) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.ExtendedResourceClaimAllocation != nil { + in, out := &in.ExtendedResourceClaimAllocation, &out.ExtendedResourceClaimAllocation + *out = new(ExtendedResourceClaimAllocation) + (*in).DeepCopyInto(*out) + } if in.PredictedNUMAZones != nil { in, out := &in.PredictedNUMAZones, &out.PredictedNUMAZones *out = make([]NUMAZonePlacement, len(*in)) @@ -170,12 +175,44 @@ func (in *ReceivedGPU) DeepCopy() *ReceivedGPU { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ExtendedResourceClaimAllocation) DeepCopyInto(out *ExtendedResourceClaimAllocation) { + *out = *in + if in.Allocation != nil { + in, out := &in.Allocation, &out.Allocation + *out = new(resourceapi.AllocationResult) + (*in).DeepCopyInto(*out) + } + if in.DeviceRequests != nil { + in, out := &in.DeviceRequests, &out.DeviceRequests + *out = make([]resourceapi.DeviceRequest, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.ContainerMappings != nil { + in, out := &in.ContainerMappings, &out.ContainerMappings + *out = make([]corev1.ContainerExtendedResourceRequest, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExtendedResourceClaimAllocation. +func (in *ExtendedResourceClaimAllocation) DeepCopy() *ExtendedResourceClaimAllocation { + if in == nil { + return nil + } + out := new(ExtendedResourceClaimAllocation) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ResourceClaimAllocation) DeepCopyInto(out *ResourceClaimAllocation) { *out = *in if in.Allocation != nil { in, out := &in.Allocation, &out.Allocation - *out = new(v1.AllocationResult) + *out = new(resourceapi.AllocationResult) (*in).DeepCopyInto(*out) } }