diff --git a/pkg/scheduler/actions/backfill/backfill.go b/pkg/scheduler/actions/backfill/backfill.go new file mode 100644 index 000000000..95586e7f9 --- /dev/null +++ b/pkg/scheduler/actions/backfill/backfill.go @@ -0,0 +1,73 @@ +/* +Copyright 2018 The Kubernetes Authors. + +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 backfill + +import ( + "github.com/golang/glog" + + "github.com/kubernetes-sigs/kube-batch/pkg/scheduler/api" + "github.com/kubernetes-sigs/kube-batch/pkg/scheduler/framework" +) + +type backfillAction struct { + ssn *framework.Session +} + +func New() *backfillAction { + return &backfillAction{} +} + +func (alloc *backfillAction) Name() string { + return "preempt" +} + +func (alloc *backfillAction) Initialize() {} + +func (alloc *backfillAction) Execute(ssn *framework.Session) { + glog.V(3).Infof("Enter Backfill ...") + defer glog.V(3).Infof("Leaving Backfill ...") + + // TODO (k82cn): When backfill, it's also need to balance between Queues. + for _, job := range ssn.Jobs { + for _, task := range job.TaskStatusIndex[api.Pending] { + if task.Resreq.IsEmpty() { + // As task did not request resources, so it only need to meet predicates. + // TODO (k82cn): need to prioritize nodes to avoid pod hole. + for _, node := range ssn.Nodes { + // TODO (k82cn): predicates did not consider pod number for now, there'll + // be ping-pong case here. + if err := ssn.PredicateFn(task, node); err != nil { + glog.V(3).Infof("Predicates failed for task <%s/%s> on node <%s>: %v", + task.Namespace, task.Name, node.Name, err) + continue + } + + glog.V(3).Infof("Binding Task <%v/%v> to node <%v>", task.Namespace, task.Name, node.Name) + if err := ssn.Allocate(task, node.Name); err != nil { + glog.Errorf("Failed to bind Task %v on %v in Session %v", task.UID, node.Name, ssn.UID) + continue + } + break + } + } else { + // TODO (k82cn): backfill for other case. + } + } + } +} + +func (alloc *backfillAction) UnInitialize() {} diff --git a/pkg/scheduler/factory.go b/pkg/scheduler/factory.go index 6290b1127..4f039736b 100644 --- a/pkg/scheduler/factory.go +++ b/pkg/scheduler/factory.go @@ -18,6 +18,7 @@ package scheduler import ( "github.com/kubernetes-sigs/kube-batch/pkg/scheduler/actions/allocate" + "github.com/kubernetes-sigs/kube-batch/pkg/scheduler/actions/backfill" "github.com/kubernetes-sigs/kube-batch/pkg/scheduler/actions/preempt" "github.com/kubernetes-sigs/kube-batch/pkg/scheduler/actions/reclaim" @@ -43,5 +44,6 @@ func init() { // Actions framework.RegisterAction(reclaim.New()) framework.RegisterAction(allocate.New()) + framework.RegisterAction(backfill.New()) framework.RegisterAction(preempt.New()) } diff --git a/pkg/scheduler/plugins/priority/priority.go b/pkg/scheduler/plugins/priority/priority.go index 44687cd5c..bd134ee23 100644 --- a/pkg/scheduler/plugins/priority/priority.go +++ b/pkg/scheduler/plugins/priority/priority.go @@ -20,8 +20,6 @@ import ( "github.com/golang/glog" "github.com/kubernetes-sigs/kube-batch/pkg/scheduler/api" "github.com/kubernetes-sigs/kube-batch/pkg/scheduler/framework" - - "k8s.io/api/core/v1" ) type priorityPlugin struct { @@ -39,11 +37,6 @@ func (pp *priorityPlugin) OnSessionOpen(ssn *framework.Session) { lv := l.(*api.TaskInfo) rv := r.(*api.TaskInfo) - // TODO quick fix, enhance it later by other option. - if res := compareQoS(lv.Pod, rv.Pod); res != 0 { - return res - } - glog.V(3).Infof("Priority TaskOrder: <%v/%v> prority is %v, <%v/%v> priority is %v", lv.Namespace, lv.Name, lv.Priority, rv.Namespace, rv.Name, rv.Priority) @@ -88,28 +81,3 @@ func (pp *priorityPlugin) OnSessionOpen(ssn *framework.Session) { } func (pp *priorityPlugin) OnSessionClose(ssn *framework.Session) {} - -// make BestEffort > Burstable/Guarantee -func compareQoS(l, r *v1.Pod) int { - lq := l.Status.QOSClass - rq := r.Status.QOSClass - - glog.V(3).Infof("Priority TaskOrder: <%v/%v> QoS is %v, <%v/%v> QoS is %v", - l.Namespace, l.Name, lq, r.Namespace, r.Name, rq) - - if lq == rq { - return 0 - } - - // BestEffort > Burstable/Guarantee - if lq == v1.PodQOSBestEffort { - return -1 - } - - // Burstable/Guarantee < BestEffort - if rq == v1.PodQOSBestEffort { - return 1 - } - - return 0 -} diff --git a/pkg/scheduler/util.go b/pkg/scheduler/util.go index 92c14e8a2..72039387d 100644 --- a/pkg/scheduler/util.go +++ b/pkg/scheduler/util.go @@ -27,7 +27,7 @@ import ( ) var defaultSchedulerConf = map[string]string{ - "actions": "reclaim, allocate, preempt", + "actions": "reclaim, allocate, backfill, preempt", "plugins": "gang, priority, drf, predicates, proportion", "plugin.gang.jobready": "true", "plugin.gang.joborder": "true",