github.com/kubewharf/katalyst-core@v0.5.3/pkg/util/native/qos_resource.go (about)

     1  /*
     2  Copyright 2022 The Katalyst Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package native
    18  
    19  import (
    20  	v1 "k8s.io/api/core/v1"
    21  
    22  	"github.com/kubewharf/katalyst-api/pkg/consts"
    23  	"github.com/kubewharf/katalyst-core/pkg/util/general"
    24  )
    25  
    26  // QoSResource is a collection of compute resource.
    27  type QoSResource struct {
    28  	ReclaimedMilliCPU int64
    29  	ReclaimedMemory   int64
    30  }
    31  
    32  // For each of these resources, a pod that doesn't request the resource explicitly
    33  // will be treated as having requested the amount indicated below, for the purpose
    34  // of computing priority only. This ensures that when scheduling zero-request pods, such
    35  // pods will not all be scheduled to the machine with the smallest in-use request,
    36  // and that when scheduling regular pods, such pods will not see zero-request pods as
    37  // consuming no resources whatsoever. We chose these values to be similar to the
    38  // resources that we give to cluster addon pods (#10653). But they are pretty arbitrary.
    39  // As described in #11713, we use request instead of limit to deal with resource requirements.
    40  const (
    41  	// DefaultReclaimedMilliCPURequest defines default milli reclaimed milli-cpu request number.
    42  	DefaultReclaimedMilliCPURequest int64 = 100 // 0.1 core
    43  	// DefaultReclaimedMemoryRequest defines default reclaimed memory request size.
    44  	DefaultReclaimedMemoryRequest int64 = 200 * 1024 * 1024 // 200 MiB
    45  )
    46  
    47  // Add adds ResourceList into QoSResource.
    48  func (r *QoSResource) Add(rl v1.ResourceList) {
    49  	if r == nil {
    50  		return
    51  	}
    52  	for rName, rQuant := range rl {
    53  		switch rName {
    54  		case consts.ReclaimedResourceMilliCPU:
    55  			r.ReclaimedMilliCPU += rQuant.Value()
    56  		case consts.ReclaimedResourceMemory:
    57  			r.ReclaimedMemory += rQuant.Value()
    58  		}
    59  	}
    60  }
    61  
    62  // SetMaxResource compares with ResourceList and takes max value for each QoSResource.
    63  func (r *QoSResource) SetMaxResource(rl v1.ResourceList) {
    64  	if r == nil {
    65  		return
    66  	}
    67  	for rName, rQuantity := range rl {
    68  		switch rName {
    69  		case consts.ReclaimedResourceMilliCPU:
    70  			r.ReclaimedMilliCPU = general.MaxInt64(r.ReclaimedMilliCPU, rQuantity.Value())
    71  		case consts.ReclaimedResourceMemory:
    72  			r.ReclaimedMemory = general.MaxInt64(r.ReclaimedMemory, rQuantity.Value())
    73  		}
    74  	}
    75  }
    76  
    77  // CalculateQoSResource calculates the QoS Resource of a Pod
    78  // resourceRequest = max(sum(podSpec.Containers), podSpec.InitContainers) + overHead
    79  func CalculateQoSResource(pod *v1.Pod) (res QoSResource, non0CPU int64, non0Mem int64) {
    80  	resPtr := &res
    81  	for _, c := range pod.Spec.Containers {
    82  		resPtr.Add(c.Resources.Requests)
    83  		non0CPUReq, non0MemReq := GetNonzeroQoSRequests(&c.Resources.Requests)
    84  		non0CPU += non0CPUReq
    85  		non0Mem += non0MemReq
    86  	}
    87  
    88  	for _, ic := range pod.Spec.InitContainers {
    89  		resPtr.SetMaxResource(ic.Resources.Requests)
    90  		non0CPUReq, non0MemReq := GetNonzeroQoSRequests(&ic.Resources.Requests)
    91  		non0CPU = general.MaxInt64(non0CPU, non0CPUReq)
    92  		non0Mem = general.MaxInt64(non0Mem, non0MemReq)
    93  	}
    94  
    95  	// If Overhead is being utilized, add to the total requests for the pod
    96  	if pod.Spec.Overhead != nil {
    97  		resPtr.Add(pod.Spec.Overhead)
    98  		if reclaimedCPUQuant, found := pod.Spec.Overhead[consts.ReclaimedResourceMilliCPU]; found {
    99  			non0CPU += reclaimedCPUQuant.Value()
   100  		}
   101  
   102  		if reclaimedMemQuant, found := pod.Spec.Overhead[consts.ReclaimedResourceMemory]; found {
   103  			non0Mem += reclaimedMemQuant.Value()
   104  		}
   105  	}
   106  
   107  	return
   108  }
   109  
   110  // GetNonzeroQoSRequests returns the default reclaimed_millicpu and reclaimed_memory resource request if none is found or
   111  // what is provided on the request.
   112  func GetNonzeroQoSRequests(requests *v1.ResourceList) (int64, int64) {
   113  	return GetRequestForQoSResource(consts.ReclaimedResourceMilliCPU, requests, true),
   114  		GetRequestForQoSResource(consts.ReclaimedResourceMemory, requests, true)
   115  }
   116  
   117  // GetRequestForQoSResource returns the requested values unless nonZero is true and there is no defined request
   118  // for CPU and memory.
   119  // If nonZero is true and the resource has no defined request for CPU or memory, it returns a default value.
   120  func GetRequestForQoSResource(resource v1.ResourceName, requests *v1.ResourceList, nonZero bool) int64 {
   121  	if requests == nil {
   122  		return 0
   123  	}
   124  	switch resource {
   125  	case consts.ReclaimedResourceMilliCPU:
   126  		// Override if un-set, but not if explicitly set to zero
   127  		reclaimedCPUQuant, found := (*requests)[consts.ReclaimedResourceMilliCPU]
   128  		if !found && nonZero {
   129  			return DefaultReclaimedMilliCPURequest
   130  		}
   131  		return reclaimedCPUQuant.Value()
   132  	case consts.ReclaimedResourceMemory:
   133  		// Override if un-set, but not if explicitly set to zero
   134  		reclaimedMemQuant, found := (*requests)[consts.ReclaimedResourceMemory]
   135  		if !found && nonZero {
   136  			return DefaultReclaimedMemoryRequest
   137  		}
   138  		return reclaimedMemQuant.Value()
   139  	default:
   140  		return 0
   141  	}
   142  }