Repository: kubernetes/kubernetes (language: go)

Issue:
scheduler: preallocation for NodeToStatusMap
<!--  Thanks for sending a pull request!  Here are some tips for you:

1. If this is your first time, please read our contributor guidelines: https://git.k8s.io/community/contributors/guide/first-contribution.md#your-first-contribution and developer guide https://git.k8s.io/community/contributors/devel/development.md#development-guide
2. Please label this pull request according to what type of issue you are addressing, especially if this is a release targeted pull request. For reference on required PR/issue labels, read here:
https://git.k8s.io/community/contributors/devel/sig-release/release.md#issuepr-kind-label
3. Ensure you have added or ran the appropriate tests for your PR: https://git.k8s.io/community/contributors/devel/sig-testing/testing.md
4. If you want *faster* PR reviews, read how: https://git.k8s.io/community/contributors/guide/pull-requests.md#best-practices-for-faster-reviews
5. If the PR is unfinished, see how to mark it: https://git.k8s.io/community/contributors/guide/pull-requests.md#marking-unfinished-pull-requests
-->

#### What type of PR is this?

/kind bug
/kind regression

<!--
Add one of the following kinds:
/kind bug
/kind cleanup
/kind documentation
/kind feature

Optionally add one or more of the following kinds if applicable:
/kind api-change
/kind deprecation
/kind failing-test
/kind flake
/kind regression
-->

#### What this PR does / why we need it:

Improve the throughput by a preallocation for NodeToStatusMap.

#### Which issue(s) this PR fixes:
<!--
*Automatically closes linked issue when PR is merged.
Usage: `Fixes #<issue number>`, or `Fixes (paste link of issue)`.
_If PR is about `failing-tests or flakes`, please post the related issues/tests in a comment and do not use `Fixes`_*
-->
Part of (hopefully fix) #124709

Edit: This was reverted in https://github.com/kubernetes/kubernetes/pull/125197 prior to release of 1.31.0

#### Special notes for your reviewer:

#### Does this PR introduce a user-facing change?
<!--
If no, just write "NONE" in the release-note block below.
If yes, a release note is required:
Enter your extended release note in the block below. If the PR requires additional action from users switching to the new release, include the string "action required".

For more information on release notes see: https://git.k8s.io/community/contributors/guide/release-notes.md
-->
```release-note
Fix a performance regression in 1.30.0 for scheduling daemonset pods to reach 300 pods/s, if the configured qps allows it.
```

#### Additional documentation e.g., KEPs (Kubernetes Enhancement Proposals), usage docs, etc.:

<!--
This section can be blank if this pull request does not require a release note.

When adding links which point to resources within git repositories, like
KEPs or supporting documentation, please reference a specific commit and avoid
linking directly to the master branch. This ensures that links reference a
specific point in time, rather than a document that may change over time.

See here for guidance on getting permanent links to files: https://help.github.com/en/articles/getting-permanent-links-to-files

Please use the following format for linking documentation:
- [KEP]: <link>
- [Usage]: <link>
- [Other doc]: <link>
-->
```docs

```

Throughput degradation scheduling daemonset pods
### What happened?

https://github.com/kubernetes/kubernetes/pull/119779 added some map queries and creations that add non-negligible latency.

The pprof reveals the following lines inside `findNodesThatFitPod` as too expensive:
- 22.2% https://github.com/kubernetes/kubernetes/blob/44bd04c0cbddde69aaeb7a90d3bd3de4e417f27f/pkg/scheduler/schedule_one.go#L492
- 21.7% https://github.com/kubernetes/kubernetes/blob/44bd04c0cbddde69aaeb7a90d3bd3de4e417f27f/pkg/scheduler/schedule_one.go#L489

