Merge pull request #40188 from jayunit100/NewSchedulerFromInterface
Automatic merge from submit-queue (batch tested with PRs 39538, 40188, 40357, 38214, 40195) Decoupling scheduler creation from creation of scheduler.Config struc… **What this PR does / why we need it**: Adds functionality to the scheduler to initialize from an Configurator interface, rather then via a Config struct. **Which issue this PR fixes** Reduces coupling to `scheduler.Config` data structure format so that we can proliferate more interface driven composition of scheduler components.
This commit is contained in:
@@ -78,24 +78,20 @@ func Run(s *options.SchedulerServer) error {
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to create kube client: %v", err)
|
||||
}
|
||||
config, err := createConfig(s, kubecli)
|
||||
recorder := createRecorder(kubecli, s)
|
||||
sched, err := createScheduler(s, kubecli, recorder)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create scheduler configuration: %v", err)
|
||||
return fmt.Errorf("error creating scheduler: %v", err)
|
||||
}
|
||||
sched := scheduler.New(config)
|
||||
|
||||
go startHTTP(s)
|
||||
|
||||
run := func(_ <-chan struct{}) {
|
||||
sched.Run()
|
||||
select {}
|
||||
}
|
||||
|
||||
if !s.LeaderElection.LeaderElect {
|
||||
run(nil)
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
id, err := os.Hostname()
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to get hostname: %v", err)
|
||||
@@ -109,7 +105,7 @@ func Run(s *options.SchedulerServer) error {
|
||||
Client: kubecli,
|
||||
LockConfig: resourcelock.ResourceLockConfig{
|
||||
Identity: id,
|
||||
EventRecorder: config.Recorder,
|
||||
EventRecorder: recorder,
|
||||
},
|
||||
}
|
||||
leaderelection.RunOrDie(leaderelection.LeaderElectionConfig{
|
||||
@@ -127,6 +123,13 @@ func Run(s *options.SchedulerServer) error {
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
func createRecorder(kubecli *clientset.Clientset, s *options.SchedulerServer) record.EventRecorder {
|
||||
eventBroadcaster := record.NewBroadcaster()
|
||||
eventBroadcaster.StartLogging(glog.Infof)
|
||||
eventBroadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: kubecli.Core().Events("")})
|
||||
return eventBroadcaster.NewRecorder(v1.EventSource{Component: s.SchedulerName})
|
||||
}
|
||||
|
||||
func startHTTP(s *options.SchedulerServer) {
|
||||
mux := http.NewServeMux()
|
||||
healthz.InstallHandler(mux)
|
||||
@@ -171,33 +174,42 @@ func createClient(s *options.SchedulerServer) (*clientset.Clientset, error) {
|
||||
return cli, nil
|
||||
}
|
||||
|
||||
func createConfig(s *options.SchedulerServer, kubecli *clientset.Clientset) (*scheduler.Config, error) {
|
||||
configFactory := factory.NewConfigFactory(kubecli, s.SchedulerName, s.HardPodAffinitySymmetricWeight, s.FailureDomains)
|
||||
if _, err := os.Stat(s.PolicyConfigFile); err == nil {
|
||||
var (
|
||||
policy schedulerapi.Policy
|
||||
configData []byte
|
||||
)
|
||||
configData, err := ioutil.ReadFile(s.PolicyConfigFile)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to read policy config: %v", err)
|
||||
}
|
||||
if err := runtime.DecodeInto(latestschedulerapi.Codec, configData, &policy); err != nil {
|
||||
return nil, fmt.Errorf("invalid configuration: %v", err)
|
||||
}
|
||||
return configFactory.CreateFromConfig(policy)
|
||||
}
|
||||
|
||||
// if the config file isn't provided, use the specified (or default) provider
|
||||
config, err := configFactory.CreateFromProvider(s.AlgorithmProvider)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
eventBroadcaster := record.NewBroadcaster()
|
||||
config.Recorder = eventBroadcaster.NewRecorder(v1.EventSource{Component: s.SchedulerName})
|
||||
eventBroadcaster.StartLogging(glog.Infof)
|
||||
eventBroadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: kubecli.Core().Events("")})
|
||||
|
||||
return config, nil
|
||||
// schedulerConfigurator is an interface wrapper that provides default Configuration creation based on user
|
||||
// provided config file.
|
||||
type schedulerConfigurator struct {
|
||||
scheduler.Configurator
|
||||
policyFile string
|
||||
algorithmProvider string
|
||||
}
|
||||
|
||||
func (sc schedulerConfigurator) Create() (*scheduler.Config, error) {
|
||||
if _, err := os.Stat(sc.policyFile); err != nil {
|
||||
return sc.Configurator.CreateFromProvider(sc.algorithmProvider)
|
||||
}
|
||||
|
||||
// policy file is valid, try to create a configuration from it.
|
||||
var policy schedulerapi.Policy
|
||||
configData, err := ioutil.ReadFile(sc.policyFile)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to read policy config: %v", err)
|
||||
}
|
||||
if err := runtime.DecodeInto(latestschedulerapi.Codec, configData, &policy); err != nil {
|
||||
return nil, fmt.Errorf("invalid configuration: %v", err)
|
||||
}
|
||||
return sc.CreateFromConfig(policy)
|
||||
}
|
||||
|
||||
// createScheduler encapsulates the entire creation of a runnable scheduler.
|
||||
func createScheduler(s *options.SchedulerServer, kubecli *clientset.Clientset, recorder record.EventRecorder) (*scheduler.Scheduler, error) {
|
||||
configurator := factory.NewConfigFactory(kubecli, s.SchedulerName, s.HardPodAffinitySymmetricWeight, s.FailureDomains)
|
||||
|
||||
// Rebuild the configurator with a default Create(...) method.
|
||||
configurator = &schedulerConfigurator{
|
||||
configurator,
|
||||
s.PolicyConfigFile,
|
||||
s.AlgorithmProvider}
|
||||
|
||||
return scheduler.NewFromConfigurator(configurator, func(cfg *scheduler.Config) {
|
||||
cfg.Recorder = recorder
|
||||
})
|
||||
}
|
||||
|
Reference in New Issue
Block a user