Skip to content

Commit c8e9577

Browse files
committed
Add EstimateComponentsPlugins support to framework and related tests
Signed-off-by: seanlaii <qazwsx0939059006@gmail.com>
1 parent ce66819 commit c8e9577

File tree

3 files changed

+309
-33
lines changed

3 files changed

+309
-33
lines changed

pkg/estimator/server/framework/interface.go

Lines changed: 35 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,18 @@ type Framework interface {
3333
Handle
3434
// RunEstimateReplicasPlugins runs the set of configured EstimateReplicasPlugins
3535
// for estimating replicas based on the given replicaRequirements.
36-
// It returns an integer and an Result.
36+
// It returns an integer and a Result.
3737
// The integer represents the minimum calculated value of estimated replicas from each EstimateReplicasPlugin.
38-
// The Result contains code, reasons and error
39-
// it is merged from all plugins returned result codes
38+
// The Result contains code, reasons and error.
39+
// It is merged from all plugins' returned result codes.
4040
RunEstimateReplicasPlugins(ctx context.Context, snapshot *schedcache.Snapshot, replicaRequirements *pb.ReplicaRequirements) (int32, *Result)
41+
// RunEstimateComponentsPlugins runs the set of configured EstimateComponentsPlugins
42+
// for estimating the maximum number of complete component sets based on the given components.
43+
// It returns an integer and a Result.
44+
// The integer represents the minimum calculated value of estimated component sets from each EstimateComponentsPlugin.
45+
// The Result contains code, reasons and error.
46+
// It is merged from all plugins' returned result codes.
47+
RunEstimateComponentsPlugins(ctx context.Context, snapshot *schedcache.Snapshot, components []pb.Component) (int32, *Result)
4148
// TODO(wengyao04): we can add filter and score plugin extension points if needed in the future
4249
}
4350

@@ -47,21 +54,34 @@ type Plugin interface {
4754
}
4855

4956
// EstimateReplicasPlugin is an interface for replica estimation plugins.
50-
// These estimators are used to estimate the replicas for a given pb.ReplicaRequirements
57+
// These estimators are used to estimate the replicas for a given pb.ReplicaRequirements.
5158
type EstimateReplicasPlugin interface {
5259
Plugin
5360
// Estimate is called for each MaxAvailableReplicas request.
54-
// It returns an integer and an error
55-
// The integer representing the number of calculated replica for the given replicaRequirements
56-
// The Result contains code, reasons and error
57-
// it is merged from all plugins returned result codes
61+
// It returns an integer and a Result.
62+
// The integer represents the number of calculated replicas for the given replicaRequirements.
63+
// The Result contains code, reasons and error.
64+
// It is merged from all plugins' returned result codes.
5865
Estimate(ctx context.Context, snapshot *schedcache.Snapshot, replicaRequirements *pb.ReplicaRequirements) (int32, *Result)
5966
}
6067