![image](https://github.com/kubernetes/kubernetes/assets/1299064/d82a658e-ae01-4bcd-9e0d-6ab892bee6c2)


### What did you expect to happen?

Scheduler to keep a throughput of 300 pods/s

### How can we reproduce it (as minimally and precisely as possible)?

Schedule 5k daemonset pods giving 300 qps to the scheduler

### Anything else we need to know?

_No response_

### Kubernetes version

<details>

```console
$ kubectl version
# paste output here
```
v1.30
</details>


### Cloud provider

<details>
GKE
</details>


### OS version

<details>

```console
# On Linux:
$ cat /etc/os-release
# paste output here
$ uname -a
# paste output here

# On Windows:
C:\> wmic os get Caption, Version, BuildNumber, OSArchitecture
# paste output here
```

</details>


### Install tools

<details>

</details>


### Container runtime (CRI) and version (if applicable)

<details>

</details>


### Related plugins (CNI, CSI, ...) and versions (if applicable)

<details>

</details>



Discussion / hints:
This issue is currently awaiting triage.

If a SIG or subproject determines this is a relevant issue, they will accept it by applying the `triage/accepted` label and provide further guidance.

The `triage/accepted` label can be added by org members by writing `/triage accepted` in a comment.


<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes-sigs/prow](https://github.com/kubernetes-sigs/prow/issues/new?title=Prow%20issue:) repository.
</details>
/cc @alculquicondor 
This patch allows us to reach 300 pods/s again
/lgtm
/approve

Can you open a cherry-pick for release-1.30?
LGTM label has been added.  <details>Git tree hash: cabde4b4d4acb424ef24fafe1fce6f24db0deda6</details>
[APPROVALNOTIFIER] This PR is **APPROVED**

This pull-request has been approved by: *<a href="https://github.com/kubernetes/kubernetes/pull/124714#issuecomment-2098360727" title="Approved">alculquicondor</a>*, *<a href="https://github.com/kubernetes/kubernetes/pull/124714#" title="Author self-approved">sanposhiho</a>*

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=kubernetes%2Fkubernetes).

The pull request process is described [here](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process)

<details >
Needs approval from an approver in each of these files:

