Unverified Commit 50328e0b authored by Kubernetes Prow Robot's avatar Kubernetes Prow Robot Committed by GitHub

Merge pull request #74041 from bsalamat/optimize_snapshot

Optimize scheduler cache snapshot to improve scheduling throughput
parents 3baab4dc 337cb703
...@@ -141,7 +141,7 @@ type genericScheduler struct { ...@@ -141,7 +141,7 @@ type genericScheduler struct {
extenders []algorithm.SchedulerExtender extenders []algorithm.SchedulerExtender
lastNodeIndex uint64 lastNodeIndex uint64
alwaysCheckAllPredicates bool alwaysCheckAllPredicates bool
cachedNodeInfoMap map[string]*schedulernodeinfo.NodeInfo nodeInfoSnapshot schedulerinternalcache.NodeInfoSnapshot
volumeBinder *volumebinder.VolumeBinder volumeBinder *volumebinder.VolumeBinder
pvcLister corelisters.PersistentVolumeClaimLister pvcLister corelisters.PersistentVolumeClaimLister
pdbLister algorithm.PDBLister pdbLister algorithm.PDBLister
...@@ -153,7 +153,7 @@ type genericScheduler struct { ...@@ -153,7 +153,7 @@ type genericScheduler struct {
// functions. // functions.
func (g *genericScheduler) snapshot() error { func (g *genericScheduler) snapshot() error {
// Used for all fit and priority funcs. // Used for all fit and priority funcs.
return g.cache.UpdateNodeNameToInfoMap(g.cachedNodeInfoMap) return g.cache.UpdateNodeInfoSnapshot(&g.nodeInfoSnapshot)
} }
// Schedule tries to schedule the given pod to one of the nodes in the node list. // Schedule tries to schedule the given pod to one of the nodes in the node list.
...@@ -210,8 +210,8 @@ func (g *genericScheduler) Schedule(pod *v1.Pod, nodeLister algorithm.NodeLister ...@@ -210,8 +210,8 @@ func (g *genericScheduler) Schedule(pod *v1.Pod, nodeLister algorithm.NodeLister
}, nil }, nil
} }
metaPrioritiesInterface := g.priorityMetaProducer(pod, g.cachedNodeInfoMap) metaPrioritiesInterface := g.priorityMetaProducer(pod, g.nodeInfoSnapshot.NodeInfoMap)
priorityList, err := PrioritizeNodes(pod, g.cachedNodeInfoMap, metaPrioritiesInterface, g.prioritizers, filteredNodes, g.extenders) priorityList, err := PrioritizeNodes(pod, g.nodeInfoSnapshot.NodeInfoMap, metaPrioritiesInterface, g.prioritizers, filteredNodes, g.extenders)
if err != nil { if err != nil {
return result, err return result, err
} }
...@@ -290,7 +290,7 @@ func (g *genericScheduler) Preempt(pod *v1.Pod, nodeLister algorithm.NodeLister, ...@@ -290,7 +290,7 @@ func (g *genericScheduler) Preempt(pod *v1.Pod, nodeLister algorithm.NodeLister,
if !ok || fitError == nil { if !ok || fitError == nil {
return nil, nil, nil, nil return nil, nil, nil, nil
} }
if !podEligibleToPreemptOthers(pod, g.cachedNodeInfoMap) { if !podEligibleToPreemptOthers(pod, g.nodeInfoSnapshot.NodeInfoMap) {
klog.V(5).Infof("Pod %v/%v is not eligible for more preemption.", pod.Namespace, pod.Name) klog.V(5).Infof("Pod %v/%v is not eligible for more preemption.", pod.Namespace, pod.Name)
return nil, nil, nil, nil return nil, nil, nil, nil
} }
...@@ -311,7 +311,7 @@ func (g *genericScheduler) Preempt(pod *v1.Pod, nodeLister algorithm.NodeLister, ...@@ -311,7 +311,7 @@ func (g *genericScheduler) Preempt(pod *v1.Pod, nodeLister algorithm.NodeLister,
if err != nil { if err != nil {
return nil, nil, nil, err return nil, nil, nil, err
} }
nodeToVictims, err := selectNodesForPreemption(pod, g.cachedNodeInfoMap, potentialNodes, g.predicates, nodeToVictims, err := selectNodesForPreemption(pod, g.nodeInfoSnapshot.NodeInfoMap, potentialNodes, g.predicates,
g.predicateMetaProducer, g.schedulingQueue, pdbs) g.predicateMetaProducer, g.schedulingQueue, pdbs)
if err != nil { if err != nil {
return nil, nil, nil, err return nil, nil, nil, err
...@@ -335,7 +335,7 @@ func (g *genericScheduler) Preempt(pod *v1.Pod, nodeLister algorithm.NodeLister, ...@@ -335,7 +335,7 @@ func (g *genericScheduler) Preempt(pod *v1.Pod, nodeLister algorithm.NodeLister,
// nomination updates these pods and moves them to the active queue. It // nomination updates these pods and moves them to the active queue. It
// lets scheduler find another place for them. // lets scheduler find another place for them.
nominatedPods := g.getLowerPriorityNominatedPods(pod, candidateNode.Name) nominatedPods := g.getLowerPriorityNominatedPods(pod, candidateNode.Name)
if nodeInfo, ok := g.cachedNodeInfoMap[candidateNode.Name]; ok { if nodeInfo, ok := g.nodeInfoSnapshot.NodeInfoMap[candidateNode.Name]; ok {
return nodeInfo.Node(), nodeToVictims[candidateNode].Pods, nominatedPods, nil return nodeInfo.Node(), nodeToVictims[candidateNode].Pods, nominatedPods, nil
} }
...@@ -355,7 +355,7 @@ func (g *genericScheduler) processPreemptionWithExtenders( ...@@ -355,7 +355,7 @@ func (g *genericScheduler) processPreemptionWithExtenders(
newNodeToVictims, err := extender.ProcessPreemption( newNodeToVictims, err := extender.ProcessPreemption(
pod, pod,
nodeToVictims, nodeToVictims,
g.cachedNodeInfoMap, g.nodeInfoSnapshot.NodeInfoMap,
) )
if err != nil { if err != nil {
if extender.IsIgnorable() { if extender.IsIgnorable() {
...@@ -452,14 +452,14 @@ func (g *genericScheduler) findNodesThatFit(pod *v1.Pod, nodes []*v1.Node) ([]*v ...@@ -452,14 +452,14 @@ func (g *genericScheduler) findNodesThatFit(pod *v1.Pod, nodes []*v1.Node) ([]*v
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
// We can use the same metadata producer for all nodes. // We can use the same metadata producer for all nodes.
meta := g.predicateMetaProducer(pod, g.cachedNodeInfoMap) meta := g.predicateMetaProducer(pod, g.nodeInfoSnapshot.NodeInfoMap)
checkNode := func(i int) { checkNode := func(i int) {
nodeName := g.cache.NodeTree().Next() nodeName := g.cache.NodeTree().Next()
fits, failedPredicates, err := podFitsOnNode( fits, failedPredicates, err := podFitsOnNode(
pod, pod,
meta, meta,
g.cachedNodeInfoMap[nodeName], g.nodeInfoSnapshot.NodeInfoMap[nodeName],
g.predicates, g.predicates,
g.schedulingQueue, g.schedulingQueue,
g.alwaysCheckAllPredicates, g.alwaysCheckAllPredicates,
...@@ -476,7 +476,7 @@ func (g *genericScheduler) findNodesThatFit(pod *v1.Pod, nodes []*v1.Node) ([]*v ...@@ -476,7 +476,7 @@ func (g *genericScheduler) findNodesThatFit(pod *v1.Pod, nodes []*v1.Node) ([]*v
cancel() cancel()
atomic.AddInt32(&filteredLen, -1) atomic.AddInt32(&filteredLen, -1)
} else { } else {
filtered[length-1] = g.cachedNodeInfoMap[nodeName].Node() filtered[length-1] = g.nodeInfoSnapshot.NodeInfoMap[nodeName].Node()
} }
} else { } else {
predicateResultLock.Lock() predicateResultLock.Lock()
...@@ -500,7 +500,7 @@ func (g *genericScheduler) findNodesThatFit(pod *v1.Pod, nodes []*v1.Node) ([]*v ...@@ -500,7 +500,7 @@ func (g *genericScheduler) findNodesThatFit(pod *v1.Pod, nodes []*v1.Node) ([]*v
if !extender.IsInterested(pod) { if !extender.IsInterested(pod) {
continue continue
} }
filteredList, failedMap, err := extender.Filter(pod, filtered, g.cachedNodeInfoMap) filteredList, failedMap, err := extender.Filter(pod, filtered, g.nodeInfoSnapshot.NodeInfoMap)
if err != nil { if err != nil {
if extender.IsIgnorable() { if extender.IsIgnorable() {
klog.Warningf("Skipping extender %v as it returned error %v and has ignorable flag set", klog.Warningf("Skipping extender %v as it returned error %v and has ignorable flag set",
...@@ -1193,7 +1193,7 @@ func NewGenericScheduler( ...@@ -1193,7 +1193,7 @@ func NewGenericScheduler(
priorityMetaProducer: priorityMetaProducer, priorityMetaProducer: priorityMetaProducer,
pluginSet: pluginSet, pluginSet: pluginSet,
extenders: extenders, extenders: extenders,
cachedNodeInfoMap: make(map[string]*schedulernodeinfo.NodeInfo), nodeInfoSnapshot: schedulerinternalcache.NewNodeInfoSnapshot(),
volumeBinder: volumeBinder, volumeBinder: volumeBinder,
pvcLister: pvcLister, pvcLister: pvcLister,
pdbLister: pdbLister, pdbLister: pdbLister,
......
...@@ -513,7 +513,7 @@ func makeScheduler(predicates map[string]algorithmpredicates.FitPredicate, nodes ...@@ -513,7 +513,7 @@ func makeScheduler(predicates map[string]algorithmpredicates.FitPredicate, nodes
emptyPluginSet, emptyPluginSet,
nil, nil, nil, nil, false, false, nil, nil, nil, nil, false, false,
schedulerapi.DefaultPercentageOfNodesToScore) schedulerapi.DefaultPercentageOfNodesToScore)
cache.UpdateNodeNameToInfoMap(s.(*genericScheduler).cachedNodeInfoMap) cache.UpdateNodeInfoSnapshot(&s.(*genericScheduler).nodeInfoSnapshot)
return s.(*genericScheduler) return s.(*genericScheduler)
} }
......
...@@ -8,7 +8,6 @@ go_library( ...@@ -8,7 +8,6 @@ go_library(
deps = [ deps = [
"//pkg/scheduler/algorithm:go_default_library", "//pkg/scheduler/algorithm:go_default_library",
"//pkg/scheduler/internal/cache:go_default_library", "//pkg/scheduler/internal/cache:go_default_library",
"//pkg/scheduler/nodeinfo:go_default_library",
"//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library",
], ],
......
...@@ -21,7 +21,6 @@ import ( ...@@ -21,7 +21,6 @@ import (
"k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/labels"
"k8s.io/kubernetes/pkg/scheduler/algorithm" "k8s.io/kubernetes/pkg/scheduler/algorithm"
schedulerinternalcache "k8s.io/kubernetes/pkg/scheduler/internal/cache" schedulerinternalcache "k8s.io/kubernetes/pkg/scheduler/internal/cache"
schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo"
) )
// Cache is used for testing // Cache is used for testing
...@@ -75,8 +74,8 @@ func (c *Cache) UpdateNode(oldNode, newNode *v1.Node) error { return nil } ...@@ -75,8 +74,8 @@ func (c *Cache) UpdateNode(oldNode, newNode *v1.Node) error { return nil }
// RemoveNode is a fake method for testing. // RemoveNode is a fake method for testing.
func (c *Cache) RemoveNode(node *v1.Node) error { return nil } func (c *Cache) RemoveNode(node *v1.Node) error { return nil }
// UpdateNodeNameToInfoMap is a fake method for testing. // UpdateNodeInfoSnapshot is a fake method for testing.
func (c *Cache) UpdateNodeNameToInfoMap(infoMap map[string]*schedulernodeinfo.NodeInfo) error { func (c *Cache) UpdateNodeInfoSnapshot(nodeSnapshot *schedulerinternalcache.NodeInfoSnapshot) error {
return nil return nil
} }
......
...@@ -95,10 +95,10 @@ type Cache interface { ...@@ -95,10 +95,10 @@ type Cache interface {
// RemoveNode removes overall information about node. // RemoveNode removes overall information about node.
RemoveNode(node *v1.Node) error RemoveNode(node *v1.Node) error
// UpdateNodeNameToInfoMap updates the passed infoMap to the current contents of Cache. // UpdateNodeInfoSnapshot updates the passed infoSnapshot to the current contents of Cache.
// The node info contains aggregated information of pods scheduled (including assumed to be) // The node info contains aggregated information of pods scheduled (including assumed to be)
// on this node. // on this node.
UpdateNodeNameToInfoMap(infoMap map[string]*schedulernodeinfo.NodeInfo) error UpdateNodeInfoSnapshot(nodeSnapshot *NodeInfoSnapshot) error
// List lists all cached pods (including assumed ones). // List lists all cached pods (including assumed ones).
List(labels.Selector) ([]*v1.Pod, error) List(labels.Selector) ([]*v1.Pod, error)
...@@ -118,3 +118,11 @@ type Snapshot struct { ...@@ -118,3 +118,11 @@ type Snapshot struct {
AssumedPods map[string]bool AssumedPods map[string]bool
Nodes map[string]*schedulernodeinfo.NodeInfo Nodes map[string]*schedulernodeinfo.NodeInfo
} }
// NodeInfoSnapshot is a snapshot of cache NodeInfo. The scheduler takes a
// snapshot at the beginning of each scheduling cycle and uses it for its
// operations in that cycle.
type NodeInfoSnapshot struct {
NodeInfoMap map[string]*schedulernodeinfo.NodeInfo
Generation int64
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment