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 }