@@ -160,6 +160,22 @@ func podMatchesAllAffinityTerms(pod *v1.Pod, terms []framework.AffinityTerm) boo
160
160
return true
161
161
}
162
162
163
+ // getMatchingAntiAffinityTopologyPairs calculates the following for "existingPod" on given node:
164
+ // (1) Whether it has PodAntiAffinity
165
+ // (2) Whether ANY AffinityTerm matches the incoming pod
166
+ func getMatchingAntiAffinityTopologyPairsOfPod (newPod * v1.Pod , existingPod * framework.PodInfo , node * v1.Node ) topologyToMatchedTermCount {
167
+ topologyMap := make (topologyToMatchedTermCount )
168
+ for _ , term := range existingPod .RequiredAntiAffinityTerms {
169
+ if schedutil .PodMatchesTermsNamespaceAndSelector (newPod , term .Namespaces , term .Selector ) {
170
+ if topologyValue , ok := node .Labels [term .TopologyKey ]; ok {
171
+ pair := topologyPair {key : term .TopologyKey , value : topologyValue }
172
+ topologyMap [pair ]++
173
+ }
174
+ }
175
+ }
176
+ return topologyMap
177
+ }
178
+
163
179
// getTPMapMatchingExistingAntiAffinity calculates the following for each existing pod on each node:
164
180
// (1) Whether it has PodAntiAffinity
165
181
// (2) Whether any AffinityTerm matches the incoming pod
@@ -314,89 +330,61 @@ func getPreFilterState(cycleState *framework.CycleState) (*preFilterState, error
314
330
315
331
// Checks if scheduling the pod onto this node would break any anti-affinity
316
332
// terms indicated by the existing pods.
317
- func (pl * InterPodAffinity ) satisfiesExistingPodsAntiAffinity (pod * v1.Pod , state * preFilterState , nodeInfo * framework.NodeInfo ) (bool , error ) {
318
- node := nodeInfo .Node ()
319
- topologyMap := state .topologyToMatchedExistingAntiAffinityTerms
320
-
321
- // Iterate over topology pairs to get any of the pods being affected by
322
- // the scheduled pod anti-affinity terms
323
- for topologyKey , topologyValue := range node .Labels {
324
- if topologyMap [topologyPair {key : topologyKey , value : topologyValue }] > 0 {
325
- klog .V (10 ).Infof ("Cannot schedule pod %+v onto node %v" , pod .Name , node .Name )
326
- return false , nil
327
- }
328
- }
329
- return true , nil
330
- }
331
-
332
- // nodeMatchesAllAffinityTerms checks whether "nodeInfo" matches all affinity terms of the incoming pod.
333
- func nodeMatchesAllAffinityTerms (nodeInfo * framework.NodeInfo , state * preFilterState ) bool {
334
- node := nodeInfo .Node ()
335
- for _ , term := range state .podInfo .RequiredAffinityTerms {
336
- if topologyValue , ok := node .Labels [term .TopologyKey ]; ok {
337
- pair := topologyPair {key : term .TopologyKey , value : topologyValue }
338
- if state .topologyToMatchedAffinityTerms [pair ] <= 0 {
333
+ func satisfyExistingPodsAntiAffinity (state * preFilterState , nodeInfo * framework.NodeInfo ) bool {
334
+ if len (state .topologyToMatchedExistingAntiAffinityTerms ) > 0 {
335
+ // Iterate over topology pairs to get any of the pods being affected by
336
+ // the scheduled pod anti-affinity terms
337
+ for topologyKey , topologyValue := range nodeInfo .Node ().Labels {
338
+ tp := topologyPair {key : topologyKey , value : topologyValue }
339
+ if state .topologyToMatchedExistingAntiAffinityTerms [tp ] > 0 {
339
340
return false
340
341
}
341
- } else {
342
- return false
343
342
}
344
343
}
345
344
return true
346
345
}
347
346
348
- // nodeMatchesAnyTopologyTerm checks whether "nodeInfo" matches any of the pod's anti affinity terms.
349
- func nodeMatchesAnyAntiAffinityTerm (nodeInfo * framework.NodeInfo , state * preFilterState ) bool {
350
- node := nodeInfo .Node ()
347
+ // Checks if the node satisifies the incoming pod's anti-affinity rules.
348
+ func satisfyPodAntiAffinity (state * preFilterState , nodeInfo * framework.NodeInfo ) bool {
351
349
for _ , term := range state .podInfo .RequiredAntiAffinityTerms {
352
- if topologyValue , ok := node .Labels [term .TopologyKey ]; ok {
353
- pair := topologyPair {key : term .TopologyKey , value : topologyValue }
354
- if state .topologyToMatchedAntiAffinityTerms [pair ] > 0 {
355
- return true
350
+ if topologyValue , ok := nodeInfo . Node () .Labels [term .TopologyKey ]; ok {
351
+ tp := topologyPair {key : term .TopologyKey , value : topologyValue }
352
+ if state .topologyToMatchedAntiAffinityTerms [tp ] > 0 {
353
+ return false
356
354
}
357
355
}
358
356
}
359
- return false
357
+ return true
360
358
}
361
359
362
- // getMatchingAntiAffinityTopologyPairs calculates the following for "existingPod" on given node:
363
- // (1) Whether it has PodAntiAffinity
364
- // (2) Whether ANY AffinityTerm matches the incoming pod
365
- func getMatchingAntiAffinityTopologyPairsOfPod (newPod * v1.Pod , existingPod * framework.PodInfo , node * v1.Node ) topologyToMatchedTermCount {
366
- topologyMap := make (topologyToMatchedTermCount )
367
- for _ , term := range existingPod .RequiredAntiAffinityTerms {
368
- if schedutil .PodMatchesTermsNamespaceAndSelector (newPod , term .Namespaces , term .Selector ) {
369
- if topologyValue , ok := node .Labels [term .TopologyKey ]; ok {
370
- pair := topologyPair {key : term .TopologyKey , value : topologyValue }
371
- topologyMap [pair ]++
360
+ // Checks if the node satisfies the incoming pod's affinity rules.
361
+ func satisfyPodAffinity (state * preFilterState , nodeInfo * framework.NodeInfo ) bool {
362
+ podsExist := true
363
+ for _ , term := range state .podInfo .RequiredAffinityTerms {
364
+ if topologyValue , ok := nodeInfo .Node ().Labels [term .TopologyKey ]; ok {
365
+ tp := topologyPair {key : term .TopologyKey , value : topologyValue }
366
+ if state .topologyToMatchedAffinityTerms [tp ] <= 0 {
367
+ podsExist = false
372
368
}
369
+ } else {
370
+ // All topology labels must exist on the node.
371
+ return false
373
372
}
374
373
}
375
- return topologyMap
376
- }
377
374
378
- // satisfiesPodsAffinityAntiAffinity checks if scheduling the pod onto this node would break any term of this pod.
379
- // This function returns two boolean flags. The first boolean flag indicates whether the pod matches affinity rules
380
- // or not. The second boolean flag indicates if the pod matches anti-affinity rules.
381
- func (pl * InterPodAffinity ) satisfiesPodsAffinityAntiAffinity (state * preFilterState , nodeInfo * framework.NodeInfo ) (bool , bool , error ) {
382
- // Check all affinity terms.
383
- if ! nodeMatchesAllAffinityTerms (nodeInfo , state ) {
375
+ if ! podsExist {
384
376
// This pod may be the first pod in a series that have affinity to themselves. In order
385
377
// to not leave such pods in pending state forever, we check that if no other pod
386
- // in the cluster matches the namespace and selector of this pod and the pod matches
387
- // its own terms, then we allow the pod to pass the affinity check.
378
+ // in the cluster matches the namespace and selector of this pod, the pod matches
379
+ // its own terms, and the node has all the requested topologies, then we allow the pod
380
+ // to pass the affinity check.
388
381
podInfo := state .podInfo
389
- if len (state .topologyToMatchedAffinityTerms ) != 0 || ! podMatchesAllAffinityTerms (podInfo .Pod , podInfo .RequiredAffinityTerms ) {
390
- return false , false , nil
382
+ if len (state .topologyToMatchedAffinityTerms ) == 0 && podMatchesAllAffinityTerms (podInfo .Pod , podInfo .RequiredAffinityTerms ) {
383
+ return true
391
384
}
385
+ return false
392
386
}
393
-
394
- // Check all anti-affinity terms.
395
- if nodeMatchesAnyAntiAffinityTerm (nodeInfo , state ) {
396
- return true , false , nil
397
- }
398
-
399
- return true , true , nil
387
+ return true
400
388
}
401
389
402
390
// Filter invoked at the filter extension point.
@@ -411,25 +399,17 @@ func (pl *InterPodAffinity) Filter(ctx context.Context, cycleState *framework.Cy
411
399
return framework .NewStatus (framework .Error , err .Error ())
412
400
}
413
401
414
- if s , err := pl .satisfiesExistingPodsAntiAffinity (pod , state , nodeInfo ); ! s || err != nil {
415
- if err != nil {
416
- return framework .NewStatus (framework .Error , err .Error ())
417
- }
418
- return framework .NewStatus (framework .Unschedulable , ErrReasonAffinityNotMatch , ErrReasonExistingAntiAffinityRulesNotMatch )
402
+ if ! satisfyPodAffinity (state , nodeInfo ) {
403
+ return framework .NewStatus (framework .UnschedulableAndUnresolvable , ErrReasonAffinityNotMatch , ErrReasonAffinityRulesNotMatch )
419
404
}
420
405
421
- // Now check if <pod> requirements will be satisfied on this node.
422
- if satisfiesAffinity , satisfiesAntiAffinity , err := pl .satisfiesPodsAffinityAntiAffinity (state , nodeInfo ); err != nil || ! satisfiesAffinity || ! satisfiesAntiAffinity {
423
- if err != nil {
424
- return framework .NewStatus (framework .Error , err .Error ())
425
- }
426
-
427
- if ! satisfiesAffinity {
428
- return framework .NewStatus (framework .UnschedulableAndUnresolvable , ErrReasonAffinityNotMatch , ErrReasonAffinityRulesNotMatch )
429
- }
430
-
406
+ if ! satisfyPodAntiAffinity (state , nodeInfo ) {
431
407
return framework .NewStatus (framework .Unschedulable , ErrReasonAffinityNotMatch , ErrReasonAntiAffinityRulesNotMatch )
432
408
}
433
409
410
+ if ! satisfyExistingPodsAntiAffinity (state , nodeInfo ) {
411
+ return framework .NewStatus (framework .Unschedulable , ErrReasonAffinityNotMatch , ErrReasonExistingAntiAffinityRulesNotMatch )
412
+ }
413
+
434
414
return nil
435
415
}
0 commit comments