diff --git a/pkg/scheduler/frameworkext/framework_extender.go b/pkg/scheduler/frameworkext/framework_extender.go index 158a665e9f..57aefb75ab 100644 --- a/pkg/scheduler/frameworkext/framework_extender.go +++ b/pkg/scheduler/frameworkext/framework_extender.go @@ -31,6 +31,7 @@ import ( koordinatorclientset "github.com/koordinator-sh/koordinator/pkg/client/clientset/versioned" koordinatorinformers "github.com/koordinator-sh/koordinator/pkg/client/informers/externalversions" "github.com/koordinator-sh/koordinator/pkg/features" + "github.com/koordinator-sh/koordinator/pkg/scheduler/frameworkext/schedulingphase" "github.com/koordinator-sh/koordinator/pkg/scheduler/frameworkext/topologymanager" reservationutil "github.com/koordinator-sh/koordinator/pkg/util/reservation" ) @@ -249,6 +250,11 @@ func (ext *frameworkExtenderImpl) RunScorePlugins(ctx context.Context, state *fr return pluginToNodeScores, status } +func (ext *frameworkExtenderImpl) RunPostFilterPlugins(ctx context.Context, state *framework.CycleState, pod *corev1.Pod, filteredNodeStatusMap framework.NodeToStatusMap) (_ *framework.PostFilterResult, status *framework.Status) { + schedulingphase.RecordPhase(state, schedulingphase.PostFilter) + return ext.Framework.RunPostFilterPlugins(ctx, state, pod, filteredNodeStatusMap) +} + // RunPreBindPlugins supports PreBindReservation for Reservation func (ext *frameworkExtenderImpl) RunPreBindPlugins(ctx context.Context, state *framework.CycleState, pod *corev1.Pod, nodeName string) *framework.Status { if !reservationutil.IsReservePod(pod) { diff --git a/pkg/scheduler/frameworkext/schedulingphase/scheduling_phase.go b/pkg/scheduler/frameworkext/schedulingphase/scheduling_phase.go new file mode 100644 index 0000000000..28e2f9fd9a --- /dev/null +++ b/pkg/scheduler/frameworkext/schedulingphase/scheduling_phase.go @@ -0,0 +1,53 @@ +/* +Copyright 2022 The Koordinator 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 schedulingphase + +import ( + "k8s.io/kubernetes/pkg/scheduler/framework" + + "github.com/koordinator-sh/koordinator/apis/extension" +) + +const ( + phaseStateKey = extension.SchedulingDomainPrefix + "/scheduling-phase" +) + +const ( + PostFilter = "PostFilter" +) + +type SchedulingPhase struct { + extensionPoint string +} + +func (s *SchedulingPhase) Clone() framework.StateData { + return s +} + +func RecordPhase(cycleState *framework.CycleState, extensionPoint string) { + cycleState.Write(phaseStateKey, &SchedulingPhase{ + extensionPoint: PostFilter, + }) +} + +func GetExtensionPointBeingExecuted(cycleState *framework.CycleState) string { + s, err := cycleState.Read(phaseStateKey) + if err != nil || s == nil { + return "" + } + return s.(*SchedulingPhase).extensionPoint +} diff --git a/pkg/scheduler/frameworkext/topologymanager/manager.go b/pkg/scheduler/frameworkext/topologymanager/manager.go index baf2ef1540..0f7ce3683e 100644 --- a/pkg/scheduler/frameworkext/topologymanager/manager.go +++ b/pkg/scheduler/frameworkext/topologymanager/manager.go @@ -24,6 +24,7 @@ import ( "k8s.io/kubernetes/pkg/scheduler/framework" apiext "github.com/koordinator-sh/koordinator/apis/extension" + "github.com/koordinator-sh/koordinator/pkg/scheduler/frameworkext/schedulingphase" ) type Interface interface { @@ -64,18 +65,25 @@ func (m *topologyManager) Admit(ctx context.Context, cycleState *framework.Cycle policy := createNUMATopologyPolicy(policyType, numaNodes) bestHint, ok := store.GetAffinity(nodeName) - if !ok { + extensionPointBeingExecuted := schedulingphase.GetExtensionPointBeingExecuted(cycleState) + klog.V(5).Infof("extensionPointBeingExecuted: %v, bestHint: %v, nodeName: %v, pod: %v", extensionPointBeingExecuted, bestHint, nodeName, pod.Name) + if !ok || extensionPointBeingExecuted == schedulingphase.PostFilter { var admit bool bestHint, admit = m.calculateAffinity(ctx, cycleState, policy, pod, nodeName, exclusivePolicy, allNUMANodeStatus) klog.V(5).Infof("Best TopologyHint for (pod: %v): %v on node: %v", klog.KObj(pod), bestHint, nodeName) if !admit { return framework.NewStatus(framework.Unschedulable, "node(s) NUMA Topology affinity error") } + status := m.allocateResources(ctx, cycleState, bestHint, pod, nodeName) + if !status.IsSuccess() { + return status + } store.SetAffinity(nodeName, bestHint) - } - status := m.allocateResources(ctx, cycleState, bestHint, pod, nodeName) - if !status.IsSuccess() { - return status + } else { + status := m.allocateResources(ctx, cycleState, bestHint, pod, nodeName) + if !status.IsSuccess() { + return status + } } return nil } diff --git a/pkg/scheduler/frameworkext/topologymanager/store.go b/pkg/scheduler/frameworkext/topologymanager/store.go index 45ebbde509..ed1400cca8 100644 --- a/pkg/scheduler/frameworkext/topologymanager/store.go +++ b/pkg/scheduler/frameworkext/topologymanager/store.go @@ -44,12 +44,7 @@ func GetStore(cycleState *framework.CycleState) *Store { } func (s *Store) Clone() framework.StateData { - ss := &Store{} - s.affinityMap.Range(func(key, value any) bool { - ss.affinityMap.Store(key, value) - return true - }) - return ss + return s } func (s *Store) SetAffinity(nodeName string, affinity NUMATopologyHint) {