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  }