Skip to content

Commit f7057da

Browse files
committed
nrt: filter: distinguish host-level resources
"host-level" resources are resources which are not expected to have NUMA affinity. This means that these resources not showing up in per-NUMA resource counters should not prevent per se scheduling on a given node. Signed-off-by: Francesco Romani <[email protected]>
1 parent e556b49 commit f7057da

File tree

3 files changed

+106
-2
lines changed

3 files changed

+106
-2
lines changed

pkg/noderesourcetopology/filter.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,8 +132,8 @@ func resourcesAvailableInAnyNUMANodes(lh logr.Logger, numaNodes NUMANodeList, re
132132

133133
// non-native resources or ephemeral-storage may not expose NUMA affinity,
134134
// but since they are available at node level, this is fine
135-
if !hasNUMAAffinity && (!v1helper.IsNativeResource(resource) || resource == v1.ResourceEphemeralStorage) {
136-
lh.V(6).Info("resource available at node level (no NUMA affinity)", "resource", resource)
135+
if !hasNUMAAffinity && isHostLevelResource(resource) {
136+
lh.V(6).Info("resource available at host level (no NUMA affinity)", "resource", resource)
137137
continue
138138
}
139139

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
Copyright 2021 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package noderesourcetopology
18+
19+
import (
20+
corev1 "k8s.io/api/core/v1"
21+
v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper"
22+
)
23+
24+
func isHostLevelResource(resource corev1.ResourceName) bool {
25+
// host-level resources are resources which *may* not be bound to NUMA nodes.
26+
// A Key example is generic [ephemeral] storage which doesn't expose NUMA affinity.
27+
if resource == corev1.ResourceEphemeralStorage {
28+
return true
29+
}
30+
if resource == corev1.ResourceStorage {
31+
return true
32+
}
33+
if !v1helper.IsNativeResource(resource) {
34+
return true
35+
}
36+
return false
37+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/*
2+
Copyright 2021 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package noderesourcetopology
18+
19+
import (
20+
"testing"
21+
22+
corev1 "k8s.io/api/core/v1"
23+
)
24+
25+
func TestIsHostLevelResource(t *testing.T) {
26+
testCases := []struct {
27+
resource corev1.ResourceName
28+
expected bool
29+
}{
30+
{
31+
resource: corev1.ResourceCPU,
32+
expected: false,
33+
},
34+
{
35+
resource: corev1.ResourceMemory,
36+
expected: false,
37+
},
38+
{
39+
resource: corev1.ResourceName("hugepages-1Gi"),
40+
expected: false,
41+
},
42+
{
43+
resource: corev1.ResourceStorage,
44+
expected: true,
45+
},
46+
{
47+
resource: corev1.ResourceEphemeralStorage,
48+
expected: true,
49+
},
50+
{
51+
resource: corev1.ResourceName("vendor.io/fastest-nic"),
52+
expected: true,
53+
},
54+
{
55+
resource: corev1.ResourceName("awesome.com/gpu-for-ai"),
56+
expected: true,
57+
},
58+
}
59+
for _, testCase := range testCases {
60+
t.Run(string(testCase.resource), func(t *testing.T) {
61+
got := isHostLevelResource(testCase.resource)
62+
if got != testCase.expected {
63+
t.Fatalf("expected %t to equal %t", got, testCase.expected)
64+
}
65+
})
66+
}
67+
}

0 commit comments

Comments
 (0)