github.com/kubewharf/katalyst-core@v0.5.3/pkg/util/spd_baseline.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 "encoding/json" 21 "fmt" 22 23 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 24 25 "github.com/kubewharf/katalyst-api/pkg/apis/workload/v1alpha1" 26 "github.com/kubewharf/katalyst-api/pkg/consts" 27 ) 28 29 type SPDBaselinePodMeta struct { 30 TimeStamp metav1.Time `json:"timeStamp"` 31 PodName string `json:"podName"` 32 } 33 34 func (c SPDBaselinePodMeta) Cmp(c1 SPDBaselinePodMeta) int { 35 if c.TimeStamp.Time.Before(c1.TimeStamp.Time) { 36 return -1 37 } 38 if c.TimeStamp.Time.After(c1.TimeStamp.Time) { 39 return 1 40 } 41 42 if c.PodName < c1.PodName { 43 return -1 44 } 45 if c.PodName > c1.PodName { 46 return 1 47 } 48 return 0 49 } 50 51 func (c SPDBaselinePodMeta) String() string { 52 d, err := json.Marshal(&c) 53 if err != nil { 54 return "" 55 } 56 return string(d) 57 } 58 59 // IsBaselinePod check whether a pod is baseline pod 60 func IsBaselinePod(podMeta metav1.ObjectMeta, baselinePercent *int32, baselineSentinel *SPDBaselinePodMeta) (bool, error) { 61 // if spd baseline percent not config means baseline is disabled 62 if baselinePercent == nil { 63 return false, nil 64 } else if *baselinePercent >= consts.SPDBaselinePercentMax { 65 return true, nil 66 } else if *baselinePercent <= consts.SPDBaselinePercentMin { 67 return false, nil 68 } 69 70 if baselineSentinel == nil { 71 return false, fmt.Errorf("baseline percent is already set but baseline sentinel is nil") 72 } 73 74 pm := GetSPDBaselinePodMeta(podMeta) 75 if pm.Cmp(*baselineSentinel) <= 0 { 76 return true, nil 77 } 78 79 return false, nil 80 } 81 82 // IsExtendedBaselinePod check whether a pod is baseline pod by extended indicator 83 func IsExtendedBaselinePod(podMeta metav1.ObjectMeta, baselinePercent *int32, podMetaMap map[string]SPDBaselinePodMeta, name string) (bool, error) { 84 var baselineSentinel *SPDBaselinePodMeta 85 sentinel, ok := podMetaMap[name] 86 if ok { 87 baselineSentinel = &sentinel 88 } 89 90 isBaseline, err := IsBaselinePod(podMeta, baselinePercent, baselineSentinel) 91 if err != nil { 92 return false, err 93 } 94 95 return isBaseline, nil 96 } 97 98 // GetSPDBaselinePodMeta get the baseline coefficient of this pod 99 func GetSPDBaselinePodMeta(podMeta metav1.ObjectMeta) SPDBaselinePodMeta { 100 return SPDBaselinePodMeta{ 101 TimeStamp: podMeta.CreationTimestamp, 102 PodName: podMeta.Name, 103 } 104 } 105 106 // GetSPDBaselineSentinel get the baseline sentinel pod of this spd 107 func GetSPDBaselineSentinel(spd *v1alpha1.ServiceProfileDescriptor) (*SPDBaselinePodMeta, error) { 108 s, ok := spd.Annotations[consts.SPDAnnotationBaselineSentinelKey] 109 if !ok { 110 return nil, nil 111 } 112 113 bs := SPDBaselinePodMeta{} 114 err := json.Unmarshal([]byte(s), &bs) 115 if err != nil { 116 return nil, err 117 } 118 119 return &bs, err 120 } 121 122 // SetSPDBaselineSentinel set the baseline percentile of this spd, if percentile is nil means delete it 123 func SetSPDBaselineSentinel(spd *v1alpha1.ServiceProfileDescriptor, podMeta *SPDBaselinePodMeta) { 124 if spd == nil { 125 return 126 } 127 128 if podMeta == nil { 129 delete(spd.Annotations, consts.SPDAnnotationBaselineSentinelKey) 130 return 131 } 132 133 if spd.Annotations == nil { 134 spd.Annotations = make(map[string]string) 135 } 136 137 spd.Annotations[consts.SPDAnnotationBaselineSentinelKey] = podMeta.String() 138 return 139 } 140 141 // GetSPDExtendedBaselineSentinel get the extended baseline sentinel pod of this spd 142 func GetSPDExtendedBaselineSentinel(spd *v1alpha1.ServiceProfileDescriptor) (map[string]SPDBaselinePodMeta, error) { 143 s, ok := spd.Annotations[consts.SPDAnnotationExtendedBaselineSentinelKey] 144 if !ok { 145 return nil, nil 146 } 147 148 bs := map[string]SPDBaselinePodMeta{} 149 err := json.Unmarshal([]byte(s), &bs) 150 if err != nil { 151 return nil, err 152 } 153 154 return bs, err 155 } 156 157 // SetSPDExtendedBaselineSentinel set the extended baseline sentinel of this spd, if percentile is nil means delete it 158 func SetSPDExtendedBaselineSentinel(spd *v1alpha1.ServiceProfileDescriptor, podMetaMap map[string]SPDBaselinePodMeta) { 159 if spd == nil { 160 return 161 } 162 163 if podMetaMap == nil || len(podMetaMap) == 0 { 164 delete(spd.Annotations, consts.SPDAnnotationExtendedBaselineSentinelKey) 165 return 166 } 167 168 if spd.Annotations == nil { 169 spd.Annotations = make(map[string]string) 170 } 171 172 extendedBaselineSentinel, err := json.Marshal(podMetaMap) 173 if err != nil { 174 spd.Annotations[consts.SPDAnnotationExtendedBaselineSentinelKey] = "" 175 } else { 176 spd.Annotations[consts.SPDAnnotationExtendedBaselineSentinelKey] = string(extendedBaselineSentinel) 177 } 178 179 return 180 }