68+
// EstimateComponentsPlugin is an interface for component set estimation plugins.
69+
// These estimators are used to estimate the maximum number of complete component sets
70+
// for a given set of components with different replica requirements.
71+
type EstimateComponentsPlugin interface {
72+
Plugin
73+
// EstimateComponents is called for each MaxAvailableComponentSets request.
74+
// It returns an integer and a Result.
75+
// The integer represents the estimated number of complete component sets that can be scheduled.
76+
// The Result contains code, reasons and error.
77+
// It is merged from all plugins' returned result codes.
78+
EstimateComponents(ctx context.Context, snapshot *schedcache.Snapshot, components []pb.Component) (int32, *Result)
79+
}
80+
6181
// Handle provides data and some tools that plugins can use. It is
6282
// passed to the plugin factories at the time of plugin initialization. Plugins
6383
// must store and use this handle to call framework functions.
64-
// We follow the design pattern as kubernetes scheduler framework
84+
// We follow the design pattern of the Kubernetes scheduler framework.
6585
type Handle interface {
6686
ClientSet() clientset.Interface
6787
SharedInformerFactory() informers.SharedInformerFactory
@@ -85,9 +105,9 @@ const (
85105
// NOTE: A nil status is also considered as "Success".
86106
Success Code = iota
87107
// Unschedulable is used when a plugin finds the resource unschedulable.
88-
// The accompanying status message should explain why the it is unschedulable.
108+
// The accompanying status message should explain why it is unschedulable.
89109
Unschedulable
90-
// Nooperation is used when a plugin is disabled or the plugin list are empty
110+
// Nooperation is used when a plugin is disabled or the plugin list is empty.
91111
Noopperation
92112
// Error is used for internal plugin errors, unexpected input, etc.
93113
Error
@@ -115,8 +135,8 @@ func NewResult(code Code, reasons ...string) *Result {
115135
// PluginToResult maps plugin name to Result.
116136
type PluginToResult map[string]*Result
117137

118-
// Merge merges the statuses in the map into one. The resulting status code have the following
119-
// precedence: Error, Unschedulable, Disabled.
138+
// Merge merges the statuses in the map into one. The resulting status code has the following
139+
// precedence: Error, Unschedulable, Nooperation.
120140
func (p PluginToResult) Merge() *Result {
121141
if len(p) == 0 {
122142
return NewResult(Noopperation, "plugin results are empty")
@@ -161,8 +181,8 @@ func (s *Result) IsUnschedulable() bool {
161181
return s != nil && s.code == Unschedulable
162182
}
163183

164-
// IsNoOperation returns true if "Result" is not nil and Code is "Nooperation"
165-
// ToDo (wengyao04): we can remove it once we include node resource estimation as the default plugin in the future
184+
// IsNoOperation returns true if "Result" is not nil and Code is "Nooperation".
185+
// TODO (wengyao04): we can remove it once we include node resource estimation as the default plugin in the future.
166186
func (s *Result) IsNoOperation() bool {
167187
return s != nil && s.code == Noopperation
168188
}

pkg/estimator/server/framework/runtime/framework.go

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,15 +34,20 @@ import (
3434
)
3535

3636
const (
37-
estimator = "Estimator"
37+
// estimator is the legacy label for replica estimation metrics.
38+
// Deprecated: Use estimateReplicasExtension instead. This will be removed in a future release.
39+
estimator = "Estimator"
40+
estimateReplicasExtension = "EstimateReplicas"
41+
estimateComponentsExtension = "EstimateComponents"
3842
)
3943

4044
// frameworkImpl implements the Framework interface and is responsible for initializing and running scheduler
4145
// plugins.
4246
type frameworkImpl struct {
43-
estimateReplicasPlugins []framework.EstimateReplicasPlugin
44-
clientSet clientset.Interface
45-
informerFactory informers.SharedInformerFactory
47+
estimateReplicasPlugins []framework.EstimateReplicasPlugin
48+
estimateComponentsPlugins []framework.EstimateComponentsPlugin
49+
clientSet clientset.Interface
50+
informerFactory informers.SharedInformerFactory
4651
}
4752

4853
var _ framework.Framework = &frameworkImpl{}
@@ -85,12 +90,16 @@ func NewFramework(r Registry, opts ...Option) (framework.Framework, error) {
8590
estimateReplicasPluginsList := reflect.ValueOf(&f.estimateReplicasPlugins).Elem()
8691
estimateReplicasType := estimateReplicasPluginsList.Type().Elem()
8792

93+
estimateComponentsPluginsList := reflect.ValueOf(&f.estimateComponentsPlugins).Elem()
94+
estimateComponentsType := estimateComponentsPluginsList.Type().Elem()
95+
8896
for name, factory := range r {
8997
p, err := factory(f)
9098
if err != nil {
9199
return nil, fmt.Errorf("failed to initialize plugin %q: %w", name, err)
92100
}
93101
addPluginToList(p, estimateReplicasType, &estimateReplicasPluginsList)
102+
addPluginToList(p, estimateComponentsType, &estimateComponentsPluginsList)
94103
}
95104
return f, nil
96105
}
@@ -119,7 +128,10 @@ func (frw *frameworkImpl) SharedInformerFactory() informers.SharedInformerFactor
119128
func (frw *frameworkImpl) RunEstimateReplicasPlugins(ctx context.Context, snapshot *schedcache.Snapshot, replicaRequirements *pb.ReplicaRequirements) (int32, *framework.Result) {
120129
startTime := time.Now()
121130
defer func() {
131+
// Emit metrics with both old and new labels for backward compatibility
132+
// TODO: Remove estimator label in a future release (deprecated)
122133
metrics.FrameworkExtensionPointDuration.WithLabelValues(estimator).Observe(utilmetrics.DurationInSeconds(startTime))
134+
metrics.FrameworkExtensionPointDuration.WithLabelValues(estimateReplicasExtension).Observe(utilmetrics.DurationInSeconds(startTime))
123135
}()
124136
var replica int32 = math.MaxInt32
125137
results := make(framework.PluginToResult)
@@ -141,6 +153,42 @@ func (frw *frameworkImpl) runEstimateReplicasPlugins(
141153
) (int32, *framework.Result) {
142154
startTime := time.Now()
143155
replica, ret := pl.Estimate(ctx, snapshot, replicaRequirements)
156+
// Emit metrics with both old and new labels for backward compatibility
157+
// TODO: Remove estimator label in a future release (deprecated)
144158
metrics.PluginExecutionDuration.WithLabelValues(pl.Name(), estimator).Observe(utilmetrics.DurationInSeconds(startTime))
159+
metrics.PluginExecutionDuration.WithLabelValues(pl.Name(), estimateReplicasExtension).Observe(utilmetrics.DurationInSeconds(startTime))
145160
return replica, ret
146161
}
162+
163+
// RunEstimateComponentsPlugins runs the set of configured EstimateComponentsPlugins
164+
// for estimating the maximum number of complete component sets based on the given components.
165+
// It returns an integer and a Result.
166+
// The integer represents the minimum calculated value of estimated component sets from each EstimateComponentsPlugin.
167+
func (frw *frameworkImpl) RunEstimateComponentsPlugins(ctx context.Context, snapshot *schedcache.Snapshot, components []pb.Component) (int32, *framework.Result) {
168+
startTime := time.Now()
169+
defer func() {
170+
metrics.FrameworkExtensionPointDuration.WithLabelValues(estimateComponentsExtension).Observe(utilmetrics.DurationInSeconds(startTime))
171+
}()
172+
var sets int32 = math.MaxInt32
173+
results := make(framework.PluginToResult)
174+
for _, pl := range frw.estimateComponentsPlugins {
175+
plSets, ret := frw.runEstimateComponentsPlugins(ctx, pl, snapshot, components)
176+
if (ret.IsSuccess() || ret.IsUnschedulable()) && plSets < sets {
177+
sets = plSets
178+
}
179+
results[pl.Name()] = ret
180+
}
181+
return sets, results.Merge()
182+
}
183+
184+
func (frw *frameworkImpl) runEstimateComponentsPlugins(
185+
ctx context.Context,
186+
pl framework.EstimateComponentsPlugin,
187+
snapshot *schedcache.Snapshot,
188+
components []pb.Component,
189+
) (int32, *framework.Result) {
190+
startTime := time.Now()
191+
sets, ret := pl.EstimateComponents(ctx, snapshot, components)
192+
metrics.PluginExecutionDuration.WithLabelValues(pl.Name(), estimateComponentsExtension).Observe(utilmetrics.DurationInSeconds(startTime))
193+
return sets, ret
194+
}

0 commit comments

Comments
 (0)