github.com/kubewharf/katalyst-core@v0.5.3/pkg/agent/sysadvisor/plugin/qosaware/resource/resource.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 resource 18 19 import ( 20 "context" 21 "fmt" 22 23 v1 "k8s.io/api/core/v1" 24 "k8s.io/apimachinery/pkg/api/resource" 25 26 "github.com/kubewharf/katalyst-core/pkg/agent/sysadvisor/metacache" 27 "github.com/kubewharf/katalyst-core/pkg/agent/sysadvisor/plugin/qosaware/resource/cpu" 28 "github.com/kubewharf/katalyst-core/pkg/agent/sysadvisor/plugin/qosaware/resource/memory" 29 "github.com/kubewharf/katalyst-core/pkg/agent/sysadvisor/types" 30 "github.com/kubewharf/katalyst-core/pkg/config" 31 "github.com/kubewharf/katalyst-core/pkg/metaserver" 32 "github.com/kubewharf/katalyst-core/pkg/metrics" 33 ) 34 35 // ResourceAdvisor is a wrapper of different sub resource advisors. It can be registered to 36 // headroom reporter to give designated resource headroom quantity based on provision result. 37 type ResourceAdvisor interface { 38 // Run starts all sub resource advisors 39 Run(ctx context.Context) 40 41 // GetSubAdvisor returns the corresponding sub advisor according to resource name 42 GetSubAdvisor(resourceName types.QoSResourceName) (SubResourceAdvisor, error) 43 44 // GetHeadroom returns the corresponding headroom quantity according to resource name 45 GetHeadroom(resourceName v1.ResourceName) (resource.Quantity, error) 46 } 47 48 // SubResourceAdvisor updates resource provision of a certain dimension based on the latest 49 // system and workload snapshot(s), and returns provision advice or resource headroom quantity. 50 // It should push updated results to the corresponding qrm server. 51 type SubResourceAdvisor interface { 52 // Run starts resource provision update based on the latest system and workload snapshot(s) 53 Run(ctx context.Context) 54 55 // GetChannels returns two channels. The first one receives update trigger from qrm server. 56 // The other one sends the latest internal calculation result to qrm server. 57 GetChannels() (interface{}, interface{}) 58 59 // GetHeadroom returns the latest resource headroom quantity for resource reporter 60 GetHeadroom() (resource.Quantity, error) 61 } 62 63 type resourceAdvisorWrapper struct { 64 subAdvisorsToRun map[types.QoSResourceName]SubResourceAdvisor 65 } 66 67 // NewResourceAdvisor returns a resource advisor wrapper instance, initializing all required 68 // sub resource advisor according to config 69 func NewResourceAdvisor(conf *config.Configuration, extraConf interface{}, metaCache metacache.MetaCache, 70 metaServer *metaserver.MetaServer, emitter metrics.MetricEmitter, 71 ) (ResourceAdvisor, error) { 72 resourceAdvisor := resourceAdvisorWrapper{ 73 subAdvisorsToRun: make(map[types.QoSResourceName]SubResourceAdvisor), 74 } 75 76 for _, resourceNameStr := range conf.ResourceAdvisors { 77 resourceName := types.QoSResourceName(resourceNameStr) 78 subAdvisor, err := NewSubResourceAdvisor(resourceName, conf, extraConf, metaCache, metaServer, emitter) 79 if err != nil { 80 return nil, fmt.Errorf("new sub resource advisor for %v failed: %v", resourceName, err) 81 } 82 resourceAdvisor.subAdvisorsToRun[resourceName] = subAdvisor 83 } 84 85 return &resourceAdvisor, nil 86 } 87 88 // NewSubResourceAdvisor returns a corresponding advisor according to resource name 89 func NewSubResourceAdvisor(resourceName types.QoSResourceName, conf *config.Configuration, extraConf interface{}, 90 metaCache metacache.MetaCache, metaServer *metaserver.MetaServer, emitter metrics.MetricEmitter, 91 ) (SubResourceAdvisor, error) { 92 switch resourceName { 93 case types.QoSResourceCPU: 94 return cpu.NewCPUResourceAdvisor(conf, extraConf, metaCache, metaServer, emitter), nil 95 case types.QoSResourceMemory: 96 return memory.NewMemoryResourceAdvisor(conf, extraConf, metaCache, metaServer, emitter), nil 97 default: 98 return nil, fmt.Errorf("try to new sub resource advisor for unsupported resource %v", resourceName) 99 } 100 } 101 102 func (ra *resourceAdvisorWrapper) Run(ctx context.Context) { 103 for _, subAdvisor := range ra.subAdvisorsToRun { 104 go subAdvisor.Run(ctx) 105 } 106 } 107 108 func (ra *resourceAdvisorWrapper) GetSubAdvisor(resourceName types.QoSResourceName) (SubResourceAdvisor, error) { 109 if subAdvisor, ok := ra.subAdvisorsToRun[resourceName]; ok { 110 return subAdvisor, nil 111 } 112 return nil, fmt.Errorf("no sub resource advisor for %v", resourceName) 113 } 114 115 func (ra *resourceAdvisorWrapper) GetHeadroom(resourceName v1.ResourceName) (resource.Quantity, error) { 116 switch resourceName { 117 case v1.ResourceCPU: 118 return ra.getSubAdvisorHeadroom(types.QoSResourceCPU) 119 case v1.ResourceMemory: 120 return ra.getSubAdvisorHeadroom(types.QoSResourceMemory) 121 default: 122 return resource.Quantity{}, fmt.Errorf("illegal resource %v", resourceName) 123 } 124 } 125 126 func (ra *resourceAdvisorWrapper) getSubAdvisorHeadroom(resourceName types.QoSResourceName) (resource.Quantity, error) { 127 subAdvisor, ok := ra.subAdvisorsToRun[resourceName] 128 if !ok { 129 return resource.Quantity{}, fmt.Errorf("no sub resource advisor for %v", resourceName) 130 } 131 return subAdvisor.GetHeadroom() 132 }