Skip to content

Commit

Permalink
custom disable or enable scheduler plugin
Browse files Browse the repository at this point in the history
Signed-off-by: chaunceyjiang <chaunceyjiang@gmail.com>
  • Loading branch information
chaunceyjiang committed Jul 7, 2022
1 parent 5ecb4ba commit 87a42a1
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 1 deletion.
11 changes: 11 additions & 0 deletions cmd/scheduler/app/options/options.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package options

import (
"fmt"
"strings"
"time"

"github.com/spf13/pflag"
Expand All @@ -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"
)
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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 on-by-default plugins, 'foo' enables the plugin named 'foo', '*,-foo' disables the plugin named 'foo'. All build-in plugins: %s.", strings.Join(frameworkplugins.NewInTreeRegistry().FactoryNames(), ",")))
features.FeatureGate.AddFlag(fs)
o.ProfileOpts.AddFlags(fs)
}
1 change: 1 addition & 0 deletions cmd/scheduler/app/scheduler.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
39 changes: 39 additions & 0 deletions pkg/scheduler/framework/runtime/registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)
Expand Down Expand Up @@ -43,3 +47,38 @@ 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=foo
if factory, ok := r[name]; ok {
retRegistry[name] = factory
klog.V(1).Infof("Starting Scheduler plugin %q", name)
continue
}
// --plugins=*,-foo
if strings.HasPrefix(name, "-") && len(retRegistry) > 0 {
factoryName := strings.TrimLeft(name, "-")
delete(retRegistry, factoryName)
klog.Warningf("%q is disabled", factoryName)
continue
}
// --plugins=*
if name == "*" {
for name, factory := range r {
klog.V(1).Infof("Starting Scheduler plugin %q", name)
retRegistry[name] = factory
}
}
}

return retRegistry
}
59 changes: 59 additions & 0 deletions pkg/scheduler/framework/runtime/registry_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
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: "wrong disable foo",
curPlugins: []string{"-foo", "*"}, // --plugins=-foo,*
r: r,
expectedPlugins: []string{"bar", "foo", "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)
}
})
}

}
11 changes: 10 additions & 1 deletion pkg/scheduler/scheduler.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 {
Expand All @@ -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
Expand Down

0 comments on commit 87a42a1

Please sign in to comment.