Expose node status so that external preemption plugins can use it

Signed-off-by: Dave Chen <dave.chen@arm.com>
This commit is contained in:
Dave Chen 2021-01-15 13:58:12 +08:00
parent eb2b71c727
commit 9d48a44601
2 changed files with 23 additions and 21 deletions

View File

@ -138,11 +138,23 @@ func (pl *DefaultPreemption) preempt(ctx context.Context, state *framework.Cycle
}
// 2) Find all preemption candidates.
candidates, err := pl.FindCandidates(ctx, state, pod, m)
if err != nil || len(candidates) == 0 {
candidates, evaluatedNodeNum, status, err := pl.FindCandidates(ctx, state, pod, m)
if err != nil {
return "", err
}
// Return a FitError only when there are no candidates that fit the pod.
if len(candidates) == 0 {
return "", &framework.FitError{
Pod: pod,
NumAllNodes: len(evaluatedNodeNum),
Diagnosis: framework.Diagnosis{
NodeToStatusMap: status,
// Leave FailedPlugins as nil as it won't be used on moving Pods.
},
}
}
// 3) Interact with registered Extenders to filter out some candidates if needed.
candidates, err = CallExtenders(ph.Extenders(), pod, nodeLister, candidates)
if err != nil {
@ -186,15 +198,14 @@ func (pl *DefaultPreemption) getOffsetAndNumCandidates(numNodes int32) (int32, i
// FindCandidates calculates a slice of preemption candidates.
// Each candidate is executable to make the given <pod> schedulable.
func (pl *DefaultPreemption) FindCandidates(ctx context.Context, state *framework.CycleState, pod *v1.Pod, m framework.NodeToStatusMap) ([]Candidate, error) {
func (pl *DefaultPreemption) FindCandidates(ctx context.Context, state *framework.CycleState, pod *v1.Pod, m framework.NodeToStatusMap) ([]Candidate, []*framework.NodeInfo, framework.NodeToStatusMap, error) {
allNodes, err := pl.fh.SnapshotSharedLister().NodeInfos().List()
if err != nil {
return nil, err
return nil, nil, nil, err
}
if len(allNodes) == 0 {
return nil, fmt.Errorf("no nodes available")
return nil, nil, nil, fmt.Errorf("no nodes available")
}
potentialNodes := nodesWherePreemptionMightHelp(allNodes, m)
if len(potentialNodes) == 0 {
klog.V(3).Infof("Preemption will not help schedule pod %v/%v on any node.", pod.Namespace, pod.Name)
@ -203,12 +214,12 @@ func (pl *DefaultPreemption) FindCandidates(ctx context.Context, state *framewor
klog.Errorf("Cannot clear 'NominatedNodeName' field of pod %v/%v: %v", pod.Namespace, pod.Name, err)
// We do not return as this error is not critical.
}
return nil, nil
return nil, nil, nil, nil
}
pdbs, err := getPodDisruptionBudgets(pl.pdbLister)
if err != nil {
return nil, err
return nil, nil, nil, err
}
offset, numCandidates := pl.getOffsetAndNumCandidates(int32(len(potentialNodes)))
@ -220,18 +231,7 @@ func (pl *DefaultPreemption) FindCandidates(ctx context.Context, state *framewor
klog.Infof("from a pool of %d nodes (offset: %d, sample %d nodes: %v), ~%d candidates will be chosen", len(potentialNodes), offset, len(sample), sample, numCandidates)
}
candidates, nodeStatuses := dryRunPreemption(ctx, pl.fh, state, pod, potentialNodes, pdbs, offset, numCandidates)
// Return a FitError only when there are no candidates that fit the pod.
if len(candidates) == 0 {
return candidates, &framework.FitError{
Pod: pod,
NumAllNodes: len(potentialNodes),
Diagnosis: framework.Diagnosis{
NodeToStatusMap: nodeStatuses,
// Leave FailedPlugins as nil as it won't be used on moving Pods.
},
}
}
return candidates, nil
return candidates, potentialNodes, nodeStatuses, nil
}
// PodEligibleToPreemptOthers determines whether this pod should be considered

View File

@ -154,7 +154,9 @@ func TestPostFilter(t *testing.T) {
"node1": framework.NewStatus(framework.UnschedulableAndUnresolvable),
},
wantResult: nil,
wantStatus: framework.NewStatus(framework.Unschedulable),
// node1 is not actually been evaluated, it will not be processed by preemption, the status here is an internal status, the final message that is going to be written in
// the log will be looks like "Status after running PostFilter plugins for pod" pod="default/p" status=&{code:2 reasons:[0/0 nodes are available: .] err:<nil>}
wantStatus: framework.NewStatus(framework.Unschedulable, "0/0 nodes are available: ."),
},
{
name: "pod can be made schedulable on one node",