@@ -41,16 +41,9 @@ const highestNUMAID = 8
41
41
42
42
type PolicyHandler func (pod * v1.Pod , zoneMap topologyv1alpha2.ZoneList ) * framework.Status
43
43
44
- func singleNUMAContainerLevelHandler (lh logr.Logger , pod * v1.Pod , zones topologyv1alpha2. ZoneList , nodeInfo * framework. NodeInfo ) * framework.Status {
44
+ func singleNUMAContainerLevelHandler (lh logr.Logger , pod * v1.Pod , info * filterInfo ) * framework.Status {
45
45
lh .V (5 ).Info ("container level single NUMA node handler" )
46
46
47
- // prepare NUMANodes list from zoneMap
48
- nodes := createNUMANodeList (lh , zones )
49
- qos := v1qos .GetPodQOS (pod )
50
-
51
- // Node() != nil already verified in Filter(), which is the only public entry point
52
- logNumaNodes (lh , "container handler NUMA resources" , nodeInfo .Node ().Name , nodes )
53
-
54
47
// the init containers are running SERIALLY and BEFORE the normal containers.
55
48
// https://kubernetes.io/docs/concepts/workloads/pods/init-containers/#understanding-init-containers
56
49
// therefore, we don't need to accumulate their resources together
@@ -59,7 +52,7 @@ func singleNUMAContainerLevelHandler(lh logr.Logger, pod *v1.Pod, zones topology
59
52
clh := lh .WithValues (logging .KeyContainer , initContainer .Name , logging .KeyContainerKind , cntKind )
60
53
clh .V (6 ).Info ("desired resources" , stringify .ResourceListToLoggable (initContainer .Resources .Requests )... )
61
54
62
- _ , match := resourcesAvailableInAnyNUMANodes (clh , nodes , initContainer .Resources .Requests , qos , nodeInfo )
55
+ _ , match := resourcesAvailableInAnyNUMANodes (clh , info , initContainer .Resources .Requests )
63
56
if ! match {
64
57
msg := "cannot align " + cntKind + " container"
65
58
// we can't align init container, so definitely we can't align a pod
@@ -72,7 +65,7 @@ func singleNUMAContainerLevelHandler(lh logr.Logger, pod *v1.Pod, zones topology
72
65
clh := lh .WithValues (logging .KeyContainer , container .Name , logging .KeyContainerKind , logging .KindContainerApp )
73
66
clh .V (6 ).Info ("container requests" , stringify .ResourceListToLoggable (container .Resources .Requests )... )
74
67
75
- numaID , match := resourcesAvailableInAnyNUMANodes (clh , nodes , container .Resources .Requests , qos , nodeInfo )
68
+ numaID , match := resourcesAvailableInAnyNUMANodes (clh , info , container .Resources .Requests )
76
69
if ! match {
77
70
// we can't align container, so definitely we can't align a pod
78
71
clh .V (2 ).Info ("cannot align container" )
@@ -81,7 +74,7 @@ func singleNUMAContainerLevelHandler(lh logr.Logger, pod *v1.Pod, zones topology
81
74
82
75
// subtract the resources requested by the container from the given NUMA.
83
76
// this is necessary, so we won't allocate the same resources for the upcoming containers
84
- err := subtractResourcesFromNUMANodeList (clh , nodes , numaID , qos , container .Resources .Requests )
77
+ err := subtractResourcesFromNUMANodeList (clh , info . numaNodes , numaID , info . qos , container .Resources .Requests )
85
78
if err != nil {
86
79
// this is an internal error which should never happen
87
80
return framework .NewStatus (framework .Error , "inconsistent resource accounting" , err .Error ())
@@ -93,14 +86,14 @@ func singleNUMAContainerLevelHandler(lh logr.Logger, pod *v1.Pod, zones topology
93
86
94
87
// resourcesAvailableInAnyNUMANodes checks for sufficient resource and return the NUMAID that would be selected by Kubelet.
95
88
// this function requires NUMANodeList with properly populated NUMANode, NUMAID should be in range 0-63
96
- func resourcesAvailableInAnyNUMANodes (lh logr.Logger , numaNodes NUMANodeList , resources v1.ResourceList , qos v1. PodQOSClass , nodeInfo * framework. NodeInfo ) (int , bool ) {
89
+ func resourcesAvailableInAnyNUMANodes (lh logr.Logger , info * filterInfo , resources v1.ResourceList ) (int , bool ) {
97
90
numaID := highestNUMAID
98
91
bitmask := bm .NewEmptyBitMask ()
99
92
// set all bits, each bit is a NUMA node, if resources couldn't be aligned
100
93
// on the NUMA node, bit should be unset
101
94
bitmask .Fill ()
102
95
103
- nodeResources := util .ResourceList (nodeInfo .Allocatable )
96
+ nodeResources := util .ResourceList (info . node .Allocatable )
104
97
105
98
for resource , quantity := range resources {
106
99
if quantity .IsZero () {
@@ -121,14 +114,14 @@ func resourcesAvailableInAnyNUMANodes(lh logr.Logger, numaNodes NUMANodeList, re
121
114
// obvious, bits which are not in the NUMA id's range would be unset
122
115
hasNUMAAffinity := false
123
116
resourceBitmask := bm .NewEmptyBitMask ()
124
- for _ , numaNode := range numaNodes {
117
+ for _ , numaNode := range info . numaNodes {
125
118
numaQuantity , ok := numaNode .Resources [resource ]
126
119
if ! ok {
127
120
continue
128
121
}
129
122
130
123
hasNUMAAffinity = true
131
- if ! isResourceSetSuitable (qos , resource , quantity , numaQuantity ) {
124
+ if ! isResourceSetSuitable (info . qos , resource , quantity , numaQuantity ) {
132
125
continue
133
126
}
134
127
@@ -161,18 +154,13 @@ func resourcesAvailableInAnyNUMANodes(lh logr.Logger, numaNodes NUMANodeList, re
161
154
return numaID , ret
162
155
}
163
156
164
- func singleNUMAPodLevelHandler (lh logr.Logger , pod * v1.Pod , zones topologyv1alpha2. ZoneList , nodeInfo * framework. NodeInfo ) * framework.Status {
157
+ func singleNUMAPodLevelHandler (lh logr.Logger , pod * v1.Pod , info * filterInfo ) * framework.Status {
165
158
lh .V (5 ).Info ("pod level single NUMA node handler" )
166
159
167
160
resources := util .GetPodEffectiveRequest (pod )
168
-
169
- nodes := createNUMANodeList (lh , zones )
170
-
171
- // Node() != nil already verified in Filter(), which is the only public entry point
172
- logNumaNodes (lh , "pod handler NUMA resources" , nodeInfo .Node ().Name , nodes )
173
161
lh .V (6 ).Info ("pod desired resources" , stringify .ResourceListToLoggable (resources )... )
174
162
175
- numaID , match := resourcesAvailableInAnyNUMANodes (lh , createNUMANodeList ( lh , zones ), resources , v1qos . GetPodQOS ( pod ), nodeInfo )
163
+ numaID , match := resourcesAvailableInAnyNUMANodes (lh , info , resources )
176
164
if ! match {
177
165
lh .V (2 ).Info ("cannot align pod" , "name" , pod .Name )
178
166
return framework .NewStatus (framework .Unschedulable , "cannot align pod" )
@@ -186,7 +174,8 @@ func (tm *TopologyMatch) Filter(ctx context.Context, cycleState *framework.Cycle
186
174
if nodeInfo .Node () == nil {
187
175
return framework .NewStatus (framework .Error , "node not found" )
188
176
}
189
- if v1qos .GetPodQOS (pod ) == v1 .PodQOSBestEffort && ! resourcerequests .IncludeNonNative (pod ) {
177
+ qos := v1qos .GetPodQOS (pod )
178
+ if qos == v1 .PodQOSBestEffort && ! resourcerequests .IncludeNonNative (pod ) {
190
179
return nil
191
180
}
192
181
@@ -212,26 +201,36 @@ func (tm *TopologyMatch) Filter(ctx context.Context, cycleState *framework.Cycle
212
201
213
202
lh .V (4 ).Info ("found nrt data" , "object" , stringify .NodeResourceTopologyResources (nodeTopology ), "conf" , conf .String ())
214
203
215
- handler := filterHandlerFromTopologyManager (conf )
204
+ handler , boundary := filterHandlerFromTopologyManager (conf )
216
205
if handler == nil {
217
206
return nil
218
207
}
219
- status := handler (lh , pod , nodeTopology .Zones , nodeInfo )
208
+
209
+ numaNodes := createNUMANodeList (lh , nodeTopology .Zones )
210
+ lh .V (4 ).Info ("aligning resources" , "boundary" , boundary , "numaCells" , len (numaNodes ))
211
+ fi := filterInfo {
212
+ nodeName : nodeName ,
213
+ node : nodeInfo ,
214
+ topologyManager : conf ,
215
+ qos : qos ,
216
+ numaNodes : numaNodes ,
217
+ }
218
+ status := handler (lh , pod , & fi )
220
219
if status != nil {
221
220
tm .nrtCache .NodeMaybeOverReserved (nodeName , pod )
222
221
}
223
222
return status
224
223
}
225
224
226
- func filterHandlerFromTopologyManager (conf nodeconfig.TopologyManager ) filterFn {
225
+ func filterHandlerFromTopologyManager (conf nodeconfig.TopologyManager ) ( filterFn , string ) {
227
226
if conf .Policy != kubeletconfig .SingleNumaNodeTopologyManagerPolicy {
228
- return nil
227
+ return nil , ""
229
228
}
230
229
if conf .Scope == kubeletconfig .PodTopologyManagerScope {
231
- return singleNUMAPodLevelHandler
230
+ return singleNUMAPodLevelHandler , "pod"
232
231
}
233
232
if conf .Scope == kubeletconfig .ContainerTopologyManagerScope {
234
- return singleNUMAContainerLevelHandler
233
+ return singleNUMAContainerLevelHandler , "container"
235
234
}
236
- return nil // cannot happen
235
+ return nil , "" // cannot happen
237
236
}
0 commit comments