github.com/kubewharf/katalyst-core@v0.5.3/pkg/agent/qrm-plugins/cpu/util/util.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 util 18 19 import ( 20 "context" 21 "fmt" 22 "math" 23 "sort" 24 25 v1 "k8s.io/api/core/v1" 26 pluginapi "k8s.io/kubelet/pkg/apis/resourceplugin/v1alpha1" 27 28 "github.com/kubewharf/katalyst-core/pkg/agent/qrm-plugins/cpu/dynamicpolicy/calculator" 29 "github.com/kubewharf/katalyst-core/pkg/agent/qrm-plugins/cpu/dynamicpolicy/state" 30 "github.com/kubewharf/katalyst-core/pkg/config" 31 "github.com/kubewharf/katalyst-core/pkg/metaserver" 32 "github.com/kubewharf/katalyst-core/pkg/util/general" 33 utilkubeconfig "github.com/kubewharf/katalyst-core/pkg/util/kubelet/config" 34 "github.com/kubewharf/katalyst-core/pkg/util/machine" 35 ) 36 37 func GetCoresReservedForSystem(conf *config.Configuration, metaServer *metaserver.MetaServer, machineInfo *machine.KatalystMachineInfo, allCPUs machine.CPUSet) (machine.CPUSet, error) { 38 if conf == nil { 39 return machine.NewCPUSet(), fmt.Errorf("nil conf") 40 } else if metaServer == nil { 41 return machine.NewCPUSet(), fmt.Errorf("nil metaServer") 42 } else if machineInfo == nil { 43 return machine.NewCPUSet(), fmt.Errorf("nil machineInfo") 44 } 45 46 var reservedQuantityInt int 47 if conf.UseKubeletReservedConfig { 48 klConfig, err := metaServer.GetKubeletConfig(context.TODO()) 49 if err != nil { 50 return machine.NewCPUSet(), fmt.Errorf("failed to get kubelet config: %v", err) 51 } 52 53 reservedQuantity, found, err := utilkubeconfig.GetReservedQuantity(klConfig, string(v1.ResourceCPU)) 54 if err != nil { 55 return machine.NewCPUSet(), fmt.Errorf("GetKubeletReservedQuantity failed with error: %v", err) 56 } else { 57 reservedQuantityFloat := float64(reservedQuantity.MilliValue()) / 1000 58 reservedQuantityInt = int(math.Ceil(reservedQuantityFloat)) 59 60 general.Infof("get reservedQuantityInt: %d from kubelet config, found: %v", reservedQuantityInt, found) 61 } 62 } else { 63 reservedQuantityInt = conf.ReservedCPUCores 64 general.Infof("get reservedQuantityInt: %d from ReservedCPUCores configuration", reservedQuantityInt) 65 } 66 67 reservedCPUs, _, reserveErr := calculator.TakeHTByNUMABalance(machineInfo, allCPUs, reservedQuantityInt) 68 if reserveErr != nil { 69 return reservedCPUs, fmt.Errorf("takeByNUMABalance for reservedCPUsNum: %d failed with error: %v", 70 reservedQuantityInt, reserveErr) 71 } 72 73 general.Infof("take reservedCPUs: %s by reservedCPUsNum: %d", reservedCPUs.String(), reservedQuantityInt) 74 return reservedCPUs, nil 75 } 76 77 // RegenerateHints regenerates hints for container that'd already been allocated cpu, 78 // and regenerateHints will assemble hints based on already-existed AllocationInfo, 79 // without any calculation logics at all 80 func RegenerateHints(allocationInfo *state.AllocationInfo, reqInt int) map[string]*pluginapi.ListOfTopologyHints { 81 hints := map[string]*pluginapi.ListOfTopologyHints{} 82 83 if allocationInfo.OriginalAllocationResult.Size() < reqInt { 84 general.ErrorS(nil, "cpus already allocated with smaller quantity than requested", 85 "podUID", allocationInfo.PodUid, 86 "containerName", allocationInfo.ContainerName, 87 "requestedResource", reqInt, 88 "allocatedSize", allocationInfo.OriginalAllocationResult.Size()) 89 90 return nil 91 } 92 93 allocatedNumaNodes := make([]uint64, 0, len(allocationInfo.TopologyAwareAssignments)) 94 for numaNode, cset := range allocationInfo.TopologyAwareAssignments { 95 if cset.Size() > 0 { 96 allocatedNumaNodes = append(allocatedNumaNodes, uint64(numaNode)) 97 } 98 } 99 100 sort.Slice(allocatedNumaNodes, func(i, j int) bool { 101 return allocatedNumaNodes[i] < allocatedNumaNodes[j] 102 }) 103 104 general.InfoS("regenerating machineInfo hints, cpus was already allocated to pod", 105 "podNamespace", allocationInfo.PodNamespace, 106 "podName", allocationInfo.PodName, 107 "containerName", allocationInfo.ContainerName, 108 "hint", allocatedNumaNodes) 109 hints[string(v1.ResourceCPU)] = &pluginapi.ListOfTopologyHints{ 110 Hints: []*pluginapi.TopologyHint{ 111 { 112 Nodes: allocatedNumaNodes, 113 Preferred: true, 114 }, 115 }, 116 } 117 return hints 118 } 119 120 // PackAllocationResponse fills pluginapi.ResourceAllocationResponse with information from AllocationInfo and pluginapi.ResourceRequest 121 func PackAllocationResponse(allocationInfo *state.AllocationInfo, resourceName, ociPropertyName string, 122 isNodeResource, isScalarResource bool, req *pluginapi.ResourceRequest, 123 ) (*pluginapi.ResourceAllocationResponse, error) { 124 if allocationInfo == nil { 125 return nil, fmt.Errorf("packAllocationResponse got nil allocationInfo") 126 } else if req == nil { 127 return nil, fmt.Errorf("packAllocationResponse got nil request") 128 } 129 130 return &pluginapi.ResourceAllocationResponse{ 131 PodUid: req.PodUid, 132 PodNamespace: req.PodNamespace, 133 PodName: req.PodName, 134 ContainerName: req.ContainerName, 135 ContainerType: req.ContainerType, 136 ContainerIndex: req.ContainerIndex, 137 PodRole: req.PodRole, 138 PodType: req.PodType, 139 ResourceName: resourceName, 140 AllocationResult: &pluginapi.ResourceAllocation{ 141 ResourceAllocation: map[string]*pluginapi.ResourceAllocationInfo{ 142 resourceName: { 143 OciPropertyName: ociPropertyName, 144 IsNodeResource: isNodeResource, 145 IsScalarResource: isScalarResource, 146 AllocatedQuantity: float64(allocationInfo.AllocationResult.Size()), 147 AllocationResult: allocationInfo.AllocationResult.String(), 148 ResourceHints: &pluginapi.ListOfTopologyHints{ 149 Hints: []*pluginapi.TopologyHint{ 150 req.Hint, 151 }, 152 }, 153 }, 154 }, 155 }, 156 Labels: general.DeepCopyMap(req.Labels), 157 Annotations: general.DeepCopyMap(req.Annotations), 158 NativeQosClass: req.NativeQosClass, 159 }, nil 160 }