- ~~[pkg/scheduler/OWNERS](https://github.com/kubernetes/kubernetes/blob/master/pkg/scheduler/OWNERS)~~ [alculquicondor,sanposhiho]

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":[]} -->
Is it possible that we regressed something timing related here? 

See https://github.com/kubernetes/kubernetes/issues/124743
@saschagrunert Well... This PR is just changing the internal data structure's field to be preallocated.
I'm not very familiar with the failing test though, I cannot think of any scenarios that this PR could affect the behaviors of sig-node's stuff (actually even in the scheduler except perf improvement).


> Can you open a cherry-pick for release-1.30?

Done; https://github.com/kubernetes/kubernetes/pull/124753
/release-note-edit

```release-note
Fix throughput when scheduling daemonset pods to reach 300 pods/s, if the configured qps allows it.
```
This issue is currently awaiting triage.

If a SIG or subproject determines this is a relevant issue, they will accept it by applying the `triage/accepted` label and provide further guidance.

The `triage/accepted` label can be added by org members by writing `/triage accepted` in a comment.


<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes-sigs/prow](https://github.com/kubernetes-sigs/prow/issues/new?title=Prow%20issue:) repository.
</details>
/sig scheduling
Before #119779, there was this line:
https://github.com/sanposhiho/kubernetes/blob/5ab23179473b621e911511b03693234b60a38033/pkg/scheduler/schedule_one.go#L489

which also had a map access. So we can quite confidently say that the culprit is just the map insert of https://github.com/kubernetes/kubernetes/blob/44bd04c0cbddde69aaeb7a90d3bd3de4e417f27f/pkg/scheduler/schedule_one.go#L492
@sanposhiho, @AxeZhan  I have two alternatives:

1. The obvious one is to do a preallocation for the size of the map. I suspect this might be enough, but still somewhat wasteful.
2. Change the preemption logic to assume that if a Node is not in the status map, it's `UnschedulableAndUnresolvable`. https://github.com/kubernetes/kubernetes/blob/44bd04c0cbddde69aaeb7a90d3bd3de4e417f27f/pkg/scheduler/framework/preemption/preemption.go#L422

Option 2 also solves #124705. However, external PostFilter plugins need to be aware of the change. But I'm not aware of any in the wild that implements a behavior similar to preemption. We can leave an ACTION REQUIRED. But was this path working in 1.28 and older?

Regardless of the decision, I think we should accompany the fix with an integration test for preemption by daemonset pods.
Can we try (1) first, ask Google for a scalability test again, and then consider (2) if (1) doesn't improve the throughput enough?

(2) could break existing PostFilter plugins. Given PostFilter is not only for preemption, in the world, there may be custom PostFilter plugins which have to rely on the status map with UnschedulableAndUnresolvable nodes. So, it'd be best if we could avoid this breaking.
Since (1) is a really small fix, I'm also thinking if we can run tests after #124714 , and then consider (2) base on the test results.

> Regardless of the decision, I think we should accompany the fix with an integration test for preemption by daemonset pods.

Are these "integration test" for performance or correctness?
I was asking for a correctness test
I wrote a benchmark test called `Benchmark_findNodesThatFitPod`

The performance without case(1) is: 
```
4927125125 ~ 5118241875 ns/op
```

The performance of case (1) is: 
```
3865283834 ~ 3972690125 ns/op
```

(1) may improve throughput
I guess we can have a different tracking issue for an integration benchmark.

This issue itself is fixed.

/close
@alculquicondor: Closing this issue.

<details>

In response to [this](https://github.com/kubernetes/kubernetes/issues/124709#issuecomment-2110490510):

>I guess we can have a different tracking issue for an integration benchmark.
>
>This issue itself is fixed.
>
>/close


Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes-sigs/prow](https://github.com/kubernetes-sigs/prow/issues/new?title=Prow%20issue:) repository.
</details>
/reopen
/assign

Still observing poor performance in large clusters post #124714. I'm investigating further improvements.
@gabesaba: You can't reopen an issue/PR unless you authored it or you are a collaborator.

<details>

In response to [this](https://github.com/kubernetes/kubernetes/issues/124709#issuecomment-2126982007):

>/reopen
>/assign
>
>Still observing poor performance in large clusters post #124714. I'm investigating further improvements.


Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes-sigs/prow](https://github.com/kubernetes-sigs/prow/issues/new?title=Prow%20issue:) repository.
</details>
/reopen
@alculquicondor: Reopened this issue.

<details>

In response to [this](https://github.com/kubernetes/kubernetes/issues/124709#issuecomment-2127420212):

>/reopen


Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes-sigs/prow](https://github.com/kubernetes-sigs/prow/issues/new?title=Prow%20issue:) repository.
</details>

Fix patch:
diff --git a/pkg/scheduler/framework/interface.go b/pkg/scheduler/framework/interface.go
index 5fd8bd86fcf5a..c5b7d89ceed6d 100644
--- a/pkg/scheduler/framework/interface.go
+++ b/pkg/scheduler/framework/interface.go
@@ -49,7 +49,8 @@ type NodeScore struct {
 	Score int64
 }
 
-// NodeToStatusMap declares map from node name to its status.
+// NodeToStatusMap contains the statuses of the Nodes where the incoming Pod was not schedulable.
+// A PostFilter plugin that uses this map should interpret absent Nodes as UnschedulableAndUnresolvable.
 type NodeToStatusMap map[string]*Status
 
 // NodePluginScores is a struct with node name and scores for that node.
@@ -448,6 +449,7 @@ type PostFilterPlugin interface {
 	// If this scheduling cycle failed at PreFilter, all Nodes have the status from the rejector PreFilter plugin in NodeToStatusMap.
 	// Note that the scheduling framework runs PostFilter plugins even when PreFilter returned UnschedulableAndUnresolvable.
 	// In that case, NodeToStatusMap contains all Nodes with UnschedulableAndUnresolvable.
+	// If there is no entry in the NodeToStatus map, its implicit status is UnschedulableAndUnresolvable.
 	//
 	// Also, ignoring Nodes with UnschedulableAndUnresolvable is the responsibility of each PostFilter plugin,
 	// meaning NodeToStatusMap obviously could have Nodes with UnschedulableAndUnresolvable
diff --git a/pkg/scheduler/framework/preemption/preemption.go b/pkg/scheduler/framework/preemption/preemption.go
index 376b6337e99f6..29864adb52f78 100644
--- a/pkg/scheduler/framework/preemption/preemption.go
+++ b/pkg/scheduler/framework/preemption/preemption.go
@@ -415,15 +415,18 @@ func (ev *Evaluator) prepareCandidate(ctx context.Context, c Candidate, pod *v1.
 func nodesWherePreemptionMightHelp(nodes []*framework.NodeInfo, m framework.NodeToStatusMap) ([]*framework.NodeInfo, framework.NodeToStatusMap) {
 	var potentialNodes []*framework.NodeInfo
 	nodeStatuses := make(framework.NodeToStatusMap)
+	unresolvableStatus := framework.NewStatus(framework.UnschedulableAndUnresolvable, "Preemption is not helpful for scheduling")
 	for _, node := range nodes {
-		name := node.Node().Name
-		// 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
+		nodeName := node.Node().Name
+		// We only attempt preemption on nodes with status 'Unschedulable'. For
+		// diagnostic purposes, we propagate UnschedulableAndUnresolvable if either
+		// implied by absence in map or explicitly set.
+		status, ok := m[nodeName]
+		if status.Code() == framework.Unschedulable {
+			potentialNodes = append(potentialNodes, node)
+		} else if !ok || status.Code() == framework.UnschedulableAndUnresolvable {
+			nodeStatuses[nodeName] = unresolvableStatus
 		}
-		potentialNodes = append(potentialNodes, node)
 	}
 	return potentialNodes, nodeStatuses
 }
diff --git a/pkg/scheduler/framework/types.go b/pkg/scheduler/framework/types.go
index 164e6aa409589..6856b78f2706a 100644
--- a/pkg/scheduler/framework/types.go
+++ b/pkg/scheduler/framework/types.go
@@ -325,9 +325,11 @@ const ExtenderName = "Extender"
 
 // Diagnosis records the details to diagnose a scheduling failure.
 type Diagnosis struct {
-	// NodeToStatusMap records the status of each node
+	// NodeToStatusMap records the status of each retriable node (status Unschedulable)
 	// if they're rejected in PreFilter (via PreFilterResult) or Filter plugins.
 	// Nodes that pass PreFilter/Filter plugins are not included in this map.
+	// While this map may contain UnschedulableAndUnresolvable statuses, the absence of
+	// a node should be interpreted as UnschedulableAndUnresolvable.
 	NodeToStatusMap NodeToStatusMap
 	// UnschedulablePlugins are plugins that returns Unschedulable or UnschedulableAndUnresolvable.
 	UnschedulablePlugins sets.Set[string]
diff --git a/pkg/scheduler/schedule_one.go b/pkg/scheduler/schedule_one.go
index 74b1ed2b2fa78..6b6992095d881 100644
--- a/pkg/scheduler/schedule_one.go
+++ b/pkg/scheduler/schedule_one.go
@@ -441,14 +441,13 @@ func (sched *Scheduler) schedulePod(ctx context.Context, fwk framework.Framework
 // filter plugins and filter extenders.
 func (sched *Scheduler) findNodesThatFitPod(ctx context.Context, fwk framework.Framework, state *framework.CycleState, pod *v1.Pod) ([]*framework.NodeInfo, framework.Diagnosis, error) {
 	logger := klog.FromContext(ctx)
+	diagnosis := framework.Diagnosis{
+		NodeToStatusMap: make(framework.NodeToStatusMap),
+	}
 
 	allNodes, err := sched.nodeInfoSnapshot.NodeInfos().List()
 	if err != nil {
-		return nil, framework.Diagnosis{}, err
-	}
-
-	diagnosis := framework.Diagnosis{
-		NodeToStatusMap: make(framework.NodeToStatusMap, len(allNodes)),
+		return nil, diagnosis, err
 	}
 	// Run "prefilter" plugins.
 	preRes, s := fwk.RunPreFilterPlugins(ctx, state, pod)
@@ -486,14 +485,12 @@ func (sched *Scheduler) findNodesThatFitPod(ctx context.Context, fwk framework.F
 	nodes := allNodes
 	if !preRes.AllNodes() {
 		nodes = make([]*framework.NodeInfo, 0, len(preRes.NodeNames))
-		for _, n := range allNodes {
-			if !preRes.NodeNames.Has(n.Node().Name) {
-				// We consider Nodes that are filtered out by PreFilterResult as rejected via UnschedulableAndUnresolvable.
-				// We have to record them in NodeToStatusMap so that they won't be considered as candidates in the preemption.
-				diagnosis.NodeToStatusMap[n.Node().Name] = framework.NewStatus(framework.UnschedulableAndUnresolvable, "node is filtered out by the prefilter result")
-				continue
+		for nodeName := range preRes.NodeNames {
+			// PreRes may return nodeName(s) which do not exist; we verify
+			// node exists in the Snapshot.
+			if nodeInfo, err := sched.nodeInfoSnapshot.Get(nodeName); err == nil {
+				nodes = append(nodes, nodeInfo)
 			}
-			nodes = append(nodes, n)
 		}
 	}
 	feasibleNodes, err := sched.findNodesThatPassFilters(ctx, fwk, state, pod, &diagnosis, nodes)


Test patch:
diff --git a/pkg/scheduler/framework/plugins/defaultpreemption/default_preemption_test.go b/pkg/scheduler/framework/plugins/defaultpreemption/default_preemption_test.go
index 536ac11171553..915016388cff6 100644
--- a/pkg/scheduler/framework/plugins/defaultpreemption/default_preemption_test.go
+++ b/pkg/scheduler/framework/plugins/defaultpreemption/default_preemption_test.go
@@ -289,7 +289,8 @@ func TestPostFilter(t *testing.T) {
 				st.MakeNode().Name("node4").Capacity(nodeRes).Obj(),
 			},
 			filteredNodesStatuses: framework.NodeToStatusMap{
-				"node3": framework.NewStatus(framework.UnschedulableAndUnresolvable),
+				"node1": framework.NewStatus(framework.Unschedulable),
+				"node2": framework.NewStatus(framework.Unschedulable),
 				"node4": framework.NewStatus(framework.UnschedulableAndUnresolvable),
 			},
 			wantResult: framework.NewPostFilterResultWithNominatedNode(""),
@@ -1776,7 +1777,15 @@ func TestPreempt(t *testing.T) {
 				State:      state,
 				Interface:  &pl,
 			}
-			res, status := pe.Preempt(ctx, test.pod, make(framework.NodeToStatusMap))
+
+			// so that these nodes are eligible for preemption, we set their status
+			// to Unschedulable.
+			nodeToStatusMap := make(framework.NodeToStatusMap, len(nodes))
+			for _, n := range nodes {
+				nodeToStatusMap[n.Name] = framework.NewStatus(framework.Unschedulable)
+			}
+
+			res, status := pe.Preempt(ctx, test.pod, nodeToStatusMap)
 			if !status.IsSuccess() && !status.IsRejected() {
 				t.Errorf("unexpected error in preemption: %v", status.AsError())
 			}
diff --git a/pkg/scheduler/framework/preemption/preemption_test.go b/pkg/scheduler/framework/preemption/preemption_test.go
index 5ddf60c199746..0bf384239ac6c 100644
--- a/pkg/scheduler/framework/preemption/preemption_test.go
+++ b/pkg/scheduler/framework/preemption/preemption_test.go
@@ -147,6 +147,7 @@ func TestNodesWherePreemptionMightHelp(t *testing.T) {
 				"node1": framework.NewStatus(framework.Unschedulable, interpodaffinity.ErrReasonAntiAffinityRulesNotMatch),
 				"node2": framework.NewStatus(framework.UnschedulableAndUnresolvable, nodename.ErrReason),
 				"node3": framework.NewStatus(framework.UnschedulableAndUnresolvable, nodeunschedulable.ErrReasonUnschedulable),
+				"node4": framework.NewStatus(framework.Unschedulable, "Unschedulable"),
 			},
 			expected: sets.New("node1", "node4"),
 		},
@@ -155,6 +156,8 @@ func TestNodesWherePreemptionMightHelp(t *testing.T) {
 			nodesStatuses: framework.NodeToStatusMap{
 				"node1": framework.NewStatus(framework.UnschedulableAndUnresolvable, interpodaffinity.ErrReasonAffinityRulesNotMatch),
 				"node2": framework.NewStatus(framework.Unschedulable, interpodaffinity.ErrReasonAntiAffinityRulesNotMatch),
+				"node3": framework.NewStatus(framework.Unschedulable, "Unschedulable"),
+				"node4": framework.NewStatus(framework.Unschedulable, "Unschedulable"),
 			},
 			expected: sets.New("node2", "node3", "node4"),
 		},
@@ -163,6 +166,8 @@ func TestNodesWherePreemptionMightHelp(t *testing.T) {
 			nodesStatuses: framework.NodeToStatusMap{
 				"node1": framework.NewStatus(framework.UnschedulableAndUnresolvable, volumerestrictions.ErrReasonDiskConflict),
 				"node2": framework.NewStatus(framework.Unschedulable, fmt.Sprintf("Insufficient %v", v1.ResourceMemory)),
+				"node3": framework.NewStatus(framework.Unschedulable, "Unschedulable"),
+				"node4": framework.NewStatus(framework.Unschedulable, "Unschedulable"),
 			},
 			expected: sets.New("node2", "node3", "node4"),
 		},
@@ -170,6 +175,9 @@ func TestNodesWherePreemptionMightHelp(t *testing.T) {
 			name: "Node condition errors should be considered unresolvable",
 			nodesStatuses: framework.NodeToStatusMap{
 				"node1": framework.NewStatus(framework.UnschedulableAndUnresolvable, nodeunschedulable.ErrReasonUnknownCondition),
+				"node2": framework.NewStatus(framework.Unschedulable, "Unschedulable"),
+				"node3": framework.NewStatus(framework.Unschedulable, "Unschedulable"),
+				"node4": framework.NewStatus(framework.Unschedulable, "Unschedulable"),
 			},
 			expected: sets.New("node2", "node3", "node4"),
 		},
@@ -179,6 +187,7 @@ func TestNodesWherePreemptionMightHelp(t *testing.T) {
 				"node1": framework.NewStatus(framework.UnschedulableAndUnresolvable, volumezone.ErrReasonConflict),
 				"node2": framework.NewStatus(framework.UnschedulableAndUnresolvable, string(volumebinding.ErrReasonNodeConflict)),
 				"node3": framework.NewStatus(framework.UnschedulableAndUnresolvable, string(volumebinding.ErrReasonBindConflict)),
+				"node4": framework.NewStatus(framework.Unschedulable, "Unschedulable"),
 			},
 			expected: sets.New("node4"),
 		},
@@ -188,12 +197,14 @@ func TestNodesWherePreemptionMightHelp(t *testing.T) {
 				"node1": framework.NewStatus(framework.Unschedulable, podtopologyspread.ErrReasonConstraintsNotMatch),
 				"node2": framework.NewStatus(framework.UnschedulableAndUnresolvable, nodename.ErrReason),
 				"node3": framework.NewStatus(framework.Unschedulable, podtopologyspread.ErrReasonConstraintsNotMatch),
+				"node4": framework.NewStatus(framework.Unschedulable, "Unschedulable"),
 			},
 			expected: sets.New("node1", "node3", "node4"),
 		},
 		{
 			name: "UnschedulableAndUnresolvable status should be skipped but Unschedulable should be tried",
 			nodesStatuses: framework.NodeToStatusMap{
+				"node1": framework.NewStatus(framework.Unschedulable, ""),
 				"node2": framework.NewStatus(framework.UnschedulableAndUnresolvable, ""),
 				"node3": framework.NewStatus(framework.Unschedulable, ""),
 				"node4": framework.NewStatus(framework.UnschedulableAndUnresolvable, ""),
@@ -203,6 +214,7 @@ func TestNodesWherePreemptionMightHelp(t *testing.T) {
 		{
 			name: "ErrReasonNodeLabelNotMatch should not be tried as it indicates that the pod is unschedulable due to node doesn't have the required label",
 			nodesStatuses: framework.NodeToStatusMap{
+				"node1": framework.NewStatus(framework.Unschedulable, ""),
 				"node2": framework.NewStatus(framework.UnschedulableAndUnresolvable, podtopologyspread.ErrReasonNodeLabelNotMatch),
 				"node3": framework.NewStatus(framework.Unschedulable, ""),
 				"node4": framework.NewStatus(framework.UnschedulableAndUnresolvable, ""),
diff --git a/pkg/scheduler/schedule_one_test.go b/pkg/scheduler/schedule_one_test.go
index 546893c31beba..81c08147623a1 100644
--- a/pkg/scheduler/schedule_one_test.go
+++ b/pkg/scheduler/schedule_one_test.go
@@ -2344,7 +2344,6 @@ func TestSchedulerSchedulePod(t *testing.T) {
 				NumAllNodes: 2,
 				Diagnosis: framework.Diagnosis{
 					NodeToStatusMap: framework.NodeToStatusMap{
-						"node1": framework.NewStatus(framework.UnschedulableAndUnresolvable, "node is filtered out by the prefilter result"),
 						"node2": framework.NewStatus(framework.Unschedulable, "injecting failure for pod test-prefilter").WithPlugin("FakeFilter"),
 					},
 					UnschedulablePlugins: sets.New("FakeFilter"),
@@ -2453,10 +2452,7 @@ func TestSchedulerSchedulePod(t *testing.T) {
 				Pod:         st.MakePod().Name("test-prefilter").UID("test-prefilter").Obj(),
 				NumAllNodes: 2,
 				Diagnosis: framework.Diagnosis{
-					NodeToStatusMap: framework.NodeToStatusMap{
-						"1": framework.NewStatus(framework.UnschedulableAndUnresolvable, "node is filtered out by the prefilter result"),
-						"2": framework.NewStatus(framework.UnschedulableAndUnresolvable, "node is filtered out by the prefilter result"),
-					},
+					NodeToStatusMap: framework.NodeToStatusMap{},
 				},
 			},
 		},