volcano.sh/volcano@v1.9.0/pkg/scheduler/api/pod_info.go (about) 1 /* 2 Copyright 2019 The Kubernetes 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 api 18 19 import ( 20 "encoding/json" 21 "strconv" 22 23 v1 "k8s.io/api/core/v1" 24 "k8s.io/klog/v2" 25 26 "volcano.sh/apis/pkg/apis/scheduling/v1beta1" 27 ) 28 29 // Refer k8s.io/kubernetes/pkg/scheduler/algorithm/predicates/predicates.go#GetResourceRequest. 30 // 31 // GetResourceRequest returns a *Resource that covers the largest width in each resource dimension. 32 // Because init-containers run sequentially, we collect the max in each dimension iteratively. 33 // In contrast, we sum the resource vectors for regular containers since they run simultaneously. 34 // 35 // To be consistent with kubernetes default scheduler, it is only used for predicates of actions(e.g. 36 // allocate, backfill, preempt, reclaim), please use GetPodResourceWithoutInitContainers for other cases. 37 // 38 // Example: 39 // 40 // Pod: 41 // InitContainers 42 // IC1: 43 // CPU: 2 44 // Memory: 1G 45 // IC2: 46 // CPU: 2 47 // Memory: 3G 48 // Containers 49 // C1: 50 // CPU: 2 51 // Memory: 1G 52 // C2: 53 // CPU: 1 54 // Memory: 1G 55 // 56 // Result: CPU: 3, Memory: 3G 57 58 // GetPodResourceRequest returns all the resource required for that pod 59 func GetPodResourceRequest(pod *v1.Pod) *Resource { 60 result := GetPodResourceWithoutInitContainers(pod) 61 62 // take max_resource(sum_pod, any_init_container) 63 for _, container := range pod.Spec.InitContainers { 64 result.SetMaxResource(NewResource(container.Resources.Requests)) 65 } 66 result.AddScalar(v1.ResourcePods, 1) 67 68 return result 69 } 70 71 // GetPodPreemptable return volcano.sh/preemptable value for pod 72 func GetPodPreemptable(pod *v1.Pod) bool { 73 // check annotaion first 74 if len(pod.Annotations) > 0 { 75 if value, found := pod.Annotations[v1beta1.PodPreemptable]; found { 76 b, err := strconv.ParseBool(value) 77 if err != nil { 78 klog.Warningf("invalid %s=%s", v1beta1.PodPreemptable, value) 79 return false 80 } 81 return b 82 } 83 } 84 85 // it annotation does not exit, check label 86 if len(pod.Labels) > 0 { 87 if value, found := pod.Labels[v1beta1.PodPreemptable]; found { 88 b, err := strconv.ParseBool(value) 89 if err != nil { 90 klog.Warningf("invalid %s=%s", v1beta1.PodPreemptable, value) 91 return false 92 } 93 return b 94 } 95 } 96 97 return true 98 } 99 100 // GetPodRevocableZone return volcano.sh/revocable-zone value for pod/podgroup 101 func GetPodRevocableZone(pod *v1.Pod) string { 102 if len(pod.Annotations) > 0 { 103 if value, found := pod.Annotations[v1beta1.RevocableZone]; found { 104 if value != "*" { 105 return "" 106 } 107 return value 108 } 109 110 if value, found := pod.Annotations[v1beta1.PodPreemptable]; found { 111 if b, err := strconv.ParseBool(value); err == nil && b { 112 return "*" 113 } 114 } 115 } 116 return "" 117 } 118 119 // GetPodTopologyInfo return volcano.sh/numa-topology-policy value for pod 120 func GetPodTopologyInfo(pod *v1.Pod) *TopologyInfo { 121 info := TopologyInfo{ 122 ResMap: make(map[int]v1.ResourceList), 123 } 124 125 if len(pod.Annotations) > 0 { 126 if value, found := pod.Annotations[v1beta1.NumaPolicyKey]; found { 127 info.Policy = value 128 } 129 130 if value, found := pod.Annotations[topologyDecisionAnnotation]; found { 131 decision := PodResourceDecision{} 132 err := json.Unmarshal([]byte(value), &decision) 133 if err == nil { 134 info.ResMap = decision.NUMAResources 135 } 136 } 137 } 138 139 return &info 140 } 141 142 // GetPodResourceWithoutInitContainers returns Pod's resource request, it does not contain 143 // init containers' resource request. 144 func GetPodResourceWithoutInitContainers(pod *v1.Pod) *Resource { 145 result := EmptyResource() 146 for _, container := range pod.Spec.Containers { 147 result.Add(NewResource(container.Resources.Requests)) 148 } 149 150 // if PodOverhead feature is supported, add overhead for running a pod 151 if pod.Spec.Overhead != nil { 152 result.Add(NewResource(pod.Spec.Overhead)) 153 } 154 155 return result 156 }