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  }