Change:
Spin-off from What would you like to be : Use maxSkew in TopologySpreadingContraint to affect relative weight of the constraint. Exact formula to be discussed. Some ideas: , intuitive but too coarse-grained at low numbers. Goes: 100%, 50%, 33%, 25%, 20% some linearity. For , goes: 100%, 66%, 50%, 40%, 33% . For , goes: 100%, 75%, 60%, 50%, 42% . Goes: 100%, 70%, 57%, 50%, 44% Why is this needed: When using for , it will be useful for operators to control how strong the constraints should be compared to explicit user requests. Pods would be able to control the weight of constraints per-topology.
/sig scheduling
1 maybe the most compatible option with the current zone:node ratio (2:1):
Not quite. The ratio is correct, but the weight is different. original: prop 1:
I realized that using as weight is quite counterintuitive. Instead, I propose that we use to water down the counts per topology. This way, the behavior still doesn't change for . But as increases, counts become more similar. For example, given the counts and , we get the new counts: . Then we proceed with the counts normalization as usual. Note that when the minimum count is zero in a topology, this procedure has the effect of giving the max score (100) for nodes (or zones) that would satisfy the condition. That won't be true when the minimum count is not zero, but enforcing it would be quite costly. This proposal still gets us closer to that and reduce score differentiation among nodes within the skew. When using constraints against multiple topologies, another side effect is that topologies with bigger would have a reduced effect in the overall score.
That sounds better than the initial proposal which seemed to deviate from the original semantics of the API.
WDYT ?
Sounds good to me. Per constraint on large-scope topology (e.g., zone), I assume it will still be credited with the matching number on its sub topologies (e.g., node), right? (It's just we're using the newCount formula - by taking the maxSkew specified on its constraint into consideration.)
Note that this doesn't replace increasing the weight as described in the parent issue. I think the issue title needs updating.
Understood. Default weight is tracked in another issue. This one talks about Scoring.
Right, just wanted to explicitly mention that to clarify the overall plan since this issue started in the context of increasing the default weight :)
Could you rename that one and clarify that it depends on this issue being resolved first?
can you clarify why that issue is dependent on this one? aren't we going to increase the weight regardless?
I was referring to . But you are right, it doesn't depend on this. kubernetes/enhancements does

Discussion:
pair := topologyPair{key: c.TopologyKey, value: tpVal} cnt = *s.TopologyPairToPodCounts[pair] } <ins> cnt = adjustForMaxSkew(cnt, int64(c.MaxSkew)) </ins> score += float64(cnt) * s.TopologyNormalizingWeight[i] } }

func topologyNormalizingWeight(size int) float64 { return math.Log(float64(size + 2)) } <ins> // adjustForMaxSkew adjusts the number of matching pods in a topology domain // using the constraint's maxSkew. // Topology domains with less than maxSkew number of pods are considered to have // the same priority. func adjustForMaxSkew(cnt, maxSkew int64) int64 { if cnt < maxSkew { return maxSkew - 1 } return cnt } </ins>

}, }, { <ins> // matching pods spread as 2/1/0/3. // With maxSkew=2, counts change internally to 2/1/1/3. name: "one constraint on node, all 4 nodes are candidates, maxSkew=2", pod: st.MakePod().Name("p").Label("foo", ""). SpreadConstraint(2, v1.LabelHostname, v1.ScheduleAnyway, st.MakeLabelSelector().Exists("foo").Obj()). Obj(), existingPods: []*v1.Pod{ st.MakePod().Name("p-a1").Node("node-a").Label("foo", "").Obj(), st.MakePod().Name("p-a2").Node("node-a").Label("foo", "").Obj(), st.MakePod().Name("p-b1").Node("node-b").Label("foo", "").Obj(), st.MakePod().Name("p-d1").Node("node-d").Label("foo", "").Obj(), st.MakePod().Name("p-d2").Node("node-d").Label("foo", "").Obj(), st.MakePod().Name("p-d3").Node("node-d").Label("foo", "").Obj(), }, nodes: []*v1.Node{ st.MakeNode().Name("node-a").Label(v1.LabelHostname, "node-a").Obj(), st.MakeNode().Name("node-b").Label(v1.LabelHostname, "node-b").Obj(), st.MakeNode().Name("node-c").Label(v1.LabelHostname, "node-c").Obj(), st.MakeNode().Name("node-d").Label(v1.LabelHostname, "node-d").Obj(), }, failedNodes: []*v1.Node{}, want: []framework.NodeScore{ {Name: "node-a", Score: 60},  // +20, compared to maxSkew=1 {Name: "node-b", Score: 100}, // +20, compared to maxSkew=1 {Name: "node-c", Score: 100}, {Name: "node-d", Score: 20}, // +20, compared to maxSkew=1 }, }, { // matching pods spread as 4/3/2/1. // With maxSkew=3, counts change internally to 4/3/2/2. name: "one constraint on node, all 4 nodes are candidates, maxSkew=3", pod: st.MakePod().Name("p").Label("foo", ""). SpreadConstraint(3, v1.LabelHostname, v1.ScheduleAnyway, st.MakeLabelSelector().Exists("foo").Obj()). Obj(), existingPods: []*v1.Pod{ st.MakePod().Name("p-a1").Node("node-a").Label("foo", "").Obj(), st.MakePod().Name("p-a2").Node("node-a").Label("foo", "").Obj(), st.MakePod().Name("p-a3").Node("node-a").Label("foo", "").Obj(), st.MakePod().Name("p-a4").Node("node-a").Label("foo", "").Obj(), st.MakePod().Name("p-b1").Node("node-b").Label("foo", "").Obj(), st.MakePod().Name("p-b2").Node("node-b").Label("foo", "").Obj(), st.MakePod().Name("p-b3").Node("node-b").Label("foo", "").Obj(), st.MakePod().Name("p-c1").Node("node-c").Label("foo", "").Obj(), st.MakePod().Name("p-c2").Node("node-c").Label("foo", "").Obj(), st.MakePod().Name("p-d1").Node("node-d").Label("foo", "").Obj(), }, nodes: []*v1.Node{ st.MakeNode().Name("node-a").Label(v1.LabelHostname, "node-a").Obj(), st.MakeNode().Name("node-b").Label(v1.LabelHostname, "node-b").Obj(), st.MakeNode().Name("node-c").Label(v1.LabelHostname, "node-c").Obj(), st.MakeNode().Name("node-d").Label(v1.LabelHostname, "node-d").Obj(), }, failedNodes: []*v1.Node{}, want: []framework.NodeScore{ {Name: "node-a", Score: 42},  // +28 compared to maxSkew=1 {Name: "node-b", Score: 71},  // +29 compared to maxSkew=1 {Name: "node-c", Score: 100}, // +29 compared to maxSkew=1 {Name: "node-d", Score: 100}, }, }, { </ins> // matching pods spread as 4/2/1/~3~ (node4 is not a candidate) name: "one constraint on node, 3 out of 4 nodes are candidates", pod: st.MakePod().Name("p").Label("foo", "").