Move scheduler components into their own packages

- rename scheduler.{operations -> components}
- move each component into its own directory with doc.go file, for proper
  access isolation
pull/6/head
Dr. Stefan Schimanski 2015-11-02 19:30:09 +01:00
parent 3601292cff
commit 29e58bab68
20 changed files with 189 additions and 50 deletions

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package operations
package algorithm
import (
"fmt"

View File

@ -0,0 +1,18 @@
/*
Copyright 2015 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Package algorithm implements the SchedulerAlgorithm
package algorithm

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package operations
package binder
import (
"fmt"

View File

@ -0,0 +1,19 @@
/*
Copyright 2015 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Package binder implements the Binder which launched a task and let the
// executor do the actual binding.
package binder

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package operations
package deleter
import (
"time"

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package operations
package deleter
import (
"testing"

View File

@ -0,0 +1,19 @@
/*
Copyright 2015 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Package deleter implements the deleter which listens for pod DELETE events
// from the apiserver and kills tasks for deleted pods.
package deleter

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
// Package operations implements independent aspects of the scheduler which
// do not use Framework internals, but rely solely on the Framework
// Package components implements independent aspects of the scheduler which
// do not use Framework or Scheduler internals, but rely solely on the Scheduler
// interface.
package operations
package components

View File

@ -0,0 +1,19 @@
/*
Copyright 2015 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Package errorhandler implements the ErrorHandler which handles scheduer error
// and possibly requeue pods for scheduling again.
package errorhandler

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package operations
package errorhandler
import (
log "github.com/golang/glog"

View File

@ -0,0 +1,19 @@
/*
Copyright 2015 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Package podreconciler implements pod reconcilation of pods which failed
// to launch, i.e. before binding by the executor took place.
package podreconciler

View File

@ -14,12 +14,13 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package operations
package podreconciler
import (
"time"
log "github.com/golang/glog"
"k8s.io/kubernetes/contrib/mesos/pkg/scheduler/components/deleter"
merrors "k8s.io/kubernetes/contrib/mesos/pkg/scheduler/errors"
"k8s.io/kubernetes/contrib/mesos/pkg/scheduler/podtask"
"k8s.io/kubernetes/contrib/mesos/pkg/scheduler/queuer"
@ -34,10 +35,10 @@ type PodReconciler struct {
sched types.Scheduler
client *client.Client
qr *queuer.Queuer
deleter *Deleter
deleter *deleter.Deleter
}
func NewPodReconciler(sched types.Scheduler, client *client.Client, qr *queuer.Queuer, deleter *Deleter) *PodReconciler {
func NewPodReconciler(sched types.Scheduler, client *client.Client, qr *queuer.Queuer, deleter *deleter.Deleter) *PodReconciler {
return &PodReconciler{
sched: sched,
client: client,

View File

@ -0,0 +1,19 @@
/*
Copyright 2015 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Package schedulerloop implement the scheduler loop which waits for pod
// events from the queuer and passes them to the SchedulerAlgorithm.
package schedulerloop

View File

@ -14,13 +14,15 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package operations
package schedulerloop
import (
"time"
log "github.com/golang/glog"
"k8s.io/kubernetes/contrib/mesos/pkg/runtime"
"k8s.io/kubernetes/contrib/mesos/pkg/scheduler/components/algorithm"
"k8s.io/kubernetes/contrib/mesos/pkg/scheduler/components/binder"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/client/record"
client "k8s.io/kubernetes/pkg/client/unversioned"
@ -38,8 +40,8 @@ type SchedulerLoopInterface interface {
}
type SchedulerLoop struct {
algorithm *SchedulerAlgorithm
binder *Binder
algorithm *algorithm.SchedulerAlgorithm
binder *binder.Binder
nextPod func() *api.Pod
error func(*api.Pod, error)
recorder record.EventRecorder
@ -47,9 +49,9 @@ type SchedulerLoop struct {
started chan<- struct{} // startup latch
}
func NewSchedulerLoop(client *client.Client, algorithm *SchedulerAlgorithm,
func NewSchedulerLoop(client *client.Client, algorithm *algorithm.SchedulerAlgorithm,
recorder record.EventRecorder, nextPod func() *api.Pod, error func(pod *api.Pod, schedulingErr error),
binder *Binder, started chan<- struct{}) *SchedulerLoop {
binder *binder.Binder, started chan<- struct{}) *SchedulerLoop {
return &SchedulerLoop{
algorithm: algorithm,
binder: binder,

View File

@ -0,0 +1,18 @@
/*
Copyright 2015 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Package taskreconciler implement Mesos task reconcilation.
package taskreconciler

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package operations
package taskreconciler
import (
"time"

View File

@ -36,11 +36,11 @@ import (
offermetrics "k8s.io/kubernetes/contrib/mesos/pkg/offers/metrics"
"k8s.io/kubernetes/contrib/mesos/pkg/proc"
"k8s.io/kubernetes/contrib/mesos/pkg/runtime"
"k8s.io/kubernetes/contrib/mesos/pkg/scheduler/components/tasksreconciler"
schedcfg "k8s.io/kubernetes/contrib/mesos/pkg/scheduler/config"
merrors "k8s.io/kubernetes/contrib/mesos/pkg/scheduler/errors"
"k8s.io/kubernetes/contrib/mesos/pkg/scheduler/meta"
"k8s.io/kubernetes/contrib/mesos/pkg/scheduler/metrics"
"k8s.io/kubernetes/contrib/mesos/pkg/scheduler/operations"
"k8s.io/kubernetes/contrib/mesos/pkg/scheduler/podtask"
"k8s.io/kubernetes/contrib/mesos/pkg/scheduler/slave"
"k8s.io/kubernetes/contrib/mesos/pkg/scheduler/types"
@ -82,7 +82,7 @@ type Framework struct {
slaveHostNames *slave.Registry
// via deferred init
tasksReconciler *operations.TasksReconciler
tasksReconciler *taskreconciler.TasksReconciler
reconcileCooldown time.Duration
asRegisteredMaster proc.Doer
terminate <-chan struct{} // signal chan, closes when we should kill background tasks
@ -274,7 +274,7 @@ func (k *Framework) onInitialRegistration(driver bindings.SchedulerDriver) {
r1 := k.makeTaskRegistryReconciler()
r2 := k.makePodRegistryReconciler()
k.tasksReconciler = operations.NewTasksReconciler(k.asRegisteredMaster, k.makeCompositeReconciler(r1, r2),
k.tasksReconciler = taskreconciler.NewTasksReconciler(k.asRegisteredMaster, k.makeCompositeReconciler(r1, r2),
k.reconcileCooldown, k.schedulerConfig.ExplicitReconciliationAbortTimeout.Duration, k.terminate)
go k.tasksReconciler.Run(driver)
@ -561,14 +561,14 @@ func explicitTaskFilter(t *podtask.T) bool {
// invoke the given ReconcilerAction funcs in sequence, aborting the sequence if reconciliation
// is cancelled. if any other errors occur the composite reconciler will attempt to complete the
// sequence, reporting only the last generated error.
func (k *Framework) makeCompositeReconciler(actions ...operations.ReconcilerAction) operations.ReconcilerAction {
func (k *Framework) makeCompositeReconciler(actions ...taskreconciler.ReconcilerAction) taskreconciler.ReconcilerAction {
if x := len(actions); x == 0 {
// programming error
panic("no actions specified for composite reconciler")
} else if x == 1 {
return actions[0]
}
chained := func(d bindings.SchedulerDriver, c <-chan struct{}, a, b operations.ReconcilerAction) <-chan error {
chained := func(d bindings.SchedulerDriver, c <-chan struct{}, a, b taskreconciler.ReconcilerAction) <-chan error {
ech := a(d, c)
ch := make(chan error, 1)
go func() {
@ -603,17 +603,17 @@ func (k *Framework) makeCompositeReconciler(actions ...operations.ReconcilerActi
for i := 2; i < len(actions); i++ {
i := i
next := func(d bindings.SchedulerDriver, c <-chan struct{}) <-chan error {
return chained(d, c, operations.ReconcilerAction(result), actions[i])
return chained(d, c, taskreconciler.ReconcilerAction(result), actions[i])
}
result = next
}
return operations.ReconcilerAction(result)
return taskreconciler.ReconcilerAction(result)
}
// reconciler action factory, performs explicit task reconciliation for non-terminal
// tasks listed in the scheduler's internal taskRegistry.
func (k *Framework) makeTaskRegistryReconciler() operations.ReconcilerAction {
return operations.ReconcilerAction(func(drv bindings.SchedulerDriver, cancel <-chan struct{}) <-chan error {
func (k *Framework) makeTaskRegistryReconciler() taskreconciler.ReconcilerAction {
return taskreconciler.ReconcilerAction(func(drv bindings.SchedulerDriver, cancel <-chan struct{}) <-chan error {
taskToSlave := make(map[string]string)
for _, t := range k.sched.Tasks().List(explicitTaskFilter) {
if t.Spec.SlaveID != "" {
@ -626,8 +626,8 @@ func (k *Framework) makeTaskRegistryReconciler() operations.ReconcilerAction {
// reconciler action factory, performs explicit task reconciliation for non-terminal
// tasks identified by annotations in the Kubernetes pod registry.
func (k *Framework) makePodRegistryReconciler() operations.ReconcilerAction {
return operations.ReconcilerAction(func(drv bindings.SchedulerDriver, cancel <-chan struct{}) <-chan error {
func (k *Framework) makePodRegistryReconciler() taskreconciler.ReconcilerAction {
return taskreconciler.ReconcilerAction(func(drv bindings.SchedulerDriver, cancel <-chan struct{}) <-chan error {
podList, err := k.client.Pods(api.NamespaceAll).List(labels.Everything(), fields.Everything())
if err != nil {
return proc.ErrorChanf("failed to reconcile pod registry: %v", err)

View File

@ -26,12 +26,12 @@ import (
"k8s.io/kubernetes/contrib/mesos/pkg/offers"
"k8s.io/kubernetes/contrib/mesos/pkg/proc"
schedcfg "k8s.io/kubernetes/contrib/mesos/pkg/scheduler/config"
"k8s.io/kubernetes/contrib/mesos/pkg/scheduler/mock"
"k8s.io/kubernetes/contrib/mesos/pkg/scheduler/podtask"
"k8s.io/kubernetes/contrib/mesos/pkg/scheduler/slave"
"k8s.io/kubernetes/contrib/mesos/pkg/scheduler/types"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/client/cache"
"k8s.io/kubernetes/contrib/mesos/pkg/scheduler/mock"
"k8s.io/kubernetes/contrib/mesos/pkg/scheduler/types"
"k8s.io/kubernetes/contrib/mesos/pkg/scheduler/podtask"
)
//get number of non-expired offers from offer registry
@ -110,7 +110,7 @@ func TestResourceOffer_Add(t *testing.T) {
}),
slaveHostNames: slave.NewRegistry(),
nodeRegistrator: registrator,
sched: mockScheduler(),
sched: mockScheduler(),
}
hostname := "h1"
@ -155,7 +155,7 @@ func TestResourceOffer_Add_Rescind(t *testing.T) {
ListenerDelay: schedcfg.DefaultListenerDelay,
}),
slaveHostNames: slave.NewRegistry(),
sched: mockScheduler(),
sched: mockScheduler(),
}
hostname := "h1"
@ -209,7 +209,7 @@ func TestSlave_Lost(t *testing.T) {
ListenerDelay: schedcfg.DefaultListenerDelay,
}),
slaveHostNames: slave.NewRegistry(),
sched: mockScheduler(),
sched: mockScheduler(),
}
hostname := "h1"
@ -267,7 +267,7 @@ func TestDisconnect(t *testing.T) {
ListenerDelay: schedcfg.DefaultListenerDelay,
}),
slaveHostNames: slave.NewRegistry(),
sched: mockScheduler(),
sched: mockScheduler(),
}
hostname := "h1"
@ -312,7 +312,7 @@ func TestStatus_Update(t *testing.T) {
}),
slaveHostNames: slave.NewRegistry(),
driver: &mockdriver,
sched: mockScheduler(),
sched: mockScheduler(),
}
taskStatus_task_starting := util.NewTaskStatus(

View File

@ -33,11 +33,11 @@ import (
"github.com/stretchr/testify/mock"
assertext "k8s.io/kubernetes/contrib/mesos/pkg/assert"
"k8s.io/kubernetes/contrib/mesos/pkg/executor/messages"
"k8s.io/kubernetes/contrib/mesos/pkg/scheduler/components/schedulerloop"
schedcfg "k8s.io/kubernetes/contrib/mesos/pkg/scheduler/config"
"k8s.io/kubernetes/contrib/mesos/pkg/scheduler/ha"
"k8s.io/kubernetes/contrib/mesos/pkg/scheduler/meta"
mmock "k8s.io/kubernetes/contrib/mesos/pkg/scheduler/mock"
"k8s.io/kubernetes/contrib/mesos/pkg/scheduler/operations"
"k8s.io/kubernetes/contrib/mesos/pkg/scheduler/podschedulers"
"k8s.io/kubernetes/contrib/mesos/pkg/scheduler/podtask"
mresource "k8s.io/kubernetes/contrib/mesos/pkg/scheduler/resource"
@ -599,7 +599,7 @@ func TestScheduler_LifeCycle(t *testing.T) {
lt.podsListWatch.Add(pod, true) // notify watchers
// wait for failedScheduling event because there is no offer
assert.EventWithReason(lt.eventObs, operations.FailedScheduling, "failedScheduling event not received")
assert.EventWithReason(lt.eventObs, schedulerloop.FailedScheduling, "failedScheduling event not received")
// add some matching offer
offers := []*mesos.Offer{NewTestOffer(fmt.Sprintf("offer%d", i))}
@ -612,7 +612,7 @@ func TestScheduler_LifeCycle(t *testing.T) {
lt.framework.ResourceOffers(nil, offers)
// and wait for scheduled pod
assert.EventWithReason(lt.eventObs, operations.Scheduled)
assert.EventWithReason(lt.eventObs, schedulerloop.Scheduled)
select {
case launchedTask := <-launchedTasks:
// report back that the task has been staged, and then started by mesos
@ -649,7 +649,7 @@ func TestScheduler_LifeCycle(t *testing.T) {
// Launch a pod and wait until the scheduler driver is called
schedulePodWithOffers := func(pod *api.Pod, offers []*mesos.Offer) (*api.Pod, *LaunchedTask, *mesos.Offer) {
// wait for failedScheduling event because there is no offer
assert.EventWithReason(lt.eventObs, operations.FailedScheduling, "failedScheduling event not received")
assert.EventWithReason(lt.eventObs, schedulerloop.FailedScheduling, "failedScheduling event not received")
// supply a matching offer
lt.framework.ResourceOffers(lt.driver, offers)
@ -664,7 +664,7 @@ func TestScheduler_LifeCycle(t *testing.T) {
}
// and wait to get scheduled
assert.EventWithReason(lt.eventObs, operations.Scheduled)
assert.EventWithReason(lt.eventObs, schedulerloop.Scheduled)
// wait for driver.launchTasks call
select {

View File

@ -24,8 +24,13 @@ import (
"k8s.io/kubernetes/contrib/mesos/pkg/offers"
"k8s.io/kubernetes/contrib/mesos/pkg/queue"
"k8s.io/kubernetes/contrib/mesos/pkg/runtime"
"k8s.io/kubernetes/contrib/mesos/pkg/scheduler/components/algorithm"
"k8s.io/kubernetes/contrib/mesos/pkg/scheduler/components/binder"
"k8s.io/kubernetes/contrib/mesos/pkg/scheduler/components/deleter"
"k8s.io/kubernetes/contrib/mesos/pkg/scheduler/components/errorhandler"
"k8s.io/kubernetes/contrib/mesos/pkg/scheduler/components/podreconciler"
"k8s.io/kubernetes/contrib/mesos/pkg/scheduler/components/schedulerloop"
"k8s.io/kubernetes/contrib/mesos/pkg/scheduler/config"
"k8s.io/kubernetes/contrib/mesos/pkg/scheduler/operations"
"k8s.io/kubernetes/contrib/mesos/pkg/scheduler/podschedulers"
"k8s.io/kubernetes/contrib/mesos/pkg/scheduler/podtask"
"k8s.io/kubernetes/contrib/mesos/pkg/scheduler/queuer"
@ -37,9 +42,9 @@ import (
// Scheduler implements types.Scheduler
type Scheduler struct {
podReconciler *operations.PodReconciler
podReconciler *podreconciler.PodReconciler
framework *Framework
loop *operations.SchedulerLoop
loop *schedulerloop.SchedulerLoop
// unsafe state, needs to be guarded, especially changes to podtask.T objects
sync.RWMutex
@ -61,16 +66,16 @@ func NewScheduler(c *config.Config, framework *Framework, podScheduler podschedu
q := queuer.New(podUpdates)
algorithm := operations.NewSchedulerAlgorithm(core, podUpdates, podScheduler)
algorithm := algorithm.NewSchedulerAlgorithm(core, podUpdates, podScheduler)
podDeleter := operations.NewDeleter(core, q)
podDeleter := deleter.NewDeleter(core, q)
core.podReconciler = operations.NewPodReconciler(core, client, q, podDeleter)
core.podReconciler = podreconciler.NewPodReconciler(core, client, q, podDeleter)
bo := backoff.New(c.InitialPodBackoff.Duration, c.MaxPodBackoff.Duration)
errorHandler := operations.NewErrorHandler(core, bo, q, podScheduler)
errorHandler := errorhandler.NewErrorHandler(core, bo, q, podScheduler)
binder := operations.NewBinder(core)
binder := binder.NewBinder(core)
startLatch := make(chan struct{})
eventBroadcaster := record.NewBroadcaster()
@ -85,7 +90,7 @@ func NewScheduler(c *config.Config, framework *Framework, podScheduler podschedu
podtask.InstallDebugHandlers(core.Tasks(), mux)
})
core.loop = operations.NewSchedulerLoop(client, algorithm, recorder, q.Yield, errorHandler.Error, binder, startLatch)
core.loop = schedulerloop.NewSchedulerLoop(client, algorithm, recorder, q.Yield, errorHandler.Error, binder, startLatch)
return core
}