Follow-up to #1214 / #1215. While fixing the weightSum == 0 divide-by-zero in the score strategies, three related scoring behaviors surfaced when a container or scope contributes no aligned resource. They are distinct from the panic fix and are filed separately so #1215 stays a focused bug fix. Each was verified on current main.
1. Native pod-scope scores 0 for every node (inconsistent with native container-scope)
podScopeScore (pkg/scheduler/plugins/noderesourcetopology/score.go:189) scores with nativeAlignedResources, an empty but non-nil set (plugin.go:46, var nativeAlignedResources = sets.NewString()). The score strategies skip a resource when alignedResource != nil && !alignedResource.Has(...), so an empty non-nil set skips every requested resource, weightSum is 0, and the node score is 0 for all nodes.
The native container-scope path passes nil instead (score.go:112, containerScopeScore(..., nil)), which does score all resources. So a native pod on a SingleNUMANodePodLevel node scores 0 everywhere, while the same pod on a SingleNUMANodeContainerLevel node scores normally. This looks unintended; podScopeScore likely should pass nil too. (Before #1215 this path panicked rather than returning 0.)
Verified: mostAllocatedScoreStrategy({cpu:2}, {cpu:4}, {}, sets.NewString()) returns 0 (same for least).
2. A container with no aligned resource dilutes the container-scope mean
containerScopeScore (score.go:164-175) scores every container in append(InitContainers, Containers...) and returns int64(stat.Mean(contScore, nil)). A container with no aligned resource now scores 0 (after #1215) and that 0 is averaged in, so an init container with no requests pulls a node from 3 to mean([0,3]) = 1. "No scoring signal" and "lowest score" are currently the same 0.
Worth deciding whether a no-signal container should be excluded from the mean, or given a neutral contribution.
Verified: stat.Mean([0,3]) = 1.5 -> int64 1.
3. BalancedAllocation returns MinInt64 for an empty aligned-resource set
balanced_allocation.go builds resourceFractions per aligned resource and returns int64((1 - stat.Variance(resourceFractions, nil)) * MaxNodeScore) (:44, :49). When no aligned resource contributes, resourceFractions is empty, stat.Variance returns NaN, and int64((1 - NaN) * 100) is -9223372036854775808. This is a garbage score rather than a value in [0, MaxNodeScore]. The weightSum == 0 guard from #1215 does not cover this strategy, since it does not divide by weightSum.
Suggested: guard the empty fraction list before Variance and return a neutral score.
Verified: stat.Variance([]) = NaN, int64((1-NaN)*100) = -9223372036854775808.
Follow-up to #1214 / #1215. While fixing the
weightSum == 0divide-by-zero in the score strategies, three related scoring behaviors surfaced when a container or scope contributes no aligned resource. They are distinct from the panic fix and are filed separately so #1215 stays a focused bug fix. Each was verified on current main.1. Native pod-scope scores 0 for every node (inconsistent with native container-scope)
podScopeScore(pkg/scheduler/plugins/noderesourcetopology/score.go:189) scores withnativeAlignedResources, an empty but non-nil set (plugin.go:46,var nativeAlignedResources = sets.NewString()). The score strategies skip a resource whenalignedResource != nil && !alignedResource.Has(...), so an empty non-nil set skips every requested resource,weightSumis 0, and the node score is 0 for all nodes.The native container-scope path passes
nilinstead (score.go:112,containerScopeScore(..., nil)), which does score all resources. So a native pod on aSingleNUMANodePodLevelnode scores 0 everywhere, while the same pod on aSingleNUMANodeContainerLevelnode scores normally. This looks unintended;podScopeScorelikely should passniltoo. (Before #1215 this path panicked rather than returning 0.)Verified:
mostAllocatedScoreStrategy({cpu:2}, {cpu:4}, {}, sets.NewString())returns0(same for least).2. A container with no aligned resource dilutes the container-scope mean
containerScopeScore(score.go:164-175) scores every container inappend(InitContainers, Containers...)and returnsint64(stat.Mean(contScore, nil)). A container with no aligned resource now scores 0 (after #1215) and that 0 is averaged in, so an init container with no requests pulls a node from 3 tomean([0,3]) = 1. "No scoring signal" and "lowest score" are currently the same 0.Worth deciding whether a no-signal container should be excluded from the mean, or given a neutral contribution.
Verified:
stat.Mean([0,3]) = 1.5 -> int64 1.3. BalancedAllocation returns MinInt64 for an empty aligned-resource set
balanced_allocation.gobuildsresourceFractionsper aligned resource and returnsint64((1 - stat.Variance(resourceFractions, nil)) * MaxNodeScore)(:44,:49). When no aligned resource contributes,resourceFractionsis empty,stat.VariancereturnsNaN, andint64((1 - NaN) * 100)is-9223372036854775808. This is a garbage score rather than a value in[0, MaxNodeScore]. TheweightSum == 0guard from #1215 does not cover this strategy, since it does not divide byweightSum.Suggested: guard the empty fraction list before
Varianceand return a neutral score.Verified:
stat.Variance([]) = NaN,int64((1-NaN)*100) = -9223372036854775808.