github.com/kubewharf/katalyst-core@v0.5.3/pkg/agent/sysadvisor/plugin/qosaware/qos_aware.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 qosaware 18 19 import ( 20 "context" 21 "sync" 22 "time" 23 24 "k8s.io/apimachinery/pkg/util/wait" 25 26 "github.com/kubewharf/katalyst-core/pkg/agent/sysadvisor/metacache" 27 "github.com/kubewharf/katalyst-core/pkg/agent/sysadvisor/plugin" 28 "github.com/kubewharf/katalyst-core/pkg/agent/sysadvisor/plugin/qosaware/reporter" 29 "github.com/kubewharf/katalyst-core/pkg/agent/sysadvisor/plugin/qosaware/resource" 30 "github.com/kubewharf/katalyst-core/pkg/agent/sysadvisor/plugin/qosaware/server" 31 "github.com/kubewharf/katalyst-core/pkg/agent/sysadvisor/types" 32 "github.com/kubewharf/katalyst-core/pkg/config" 33 "github.com/kubewharf/katalyst-core/pkg/config/agent/dynamic/crd" 34 "github.com/kubewharf/katalyst-core/pkg/metaserver" 35 "github.com/kubewharf/katalyst-core/pkg/metrics" 36 metricspool "github.com/kubewharf/katalyst-core/pkg/metrics/metrics-pool" 37 ) 38 39 const ( 40 // MetricsNamePlugQoSAwareHearBeat is the heartbeat metrics of qos aware plugin 41 MetricsNamePlugQoSAwareHearBeat = "plugin_qosaware_heartbeat" 42 ) 43 44 // QoSAwarePlugin calculates node headroom and updates resource provision value suggestions 45 // using different algorithms configured by user. Resource headroom data will be reported by the 46 // reporter and provision result will be sync to QRM plugin by gRPC. To take different resource 47 // dimensions into consideration, implement calculators or algorithms for each resource and register 48 // them to qos aware plugin. 49 type QoSAwarePlugin struct { 50 name string 51 period time.Duration 52 53 resourceAdvisor resource.ResourceAdvisor 54 qrmServer server.QRMServer 55 reporters []reporter.Reporter 56 57 metaCache metacache.MetaCache 58 emitter metrics.MetricEmitter 59 } 60 61 // NewQoSAwarePlugin creates a qos aware plugin with the specified config 62 func NewQoSAwarePlugin(pluginName string, conf *config.Configuration, extraConf interface{}, emitterPool metricspool.MetricsEmitterPool, 63 metaServer *metaserver.MetaServer, metaCache metacache.MetaCache, 64 ) (plugin.SysAdvisorPlugin, error) { 65 emitter := emitterPool.GetDefaultMetricsEmitter().WithTags("advisor-qosaware") 66 67 resourceAdvisor, err := resource.NewResourceAdvisor(conf, extraConf, metaCache, metaServer, emitter) 68 if err != nil { 69 return nil, err 70 } 71 72 qrmServer, err := server.NewQRMServer(resourceAdvisor, conf, metaCache, metaServer, emitter) 73 if err != nil { 74 return nil, err 75 } 76 77 reporters := make([]reporter.Reporter, 0) 78 for _, reporterName := range conf.Reporters { 79 switch reporterName { 80 case types.HeadroomReporter: 81 headroomReporter, err := reporter.NewHeadroomReporter(emitter, metaServer, conf, resourceAdvisor) 82 if err != nil { 83 return nil, err 84 } 85 reporters = append(reporters, headroomReporter) 86 case types.NodeMetricReporter: 87 nodeMetricsReporter, err := reporter.NewNodeMetricsReporter(emitter, metaServer, metaCache, conf) 88 if err != nil { 89 return nil, err 90 } 91 reporters = append(reporters, nodeMetricsReporter) 92 } 93 } 94 95 // add AdminQos dynamic config watcher 96 err = metaServer.ConfigurationManager.AddConfigWatcher(crd.AdminQoSConfigurationGVR) 97 if err != nil { 98 return nil, err 99 } 100 101 // add TransparentMemoryOffloading dynamic config watcher 102 err = metaServer.ConfigurationManager.AddConfigWatcher(crd.TransparentMemoryOffloadingConfigurationGVR) 103 if err != nil { 104 return nil, err 105 } 106 107 qap := &QoSAwarePlugin{ 108 name: pluginName, 109 period: conf.SysAdvisorPluginsConfiguration.QoSAwarePluginConfiguration.SyncPeriod, 110 111 resourceAdvisor: resourceAdvisor, 112 reporters: reporters, 113 qrmServer: qrmServer, 114 115 metaCache: metaCache, 116 emitter: emitter, 117 } 118 119 return qap, nil 120 } 121 122 // Run starts the qos aware plugin, which periodically inspects cpu usage and takes measures. 123 func (qap *QoSAwarePlugin) Run(ctx context.Context) { 124 go wait.UntilWithContext(ctx, qap.periodicWork, qap.period) 125 126 go qap.qrmServer.Run(ctx) 127 go qap.resourceAdvisor.Run(ctx) 128 129 // reporters must run synchronously to be stopped gracefully 130 wg := sync.WaitGroup{} 131 for _, reporter := range qap.reporters { 132 wg.Add(1) 133 runnable := reporter 134 go func() { 135 defer wg.Done() 136 runnable.Run(ctx) 137 }() 138 } 139 wg.Wait() 140 } 141 142 // Name returns the name of qos aware plugin 143 func (qap *QoSAwarePlugin) Name() string { 144 return qap.name 145 } 146 147 // Init initializes the qos aware plugin 148 func (qap *QoSAwarePlugin) Init() error { 149 return nil 150 } 151 152 func (qap *QoSAwarePlugin) periodicWork(_ context.Context) { 153 _ = qap.emitter.StoreInt64(MetricsNamePlugQoSAwareHearBeat, int64(qap.period.Seconds()), metrics.MetricTypeNameCount) 154 }