mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-23 19:56:01 +00:00
Include UnschedulableAndUnresolvable
nodes into the status map
Signed-off-by: Dave Chen <dave.chen@arm.com>
This commit is contained in:
parent
9d48a44601
commit
fe5a266a03
@ -138,7 +138,7 @@ func (pl *DefaultPreemption) preempt(ctx context.Context, state *framework.Cycle
|
||||
}
|
||||
|
||||
// 2) Find all preemption candidates.
|
||||
candidates, evaluatedNodeNum, status, err := pl.FindCandidates(ctx, state, pod, m)
|
||||
candidates, nodeToStautsMap, err := pl.FindCandidates(ctx, state, pod, m)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@ -147,9 +147,9 @@ func (pl *DefaultPreemption) preempt(ctx context.Context, state *framework.Cycle
|
||||
if len(candidates) == 0 {
|
||||
return "", &framework.FitError{
|
||||
Pod: pod,
|
||||
NumAllNodes: len(evaluatedNodeNum),
|
||||
NumAllNodes: len(nodeToStautsMap),
|
||||
Diagnosis: framework.Diagnosis{
|
||||
NodeToStatusMap: status,
|
||||
NodeToStatusMap: nodeToStautsMap,
|
||||
// Leave FailedPlugins as nil as it won't be used on moving Pods.
|
||||
},
|
||||
}
|
||||
@ -198,15 +198,15 @@ 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, []*framework.NodeInfo, framework.NodeToStatusMap, error) {
|
||||
func (pl *DefaultPreemption) FindCandidates(ctx context.Context, state *framework.CycleState, pod *v1.Pod, m framework.NodeToStatusMap) ([]Candidate, framework.NodeToStatusMap, error) {
|
||||
allNodes, err := pl.fh.SnapshotSharedLister().NodeInfos().List()
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
if len(allNodes) == 0 {
|
||||
return nil, nil, nil, fmt.Errorf("no nodes available")
|
||||
return nil, nil, fmt.Errorf("no nodes available")
|
||||
}
|
||||
potentialNodes := nodesWherePreemptionMightHelp(allNodes, m)
|
||||
potentialNodes, unschedulableNodeStatus := 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)
|
||||
// In this case, we should clean-up any existing nominated node name of the pod.
|
||||
@ -214,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, nil, nil
|
||||
return nil, unschedulableNodeStatus, nil
|
||||
}
|
||||
|
||||
pdbs, err := getPodDisruptionBudgets(pl.pdbLister)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
offset, numCandidates := pl.getOffsetAndNumCandidates(int32(len(potentialNodes)))
|
||||
@ -231,7 +231,10 @@ 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 candidates, potentialNodes, nodeStatuses, nil
|
||||
for node, status := range unschedulableNodeStatus {
|
||||
nodeStatuses[node] = status
|
||||
}
|
||||
return candidates, nodeStatuses, nil
|
||||
}
|
||||
|
||||
// PodEligibleToPreemptOthers determines whether this pod should be considered
|
||||
@ -268,18 +271,20 @@ func PodEligibleToPreemptOthers(pod *v1.Pod, nodeInfos framework.NodeInfoLister,
|
||||
|
||||
// nodesWherePreemptionMightHelp returns a list of nodes with failed predicates
|
||||
// that may be satisfied by removing pods from the node.
|
||||
func nodesWherePreemptionMightHelp(nodes []*framework.NodeInfo, m framework.NodeToStatusMap) []*framework.NodeInfo {
|
||||
func nodesWherePreemptionMightHelp(nodes []*framework.NodeInfo, m framework.NodeToStatusMap) ([]*framework.NodeInfo, framework.NodeToStatusMap) {
|
||||
var potentialNodes []*framework.NodeInfo
|
||||
nodeStatuses := make(framework.NodeToStatusMap)
|
||||
for _, node := range nodes {
|
||||
name := node.Node().Name
|
||||
// We reply on the status by each plugin - 'Unschedulable' or 'UnschedulableAndUnresolvable'
|
||||
// We rely on the status by each plugin - 'Unschedulable' or 'UnschedulableAndUnresolvable'
|
||||
// to determine whether preemption may help or not on the node.
|
||||
if m[name].Code() == framework.UnschedulableAndUnresolvable {
|
||||
nodeStatuses[node.Node().Name] = framework.NewStatus(framework.UnschedulableAndUnresolvable, "Preemption is not helpful for scheduling")
|
||||
continue
|
||||
}
|
||||
potentialNodes = append(potentialNodes, node)
|
||||
}
|
||||
return potentialNodes
|
||||
return potentialNodes, nodeStatuses
|
||||
}
|
||||
|
||||
type candidateList struct {
|
||||
|
@ -154,9 +154,7 @@ func TestPostFilter(t *testing.T) {
|
||||
"node1": framework.NewStatus(framework.UnschedulableAndUnresolvable),
|
||||
},
|
||||
wantResult: nil,
|
||||
// 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: ."),
|
||||
wantStatus: framework.NewStatus(framework.Unschedulable, "0/1 nodes are available: 1 Preemption is not helpful for scheduling."),
|
||||
},
|
||||
{
|
||||
name: "pod can be made schedulable on one node",
|
||||
@ -233,6 +231,26 @@ func TestPostFilter(t *testing.T) {
|
||||
wantResult: nil,
|
||||
wantStatus: framework.NewStatus(framework.Unschedulable, "0/2 nodes are available: 1 Insufficient cpu, 1 No victims found on node node1 for preemptor pod p."),
|
||||
},
|
||||
{
|
||||
name: "no candidate nodes found with mixed reason, 2 UnschedulableAndUnresolvable nodes and 2 nodes don't have enough CPU resource",
|
||||
pod: st.MakePod().Name("p").UID("p").Namespace(v1.NamespaceDefault).Priority(highPriority).Req(largeRes).Obj(),
|
||||
pods: []*v1.Pod{
|
||||
st.MakePod().Name("p1").UID("p1").Namespace(v1.NamespaceDefault).Node("node1").Obj(),
|
||||
st.MakePod().Name("p2").UID("p2").Namespace(v1.NamespaceDefault).Node("node2").Obj(),
|
||||
},
|
||||
nodes: []*v1.Node{
|
||||
st.MakeNode().Name("node1").Capacity(nodeRes).Obj(),
|
||||
st.MakeNode().Name("node2").Capacity(nodeRes).Obj(),
|
||||
st.MakeNode().Name("node3").Capacity(nodeRes).Obj(),
|
||||
st.MakeNode().Name("node4").Capacity(nodeRes).Obj(),
|
||||
},
|
||||
filteredNodesStatuses: framework.NodeToStatusMap{
|
||||
"node3": framework.NewStatus(framework.UnschedulableAndUnresolvable),
|
||||
"node4": framework.NewStatus(framework.UnschedulableAndUnresolvable),
|
||||
},
|
||||
wantResult: nil,
|
||||
wantStatus: framework.NewStatus(framework.Unschedulable, "0/4 nodes are available: 2 Insufficient cpu, 2 Preemption is not helpful for scheduling."),
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
@ -1413,7 +1431,7 @@ func TestNodesWherePreemptionMightHelp(t *testing.T) {
|
||||
ni.SetNode(st.MakeNode().Name(name).Obj())
|
||||
nodeInfos = append(nodeInfos, ni)
|
||||
}
|
||||
nodes := nodesWherePreemptionMightHelp(nodeInfos, tt.nodesStatuses)
|
||||
nodes, _ := nodesWherePreemptionMightHelp(nodeInfos, tt.nodesStatuses)
|
||||
if len(tt.expected) != len(nodes) {
|
||||
t.Errorf("number of nodes is not the same as expected. exptectd: %d, got: %d. Nodes: %v", len(tt.expected), len(nodes), nodes)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user