custom scheduler plugin
Signed-off-by: chaunceyjiang <chaunceyjiang@gmail.com>
This commit is contained in:
parent
5ecb4ba1bb
commit
fc600ae003
|
@ -1,6 +1,8 @@
|
|||
package options
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/pflag"
|
||||
|
@ -9,6 +11,7 @@ import (
|
|||
componentbaseconfig "k8s.io/component-base/config"
|
||||
|
||||
"github.com/karmada-io/karmada/pkg/features"
|
||||
frameworkplugins "github.com/karmada-io/karmada/pkg/scheduler/framework/plugins"
|
||||
"github.com/karmada-io/karmada/pkg/sharedcli/profileflag"
|
||||
"github.com/karmada-io/karmada/pkg/util"
|
||||
)
|
||||
|
@ -52,6 +55,12 @@ type Options struct {
|
|||
// EnableEmptyWorkloadPropagation represents whether workload with 0 replicas could be propagated to member clusters.
|
||||
EnableEmptyWorkloadPropagation bool
|
||||
ProfileOpts profileflag.Options
|
||||
|
||||
// Plugins is the list of plugins to enable or disable
|
||||
// '*' means "all enabled by default plugins"
|
||||
// 'foo' means "enable 'foo'"
|
||||
// '*,-foo' means "disable 'foo'"
|
||||
Plugins []string
|
||||
}
|
||||
|
||||
// NewOptions builds an default scheduler options.
|
||||
|
@ -88,6 +97,8 @@ func (o *Options) AddFlags(fs *pflag.FlagSet) {
|
|||
fs.DurationVar(&o.SchedulerEstimatorTimeout.Duration, "scheduler-estimator-timeout", 3*time.Second, "Specifies the timeout period of calling the scheduler estimator service.")
|
||||
fs.IntVar(&o.SchedulerEstimatorPort, "scheduler-estimator-port", defaultEstimatorPort, "The secure port on which to connect the accurate scheduler estimator.")
|
||||
fs.BoolVar(&o.EnableEmptyWorkloadPropagation, "enable-empty-workload-propagation", false, "Enable workload with replicas 0 to be propagated to member clusters.")
|
||||
fs.StringSliceVar(&o.Plugins, "plugins", []string{"*"},
|
||||
fmt.Sprintf("A list of plugins to enable. '*' enables all build-in and customized plugins, 'foo' enables the plugin named 'foo', '*,-foo' disables the plugin named 'foo'.\nAll build-in plugins: %s.", strings.Join(frameworkplugins.NewInTreeRegistry().FactoryNames(), ",")))
|
||||
features.FeatureGate.AddFlag(fs)
|
||||
o.ProfileOpts.AddFlags(fs)
|
||||
}
|
||||
|
|
|
@ -122,6 +122,7 @@ func run(opts *options.Options, stopChan <-chan struct{}, registryOptions ...Opt
|
|||
scheduler.WithSchedulerEstimatorPort(opts.SchedulerEstimatorPort),
|
||||
scheduler.WithSchedulerEstimatorTimeout(opts.SchedulerEstimatorTimeout),
|
||||
scheduler.WithEnableEmptyWorkloadPropagation(opts.EnableEmptyWorkloadPropagation),
|
||||
scheduler.WithEnableSchedulerPlugin(opts.Plugins),
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("couldn't create scheduler: %w", err)
|
||||
|
|
|
@ -2,6 +2,10 @@ package runtime
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/klog/v2"
|
||||
|
||||
"github.com/karmada-io/karmada/pkg/scheduler/framework"
|
||||
)
|
||||
|
@ -43,3 +47,41 @@ func (r Registry) Merge(in Registry) error {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// FactoryNames returns all known plugin names
|
||||
func (r Registry) FactoryNames() []string {
|
||||
return sets.StringKeySet(r).List()
|
||||
}
|
||||
|
||||
// Filter out the disabled plugin
|
||||
func (r Registry) Filter(names []string) Registry {
|
||||
var retRegistry = make(Registry)
|
||||
for _, name := range names {
|
||||
// --plugins=*
|
||||
if name == "*" {
|
||||
for factoryName, factory := range r {
|
||||
klog.Infof("Enable Scheduler plugin %q", factoryName)
|
||||
retRegistry[factoryName] = factory
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
for _, name := range names {
|
||||
// --plugins=foo
|
||||
if factory, ok := r[name]; ok {
|
||||
retRegistry[name] = factory
|
||||
klog.Infof("Enable Scheduler plugin %q", name)
|
||||
continue
|
||||
}
|
||||
// --plugins=*,-foo
|
||||
// --plugins=-foo,*
|
||||
if strings.HasPrefix(name, "-") && len(retRegistry) > 0 {
|
||||
factoryName := strings.TrimLeft(name, "-")
|
||||
delete(retRegistry, factoryName)
|
||||
klog.Warningf("%q is disabled", factoryName)
|
||||
}
|
||||
}
|
||||
|
||||
return retRegistry
|
||||
}
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
package runtime
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/karmada-io/karmada/pkg/scheduler/framework"
|
||||
)
|
||||
|
||||
func TestRegistry_Filter(t *testing.T) {
|
||||
plugins := []string{"bar", "foo", "fuzz"}
|
||||
var r = make(Registry)
|
||||
for _, name := range plugins {
|
||||
_ = r.Register(name, func() (framework.Plugin, error) {
|
||||
return nil, nil
|
||||
})
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
curPlugins []string
|
||||
r Registry
|
||||
expectedPlugins []string
|
||||
}{
|
||||
{
|
||||
name: "enable foo",
|
||||
curPlugins: []string{"foo"}, // --plugins=foo
|
||||
r: r,
|
||||
expectedPlugins: []string{"foo"},
|
||||
},
|
||||
{
|
||||
name: "enable all",
|
||||
curPlugins: []string{"*"}, // --plugins=*
|
||||
r: r,
|
||||
expectedPlugins: []string{"bar", "foo", "fuzz"},
|
||||
},
|
||||
{
|
||||
name: "disable foo",
|
||||
curPlugins: []string{"*", "-foo"}, // --plugins=*,-foo
|
||||
r: r,
|
||||
expectedPlugins: []string{"bar", "fuzz"},
|
||||
},
|
||||
{
|
||||
name: "disable foo",
|
||||
curPlugins: []string{"-foo", "*"}, // --plugins=-foo,*
|
||||
r: r,
|
||||
expectedPlugins: []string{"bar", "fuzz"},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := tt.r.Filter(tt.curPlugins); !reflect.DeepEqual(got.FactoryNames(), tt.expectedPlugins) {
|
||||
t.Errorf("Filter() = %v, want %v", got.FactoryNames(), tt.expectedPlugins)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -102,6 +102,8 @@ type schedulerOptions struct {
|
|||
enableEmptyWorkloadPropagation bool
|
||||
// outOfTreeRegistry represents the registry of out-of-tree plugins
|
||||
outOfTreeRegistry runtime.Registry
|
||||
// plugins is the list of plugins to enable or disable
|
||||
plugins []string
|
||||
}
|
||||
|
||||
// Option configures a Scheduler
|
||||
|
@ -142,6 +144,13 @@ func WithEnableEmptyWorkloadPropagation(enableEmptyWorkloadPropagation bool) Opt
|
|||
}
|
||||
}
|
||||
|
||||
// WithEnableSchedulerPlugin sets the scheduler-plugin for scheduler
|
||||
func WithEnableSchedulerPlugin(plugins []string) Option {
|
||||
return func(o *schedulerOptions) {
|
||||
o.plugins = plugins
|
||||
}
|
||||
}
|
||||
|
||||
// WithOutOfTreeRegistry sets the registry for out-of-tree plugins. Those plugins
|
||||
// will be appended to the default in-tree registry.
|
||||
func WithOutOfTreeRegistry(registry runtime.Registry) Option {
|
||||
|
@ -166,11 +175,11 @@ func NewScheduler(dynamicClient dynamic.Interface, karmadaClient karmadaclientse
|
|||
opt(&options)
|
||||
}
|
||||
|
||||
// TODO(kerthcet): make plugins configurable via config file
|
||||
registry := frameworkplugins.NewInTreeRegistry()
|
||||
if err := registry.Merge(options.outOfTreeRegistry); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
registry = registry.Filter(options.plugins)
|
||||
algorithm, err := core.NewGenericScheduler(schedulerCache, registry)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
Loading…
Reference in New Issue