github.com/kubewharf/katalyst-core@v0.5.3/pkg/agent/qrm-plugins/cpu/dynamicpolicy/cpueviction/strategy/pressure.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 strategy
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  	"sync"
    23  	"time"
    24  
    25  	"k8s.io/apimachinery/pkg/util/wait"
    26  
    27  	"github.com/kubewharf/katalyst-api/pkg/plugins/skeleton"
    28  	pluginapi "github.com/kubewharf/katalyst-api/pkg/protocol/evictionplugin/v1alpha1"
    29  	"github.com/kubewharf/katalyst-core/pkg/agent/qrm-plugins/util"
    30  	"github.com/kubewharf/katalyst-core/pkg/metrics"
    31  	"github.com/kubewharf/katalyst-core/pkg/util/general"
    32  )
    33  
    34  const (
    35  	EvictionNameDummy = "cpu-pressure-dummy"
    36  )
    37  
    38  type CPUPressureEviction interface {
    39  	Start(context.Context) (err error)
    40  	Name() string
    41  	GetEvictPods(context.Context, *pluginapi.GetEvictPodsRequest) (*pluginapi.GetEvictPodsResponse, error)
    42  	ThresholdMet(context.Context, *pluginapi.Empty) (*pluginapi.ThresholdMetResponse, error)
    43  	GetTopEvictionPods(context.Context, *pluginapi.GetTopEvictionPodsRequest) (*pluginapi.GetTopEvictionPodsResponse, error)
    44  }
    45  
    46  type DummyCPUPressureEviction struct{}
    47  
    48  var _ CPUPressureEviction = &DummyCPUPressureEviction{}
    49  
    50  func (d *DummyCPUPressureEviction) Start(_ context.Context) (err error) {
    51  	return nil
    52  }
    53  
    54  func (d *DummyCPUPressureEviction) Name() string {
    55  	return EvictionNameDummy
    56  }
    57  
    58  func (d *DummyCPUPressureEviction) GetEvictPods(_ context.Context, _ *pluginapi.GetEvictPodsRequest) (*pluginapi.GetEvictPodsResponse, error) {
    59  	return &pluginapi.GetEvictPodsResponse{}, nil
    60  }
    61  
    62  func (d *DummyCPUPressureEviction) ThresholdMet(_ context.Context, _ *pluginapi.Empty) (*pluginapi.ThresholdMetResponse, error) {
    63  	return &pluginapi.ThresholdMetResponse{}, nil
    64  }
    65  
    66  func (d *DummyCPUPressureEviction) GetTopEvictionPods(_ context.Context, _ *pluginapi.GetTopEvictionPodsRequest) (*pluginapi.GetTopEvictionPodsResponse, error) {
    67  	return &pluginapi.GetTopEvictionPodsResponse{}, nil
    68  }
    69  
    70  type CPUPressureEvictionPluginWrapper struct {
    71  	CPUPressureEviction
    72  
    73  	ctx    context.Context
    74  	cancel context.CancelFunc
    75  
    76  	sync.Mutex
    77  	started bool
    78  
    79  	emitter metrics.MetricEmitter
    80  }
    81  
    82  func NewCPUPressureEvictionPlugin(strategy CPUPressureEviction, emitter metrics.MetricEmitter) skeleton.EvictionPlugin {
    83  	return &CPUPressureEvictionPluginWrapper{CPUPressureEviction: strategy, emitter: emitter}
    84  }
    85  
    86  func (p *CPUPressureEvictionPluginWrapper) Start() (err error) {
    87  	p.Lock()
    88  	defer func() {
    89  		if err == nil {
    90  			p.started = true
    91  		}
    92  		p.Unlock()
    93  	}()
    94  
    95  	if p.started {
    96  		return
    97  	}
    98  
    99  	general.Infof("%s", p.Name())
   100  	p.ctx, p.cancel = context.WithCancel(context.Background())
   101  	if startErr := p.CPUPressureEviction.Start(p.ctx); startErr != nil {
   102  		return fmt.Errorf("start %v failed: %v", p.Name(), startErr)
   103  	}
   104  
   105  	go wait.Until(func() {
   106  		_ = p.emitter.StoreInt64(util.MetricNameHeartBeat, 1, metrics.MetricTypeNameRaw)
   107  	}, time.Second*30, p.ctx.Done())
   108  	return
   109  }
   110  
   111  func (p *CPUPressureEvictionPluginWrapper) Stop() error {
   112  	p.Lock()
   113  	defer func() {
   114  		p.started = false
   115  		p.Unlock()
   116  	}()
   117  
   118  	// plugin.Stop may be called before plugin.Start or multiple times,
   119  	// we should ensure cancel function exist
   120  	if !p.started {
   121  		return nil
   122  	}
   123  
   124  	general.Infof("%s", p.Name())
   125  	p.cancel()
   126  	return nil
   127  }
   128  
   129  // GetToken TODO implementation
   130  func (p *CPUPressureEvictionPluginWrapper) GetToken(_ context.Context, _ *pluginapi.Empty) (*pluginapi.GetTokenResponse, error) {
   131  	return &pluginapi.GetTokenResponse{
   132  		Token: "",
   133  	}, nil
   134  }