Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ type PowerAwarePluginOptions struct {
PowerCappingAdvisorSocketAbsPath string
AnnotationKeyPrefix string
DVFSIndication string

CPUHeadroomPowerDiscountEnabled bool
CPUHeadroomPowerDiscountP1 float64
CPUHeadroomPowerDiscountP2 float64
CPUHeadroomPowerDiscountP3 float64
}

func (p *PowerAwarePluginOptions) AddFlags(fss *cliflag.NamedFlagSets) {
Expand All @@ -39,6 +44,10 @@ func (p *PowerAwarePluginOptions) AddFlags(fss *cliflag.NamedFlagSets) {
fs.StringVar(&p.PowerCappingAdvisorSocketAbsPath, "power-capping-advisor-sock-abs-path", p.PowerCappingAdvisorSocketAbsPath, "absolute path of unix socket file for power capping advisor served in sys-advisor")
fs.StringVar(&p.AnnotationKeyPrefix, "power-aware-annotation-key-prefix", p.AnnotationKeyPrefix, "prefix of node annotation keys used by power aware plugin")
fs.StringVar(&p.DVFSIndication, "power-aware-dvfs-indication", p.DVFSIndication, "indication metric name of dvfs effect")
fs.BoolVar(&p.CPUHeadroomPowerDiscountEnabled, "cpu-headroom-power-discount-enable", p.CPUHeadroomPowerDiscountEnabled, "to enable cpu headroom discount when power level is present")
fs.Float64Var(&p.CPUHeadroomPowerDiscountP1, "cpu-headroom-power-discount-p1", p.CPUHeadroomPowerDiscountP1, "discount rate of cpu headroom when power level is p1")
fs.Float64Var(&p.CPUHeadroomPowerDiscountP2, "cpu-headroom-power-discount-p2", p.CPUHeadroomPowerDiscountP2, "discount rate of cpu headroom when power level is p2")
fs.Float64Var(&p.CPUHeadroomPowerDiscountP3, "cpu-headroom-power-discount-p3", p.CPUHeadroomPowerDiscountP3, "discount rate of cpu headroom when power level is p3")
}

func (p *PowerAwarePluginOptions) ApplyTo(o *poweraware.PowerAwarePluginConfiguration) error {
Expand All @@ -49,12 +58,21 @@ func (p *PowerAwarePluginOptions) ApplyTo(o *poweraware.PowerAwarePluginConfigur
o.AnnotationKeyPrefix = p.AnnotationKeyPrefix
o.DVFSIndication = p.DVFSIndication

o.CPUHeadroomPowerDiscountEnabled = p.CPUHeadroomPowerDiscountEnabled
o.CPUHeadroomPowerDiscountP1 = p.CPUHeadroomPowerDiscountP1
o.CPUHeadroomPowerDiscountP2 = p.CPUHeadroomPowerDiscountP2
o.CPUHeadroomPowerDiscountP3 = p.CPUHeadroomPowerDiscountP3

return nil
}

// NewPowerAwarePluginOptions creates a new Options with a default config.
func NewPowerAwarePluginOptions() *PowerAwarePluginOptions {
return &PowerAwarePluginOptions{
DVFSIndication: poweraware.DVFSIndicationPower,
DVFSIndication: poweraware.DVFSIndicationPower,
CPUHeadroomPowerDiscountEnabled: true,
CPUHeadroomPowerDiscountP1: 0.2,
CPUHeadroomPowerDiscountP2: 0.4,
CPUHeadroomPowerDiscountP3: 0.6,
}
}
7 changes: 7 additions & 0 deletions pkg/agent/sysadvisor/plugin/poweraware/power_aware.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ import (
"github.com/kubewharf/katalyst-core/pkg/agent/sysadvisor/plugin/poweraware/evictor"
evictserver "github.com/kubewharf/katalyst-core/pkg/agent/sysadvisor/plugin/poweraware/evictor/server"
"github.com/kubewharf/katalyst-core/pkg/agent/sysadvisor/plugin/poweraware/reader"
"github.com/kubewharf/katalyst-core/pkg/agent/sysadvisor/plugin/qosaware/resource/cpu/assembler/headroomassembler/decorator"
"github.com/kubewharf/katalyst-core/pkg/agent/sysadvisor/types"
"github.com/kubewharf/katalyst-core/pkg/config"
"github.com/kubewharf/katalyst-core/pkg/config/agent/sysadvisor/poweraware"
"github.com/kubewharf/katalyst-core/pkg/metaserver"
Expand Down Expand Up @@ -125,6 +127,11 @@ func NewPowerAwarePlugin(
}

func newPluginWithAdvisor(pluginName string, conf *config.Configuration, advisor advisor.PowerAwareAdvisor) (plugin.SysAdvisorPlugin, error) {
if conf.CPUHeadroomPowerDiscountEnabled {
general.Infof("enable cpu headroom assembler discount decorator")
decorator.EnablePlugin(types.CPUHeadroomAssemblerDecoratorDiscount)
}

return &powerAwarePlugin{
name: pluginName,
dryRun: conf.PowerAwarePluginConfiguration.DryRun,
Expand Down
1 change: 1 addition & 0 deletions pkg/agent/sysadvisor/plugin/poweraware/spec/spec.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ const (
PowerAlertP0 PowerAlert = "p0"
PowerAlertP1 PowerAlert = "p1"
PowerAlertP2 PowerAlert = "p2"
PowerAlertP3 PowerAlert = "p3"

// PowerAlertOK is derivative power alert code which corresponds to NON-existent power alert annotation
PowerAlertOK PowerAlert = "ok"
Expand Down
2 changes: 1 addition & 1 deletion pkg/agent/sysadvisor/plugin/qosaware/qos_aware.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ func (qap *QoSAwarePlugin) Name() string {

// Init initializes the qos aware plugin
func (qap *QoSAwarePlugin) Init() error {
return nil
return qap.resourceAdvisor.Init()
}

func (qap *QoSAwarePlugin) periodicWork(_ context.Context) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import (
"github.com/kubewharf/katalyst-core/pkg/agent/qrm-plugins/commonstate"
"github.com/kubewharf/katalyst-core/pkg/agent/sysadvisor/metacache"
"github.com/kubewharf/katalyst-core/pkg/agent/sysadvisor/plugin/qosaware/resource/cpu/assembler/headroomassembler"
"github.com/kubewharf/katalyst-core/pkg/agent/sysadvisor/plugin/qosaware/resource/cpu/assembler/headroomassembler/decorator"
"github.com/kubewharf/katalyst-core/pkg/agent/sysadvisor/plugin/qosaware/resource/cpu/assembler/provisionassembler"
"github.com/kubewharf/katalyst-core/pkg/agent/sysadvisor/plugin/qosaware/resource/cpu/isolation"
"github.com/kubewharf/katalyst-core/pkg/agent/sysadvisor/plugin/qosaware/resource/cpu/region"
Expand Down Expand Up @@ -81,6 +82,8 @@ func init() {
headroomassembler.RegisterInitializer(types.CPUHeadroomAssemblerCommon, headroomassembler.NewHeadroomAssemblerCommon)
// TODO: CPUHeadroomAssemblerDedicated policy has removed, its name is retained for compatibility.
headroomassembler.RegisterInitializer(types.CPUHeadroomAssemblerDedicated, headroomassembler.NewHeadroomAssemblerCommon)

decorator.RegisterInitializer(types.CPUHeadroomAssemblerDecoratorDiscount, decorator.NewAssemblerDiscountDecorator)
}

// cpuResourceAdvisor is the entrance of updating cpu resource provision advice for
Expand Down Expand Up @@ -114,6 +117,11 @@ type cpuResourceAdvisor struct {
emitter metrics.MetricEmitter
}

func (cra *cpuResourceAdvisor) Init() error {
// to decorate headroom assembler if applicable decorator is enabled
return cra.decorateHeadroomAssembler()
}

// NewCPUResourceAdvisor returns a cpuResourceAdvisor instance
func NewCPUResourceAdvisor(conf *config.Configuration, extraConf interface{}, metaCache metacache.MetaCache,
metaServer *metaserver.MetaServer, emitter metrics.MetricEmitter,
Expand Down Expand Up @@ -143,6 +151,7 @@ func NewCPUResourceAdvisor(conf *config.Configuration, extraConf interface{}, me
if err := cra.initializeProvisionAssembler(); err != nil {
klog.Errorf("[qosaware-cpu] initialize provision assembler failed: %v", err)
}

if err := cra.initializeHeadroomAssembler(); err != nil {
klog.Errorf("[qosaware-cpu] initialize headroom assembler failed: %v", err)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
"github.com/kubewharf/katalyst-core/pkg/agent/qrm-plugins/commonstate"
"github.com/kubewharf/katalyst-core/pkg/agent/qrm-plugins/cpu/dynamicpolicy/state"
"github.com/kubewharf/katalyst-core/pkg/agent/sysadvisor/plugin/qosaware/resource/cpu/assembler/headroomassembler"
"github.com/kubewharf/katalyst-core/pkg/agent/sysadvisor/plugin/qosaware/resource/cpu/assembler/headroomassembler/decorator"
"github.com/kubewharf/katalyst-core/pkg/agent/sysadvisor/plugin/qosaware/resource/cpu/assembler/provisionassembler"
"github.com/kubewharf/katalyst-core/pkg/agent/sysadvisor/plugin/qosaware/resource/cpu/region"
"github.com/kubewharf/katalyst-core/pkg/agent/sysadvisor/types"
Expand Down Expand Up @@ -142,6 +143,22 @@ func (cra *cpuResourceAdvisor) initializeProvisionAssembler() error {
return nil
}

func (cra *cpuResourceAdvisor) decorateHeadroomAssembler() error {
decorateName := decorator.GetEnabledPlugin()
if len(decorateName) > 0 {
initializers := decorator.GetRegisteredInitializers()
decoratorInitializer, ok := initializers[decorateName]
if !ok {
return fmt.Errorf("unsupported headroom assembler decorator %v", decorateName)
}

general.Infof("cpu headroom assembler: decorated by %q", decorateName)
cra.headroomAssembler = decoratorInitializer(cra.headroomAssembler, cra.conf, cra.extraConf, cra.metaCache, cra.metaServer, cra.emitter)
}

return nil
}

func (cra *cpuResourceAdvisor) initializeHeadroomAssembler() error {
assemblerName := cra.conf.CPUAdvisorConfiguration.HeadroomAssembler
initializers := headroomassembler.GetRegisteredInitializers()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
Copyright 2022 The Katalyst Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package decorator

import (
"sync"

"github.com/kubewharf/katalyst-core/pkg/agent/sysadvisor/metacache"
"github.com/kubewharf/katalyst-core/pkg/agent/sysadvisor/plugin/qosaware/resource/cpu/assembler/headroomassembler"
"github.com/kubewharf/katalyst-core/pkg/config"
"github.com/kubewharf/katalyst-core/pkg/metaserver"
"github.com/kubewharf/katalyst-core/pkg/metrics"
)

var (
initializers sync.Map
enabledDecorator string
lock sync.RWMutex
)

type InitFunc func(inner headroomassembler.HeadroomAssembler,
conf *config.Configuration, extraConf interface{},
metaReader metacache.MetaReader, metaServer *metaserver.MetaServer, emitter metrics.MetricEmitter,
) headroomassembler.HeadroomAssembler

func RegisterInitializer(name string, initFunc InitFunc) {
initializers.Store(name, initFunc)
}

func GetRegisteredInitializers() map[string]InitFunc {
res := make(map[string]InitFunc)
initializers.Range(func(key, value interface{}) bool {
res[key.(string)] = value.(InitFunc)
return true
})
return res
}

func EnablePlugin(name string) {
lock.Lock()
defer lock.Unlock()
enabledDecorator = name
}

func GetEnabledPlugin() string {
lock.RLock()
defer lock.RUnlock()

return enabledDecorator
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
/*
Copyright 2022 The Katalyst Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package decorator

import (
"context"
"strconv"

"github.com/pkg/errors"
"k8s.io/apimachinery/pkg/api/resource"
"k8s.io/klog/v2"

"github.com/kubewharf/katalyst-core/pkg/agent/sysadvisor/metacache"
"github.com/kubewharf/katalyst-core/pkg/agent/sysadvisor/plugin/poweraware/spec"
"github.com/kubewharf/katalyst-core/pkg/agent/sysadvisor/plugin/qosaware/resource/cpu/assembler/headroomassembler"
"github.com/kubewharf/katalyst-core/pkg/config"
"github.com/kubewharf/katalyst-core/pkg/consts"
"github.com/kubewharf/katalyst-core/pkg/metaserver"
"github.com/kubewharf/katalyst-core/pkg/metrics"
"github.com/kubewharf/katalyst-core/pkg/util/general"
)

func NewAssemblerDiscountDecorator(inner headroomassembler.HeadroomAssembler,
conf *config.Configuration, extraConf interface{},
metaReader metacache.MetaReader, metaServer *metaserver.MetaServer, emitter metrics.MetricEmitter,
) headroomassembler.HeadroomAssembler {
discounts := map[spec.PowerAlert]float64{
spec.PowerAlertP1: conf.CPUHeadroomPowerDiscountP1,
spec.PowerAlertP2: conf.CPUHeadroomPowerDiscountP2,
spec.PowerAlertP3: conf.CPUHeadroomPowerDiscountP3,
}

return &discountDecorator{
inner: inner,
discounter: &nodeAnnotationDiscountGetter{
specFetcher: spec.NewFetcher(metaServer.NodeFetcher, conf.PowerAwarePluginConfiguration.AnnotationKeyPrefix),
conf: conf,
discounts: discounts,
},
emitter: emitter,
}
}

type DiscountGetter interface {
GetDiscount() (float64, error)
}

type nodeAnnotationDiscountGetter struct {
specFetcher spec.SpecFetcher
conf *config.Configuration
discounts map[spec.PowerAlert]float64
}

func getDiscountByLevel(level spec.PowerAlert, discounts map[spec.PowerAlert]float64) float64 {
if len(level) == 0 {
return 1.0
}

if value, ok := discounts[level]; ok {
return value
}

switch level {
case spec.PowerAlertS0, spec.PowerAlertP0:
return 0.0
default:
return 1.0
}
}

func (d *nodeAnnotationDiscountGetter) GetDiscount() (float64, error) {
powerSpec, err := d.specFetcher.GetPowerSpec(context.Background())
if err != nil {
return 1.0, errors.Wrap(err, "failed to get discount")
}

level := powerSpec.Alert
return getDiscountByLevel(level, d.discounts), nil
}

type discountDecorator struct {
inner headroomassembler.HeadroomAssembler
discounter DiscountGetter
emitter metrics.MetricEmitter
}

func applyDiscount(cpuQuantity resource.Quantity, discount float64) resource.Quantity {
milliValue := cpuQuantity.MilliValue()
newMilliValue := int64(float64(milliValue) * discount)
newQtyViaMilli := resource.NewMilliQuantity(newMilliValue, resource.DecimalSI)
return *newQtyViaMilli
}

func (d *discountDecorator) GetHeadroom() (resource.Quantity, map[int]resource.Quantity, error) {
currentDiscount, err := d.discounter.GetDiscount()
if err != nil {
general.Warningf("unable to determine current discount; apply no discount instead: %s", err)
return d.inner.GetHeadroom()
}
if currentDiscount >= 1.0 || currentDiscount < 0 {
general.Warningf("discount %f apply no discount", currentDiscount)
return d.inner.GetHeadroom()
}

headroom, numaHeadrooms, err := d.inner.GetHeadroom()
if err != nil {
return headroom, numaHeadrooms, err
}

discountHeadroom := applyDiscount(headroom, currentDiscount)
discountNumaHeadrooms := make(map[int]resource.Quantity)
for numa, numaHeadroom := range numaHeadrooms {
discountNumaHeadrooms[numa] = applyDiscount(numaHeadroom, currentDiscount)
}

if klog.V(6).Enabled() {
general.Infof("headroom discount=%f", currentDiscount)
general.Infof("headroom original %v, %v", headroom, numaHeadrooms)
general.Infof("headroom discount %v, %v", discountHeadroom, discountNumaHeadrooms)
}

// calc headroom loss and emit metrics
lossHeadroomMilli := headroom.MilliValue() - discountHeadroom.MilliValue()
_ = d.emitter.StoreInt64(consts.MetricsNodeCPUHeadroomLoss, lossHeadroomMilli, metrics.MetricTypeNameRaw)
for numa, numaHeadroom := range numaHeadrooms {
discountNumaHeadroom := discountNumaHeadrooms[numa]
lossNumaHeadroomMilli := numaHeadroom.MilliValue() - discountNumaHeadroom.MilliValue()
_ = d.emitter.StoreInt64(consts.MetricsNumaCPUHeadroomLoss, lossNumaHeadroomMilli, metrics.MetricTypeNameRaw,
metrics.MetricTag{Key: "numa", Val: strconv.Itoa(numa)},
)
}

return discountHeadroom, discountNumaHeadrooms, nil
}
Loading