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 }