Merge pull request #4026 from marwanad/cherry-pick-fits-any-1.18

Cherry pick #3429 onto 1.18 - Use FitsAnyNode in binpacking
This commit is contained in:
Kubernetes Prow Robot 2021-05-17 07:02:00 -07:00 committed by GitHub
commit 0dd845c9eb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 25 additions and 10 deletions

View File

@ -63,7 +63,7 @@ func (estimator *BinpackingNodeEstimator) Estimate(
podInfos := calculatePodScore(pods, nodeTemplate) podInfos := calculatePodScore(pods, nodeTemplate)
sort.Slice(podInfos, func(i, j int) bool { return podInfos[i].score > podInfos[j].score }) sort.Slice(podInfos, func(i, j int) bool { return podInfos[i].score > podInfos[j].score })
newNodeNames := make([]string, 0) newNodeNames := make(map[string]bool)
if err := estimator.clusterSnapshot.Fork(); err != nil { if err := estimator.clusterSnapshot.Fork(); err != nil {
klog.Errorf("Error while calling ClusterSnapshot.Fork; %v", err) klog.Errorf("Error while calling ClusterSnapshot.Fork; %v", err)
@ -80,16 +80,18 @@ func (estimator *BinpackingNodeEstimator) Estimate(
for _, podInfo := range podInfos { for _, podInfo := range podInfos {
found := false found := false
for _, nodeName := range newNodeNames {
if err := estimator.predicateChecker.CheckPredicates(estimator.clusterSnapshot, podInfo.pod, nodeName); err == nil { nodeName, err := estimator.predicateChecker.FitsAnyNodeMatching(estimator.clusterSnapshot, podInfo.pod, func(nodeInfo *schedulernodeinfo.NodeInfo) bool {
return newNodeNames[nodeInfo.Node().Name]
})
if err == nil {
found = true found = true
if err := estimator.clusterSnapshot.AddPod(podInfo.pod, nodeName); err != nil { if err := estimator.clusterSnapshot.AddPod(podInfo.pod, nodeName); err != nil {
klog.Errorf("Error adding pod %v.%v to node %v in ClusterSnapshot; %v", podInfo.pod.Namespace, podInfo.pod.Name, nodeName, err) klog.Errorf("Error adding pod %v.%v to node %v in ClusterSnapshot; %v", podInfo.pod.Namespace, podInfo.pod.Name, nodeName, err)
return 0 return 0
} }
break
}
} }
if !found { if !found {
// Add new node // Add new node
newNodeName, err := estimator.addNewNodeToSnapshot(nodeTemplate, newNodeNameTimestamp, newNodeNameIndex) newNodeName, err := estimator.addNewNodeToSnapshot(nodeTemplate, newNodeNameTimestamp, newNodeNameIndex)
@ -103,7 +105,7 @@ func (estimator *BinpackingNodeEstimator) Estimate(
klog.Errorf("Error adding pod %v.%v to node %v in ClusterSnapshot; %v", podInfo.pod.Namespace, podInfo.pod.Name, newNodeName, err) klog.Errorf("Error adding pod %v.%v to node %v in ClusterSnapshot; %v", podInfo.pod.Namespace, podInfo.pod.Name, newNodeName, err)
return 0 return 0
} }
newNodeNames = append(newNodeNames, newNodeName) newNodeNames[newNodeName] = true
} }
} }
return len(newNodeNames) return len(newNodeNames)

View File

@ -18,10 +18,12 @@ package simulator
import ( import (
apiv1 "k8s.io/api/core/v1" apiv1 "k8s.io/api/core/v1"
schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo"
) )
// PredicateChecker checks whether all required predicates pass for given Pod and Node. // PredicateChecker checks whether all required predicates pass for given Pod and Node.
type PredicateChecker interface { type PredicateChecker interface {
FitsAnyNode(clusterSnapshot ClusterSnapshot, pod *apiv1.Pod) (string, error) FitsAnyNode(clusterSnapshot ClusterSnapshot, pod *apiv1.Pod) (string, error)
FitsAnyNodeMatching(clusterSnapshot ClusterSnapshot, pod *apiv1.Pod, nodeMatches func(*schedulernodeinfo.NodeInfo) bool) (string, error)
CheckPredicates(clusterSnapshot ClusterSnapshot, pod *apiv1.Pod, nodeName string) *PredicateError CheckPredicates(clusterSnapshot ClusterSnapshot, pod *apiv1.Pod, nodeName string) *PredicateError
} }

View File

@ -89,6 +89,13 @@ func NewSchedulerBasedPredicateChecker(kubeClient kube_client.Interface, stop <-
// FitsAnyNode checks if the given pod can be placed on any of the given nodes. // FitsAnyNode checks if the given pod can be placed on any of the given nodes.
func (p *SchedulerBasedPredicateChecker) FitsAnyNode(clusterSnapshot ClusterSnapshot, pod *apiv1.Pod) (string, error) { func (p *SchedulerBasedPredicateChecker) FitsAnyNode(clusterSnapshot ClusterSnapshot, pod *apiv1.Pod) (string, error) {
return p.FitsAnyNodeMatching(clusterSnapshot, pod, func(*scheduler_nodeinfo.NodeInfo) bool {
return true
})
}
// FitsAnyNodeMatching checks if the given pod can be placed on any of the given nodes matching the provided function.
func (p *SchedulerBasedPredicateChecker) FitsAnyNodeMatching(clusterSnapshot ClusterSnapshot, pod *apiv1.Pod, nodeMatches func(*scheduler_nodeinfo.NodeInfo) bool) (string, error) {
if clusterSnapshot == nil { if clusterSnapshot == nil {
return "", fmt.Errorf("ClusterSnapshot not provided") return "", fmt.Errorf("ClusterSnapshot not provided")
} }
@ -113,6 +120,10 @@ func (p *SchedulerBasedPredicateChecker) FitsAnyNode(clusterSnapshot ClusterSnap
} }
for _, nodeInfo := range nodeInfosList { for _, nodeInfo := range nodeInfosList {
if !nodeMatches(nodeInfo) {
continue
}
// Be sure that the node is schedulable. // Be sure that the node is schedulable.
if nodeInfo.Node().Spec.Unschedulable { if nodeInfo.Node().Spec.Unschedulable {
continue continue