mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-24 04:06:03 +00:00
Merge pull request #90475 from alculquicondor/topology-scoring
Topology spreading scoring with automatically weighted topologies
This commit is contained in:
commit
ba43630708
@ -39,6 +39,10 @@ type preScoreState struct {
|
|||||||
IgnoredNodes sets.String
|
IgnoredNodes sets.String
|
||||||
// TopologyPairToPodCounts is keyed with topologyPair, and valued with the number of matching pods.
|
// TopologyPairToPodCounts is keyed with topologyPair, and valued with the number of matching pods.
|
||||||
TopologyPairToPodCounts map[topologyPair]*int64
|
TopologyPairToPodCounts map[topologyPair]*int64
|
||||||
|
// TopologyNormalizingWeight is the weight we give to the counts per topology.
|
||||||
|
// This allows the pod counts of smaller topologies to not be watered down by
|
||||||
|
// bigger ones.
|
||||||
|
TopologyNormalizingWeight []float64
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clone implements the mandatory Clone interface. We don't really copy the data since
|
// Clone implements the mandatory Clone interface. We don't really copy the data since
|
||||||
@ -51,6 +55,7 @@ func (s *preScoreState) Clone() framework.StateData {
|
|||||||
// don't have required topologyKey(s), and initialize:
|
// don't have required topologyKey(s), and initialize:
|
||||||
// 1) s.TopologyPairToPodCounts: keyed with both eligible topology pair and node names.
|
// 1) s.TopologyPairToPodCounts: keyed with both eligible topology pair and node names.
|
||||||
// 2) s.IgnoredNodes: the set of nodes that shouldn't be scored.
|
// 2) s.IgnoredNodes: the set of nodes that shouldn't be scored.
|
||||||
|
// 3) s.TopologyNormalizingWeight: The weight to be given to each constraint based on the number of values in a topology.
|
||||||
func (pl *PodTopologySpread) initPreScoreState(s *preScoreState, pod *v1.Pod, filteredNodes []*v1.Node) error {
|
func (pl *PodTopologySpread) initPreScoreState(s *preScoreState, pod *v1.Pod, filteredNodes []*v1.Node) error {
|
||||||
var err error
|
var err error
|
||||||
if len(pod.Spec.TopologySpreadConstraints) > 0 {
|
if len(pod.Spec.TopologySpreadConstraints) > 0 {
|
||||||
@ -67,6 +72,7 @@ func (pl *PodTopologySpread) initPreScoreState(s *preScoreState, pod *v1.Pod, fi
|
|||||||
if len(s.Constraints) == 0 {
|
if len(s.Constraints) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
topoSize := make([]int, len(s.Constraints))
|
||||||
for _, node := range filteredNodes {
|
for _, node := range filteredNodes {
|
||||||
if !nodeLabelsMatchSpreadConstraints(node.Labels, s.Constraints) {
|
if !nodeLabelsMatchSpreadConstraints(node.Labels, s.Constraints) {
|
||||||
// Nodes which don't have all required topologyKeys present are ignored
|
// Nodes which don't have all required topologyKeys present are ignored
|
||||||
@ -74,7 +80,7 @@ func (pl *PodTopologySpread) initPreScoreState(s *preScoreState, pod *v1.Pod, fi
|
|||||||
s.IgnoredNodes.Insert(node.Name)
|
s.IgnoredNodes.Insert(node.Name)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
for _, constraint := range s.Constraints {
|
for i, constraint := range s.Constraints {
|
||||||
// per-node counts are calculated during Score.
|
// per-node counts are calculated during Score.
|
||||||
if constraint.TopologyKey == v1.LabelHostname {
|
if constraint.TopologyKey == v1.LabelHostname {
|
||||||
continue
|
continue
|
||||||
@ -82,9 +88,19 @@ func (pl *PodTopologySpread) initPreScoreState(s *preScoreState, pod *v1.Pod, fi
|
|||||||
pair := topologyPair{key: constraint.TopologyKey, value: node.Labels[constraint.TopologyKey]}
|
pair := topologyPair{key: constraint.TopologyKey, value: node.Labels[constraint.TopologyKey]}
|
||||||
if s.TopologyPairToPodCounts[pair] == nil {
|
if s.TopologyPairToPodCounts[pair] == nil {
|
||||||
s.TopologyPairToPodCounts[pair] = new(int64)
|
s.TopologyPairToPodCounts[pair] = new(int64)
|
||||||
|
topoSize[i]++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s.TopologyNormalizingWeight = make([]float64, len(s.Constraints))
|
||||||
|
for i, c := range s.Constraints {
|
||||||
|
sz := topoSize[i]
|
||||||
|
if c.TopologyKey == v1.LabelHostname {
|
||||||
|
sz = len(filteredNodes) - len(s.IgnoredNodes)
|
||||||
|
}
|
||||||
|
s.TopologyNormalizingWeight[i] = topologyNormalizingWeight(sz)
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,20 +190,20 @@ func (pl *PodTopologySpread) Score(ctx context.Context, cycleState *framework.Cy
|
|||||||
|
|
||||||
// For each present <pair>, current node gets a credit of <matchSum>.
|
// For each present <pair>, current node gets a credit of <matchSum>.
|
||||||
// And we sum up <matchSum> and return it as this node's score.
|
// And we sum up <matchSum> and return it as this node's score.
|
||||||
var score int64
|
var score float64
|
||||||
for _, c := range s.Constraints {
|
for i, c := range s.Constraints {
|
||||||
if tpVal, ok := node.Labels[c.TopologyKey]; ok {
|
if tpVal, ok := node.Labels[c.TopologyKey]; ok {
|
||||||
|
var cnt int64
|
||||||
if c.TopologyKey == v1.LabelHostname {
|
if c.TopologyKey == v1.LabelHostname {
|
||||||
count := countPodsMatchSelector(nodeInfo.Pods, c.Selector, pod.Namespace)
|
cnt = int64(countPodsMatchSelector(nodeInfo.Pods, c.Selector, pod.Namespace))
|
||||||
score += int64(count)
|
|
||||||
} else {
|
} else {
|
||||||
pair := topologyPair{key: c.TopologyKey, value: tpVal}
|
pair := topologyPair{key: c.TopologyKey, value: tpVal}
|
||||||
matchSum := *s.TopologyPairToPodCounts[pair]
|
cnt = *s.TopologyPairToPodCounts[pair]
|
||||||
score += matchSum
|
}
|
||||||
|
score += float64(cnt) * s.TopologyNormalizingWeight[i]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
return int64(score), nil
|
||||||
return score, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NormalizeScore invoked after scoring all nodes.
|
// NormalizeScore invoked after scoring all nodes.
|
||||||
@ -200,21 +216,22 @@ func (pl *PodTopologySpread) NormalizeScore(ctx context.Context, cycleState *fra
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate the summed <total> score and <minScore>.
|
// Calculate <minScore> and <maxScore>
|
||||||
var minScore int64 = math.MaxInt64
|
var minScore int64 = math.MaxInt64
|
||||||
var total int64
|
var maxScore int64
|
||||||
for _, score := range scores {
|
for _, score := range scores {
|
||||||
// it's mandatory to check if <score.Name> is present in m.IgnoredNodes
|
// it's mandatory to check if <score.Name> is present in m.IgnoredNodes
|
||||||
if s.IgnoredNodes.Has(score.Name) {
|
if s.IgnoredNodes.Has(score.Name) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
total += score.Score
|
|
||||||
if score.Score < minScore {
|
if score.Score < minScore {
|
||||||
minScore = score.Score
|
minScore = score.Score
|
||||||
}
|
}
|
||||||
|
if score.Score > maxScore {
|
||||||
|
maxScore = score.Score
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
maxMinDiff := total - minScore
|
|
||||||
for i := range scores {
|
for i := range scores {
|
||||||
nodeInfo, err := pl.sharedLister.NodeInfos().Get(scores[i].Name)
|
nodeInfo, err := pl.sharedLister.NodeInfos().Get(scores[i].Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -222,19 +239,18 @@ func (pl *PodTopologySpread) NormalizeScore(ctx context.Context, cycleState *fra
|
|||||||
}
|
}
|
||||||
node := nodeInfo.Node()
|
node := nodeInfo.Node()
|
||||||
|
|
||||||
if maxMinDiff == 0 {
|
|
||||||
scores[i].Score = framework.MaxNodeScore
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if s.IgnoredNodes.Has(node.Name) {
|
if s.IgnoredNodes.Has(node.Name) {
|
||||||
scores[i].Score = 0
|
scores[i].Score = 0
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
flippedScore := total - scores[i].Score
|
if maxScore == 0 {
|
||||||
fScore := float64(framework.MaxNodeScore) * (float64(flippedScore) / float64(maxMinDiff))
|
scores[i].Score = framework.MaxNodeScore
|
||||||
scores[i].Score = int64(fScore)
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
s := scores[i].Score
|
||||||
|
scores[i].Score = framework.MaxNodeScore * (maxScore + minScore - s) / maxScore
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -256,3 +272,16 @@ func getPreScoreState(cycleState *framework.CycleState) (*preScoreState, error)
|
|||||||
}
|
}
|
||||||
return s, nil
|
return s, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// topologyNormalizingWeight calculates the weight for the topology, based on
|
||||||
|
// the number of values that exist for a topology.
|
||||||
|
// Since <size> is at least 1 (all nodes that passed the Filters are in the
|
||||||
|
// same topology), and k8s supports 5k nodes, the result is in the interval
|
||||||
|
// <1.09, 8.52>.
|
||||||
|
//
|
||||||
|
// Note: <size> could also be zero when no nodes have the required topologies,
|
||||||
|
// however we don't care about topology weight in this case as we return a 0
|
||||||
|
// score for all nodes.
|
||||||
|
func topologyNormalizingWeight(size int) float64 {
|
||||||
|
return math.Log(float64(size + 2))
|
||||||
|
}
|
||||||
|
@ -48,12 +48,12 @@ func TestPreScoreStateEmptyNodes(t *testing.T) {
|
|||||||
name: "normal case",
|
name: "normal case",
|
||||||
pod: st.MakePod().Name("p").Label("foo", "").
|
pod: st.MakePod().Name("p").Label("foo", "").
|
||||||
SpreadConstraint(1, "zone", v1.ScheduleAnyway, st.MakeLabelSelector().Exists("foo").Obj()).
|
SpreadConstraint(1, "zone", v1.ScheduleAnyway, st.MakeLabelSelector().Exists("foo").Obj()).
|
||||||
SpreadConstraint(1, "node", v1.ScheduleAnyway, st.MakeLabelSelector().Exists("foo").Obj()).
|
SpreadConstraint(1, v1.LabelHostname, v1.ScheduleAnyway, st.MakeLabelSelector().Exists("foo").Obj()).
|
||||||
Obj(),
|
Obj(),
|
||||||
nodes: []*v1.Node{
|
nodes: []*v1.Node{
|
||||||
st.MakeNode().Name("node-a").Label("zone", "zone1").Label("node", "node-a").Obj(),
|
st.MakeNode().Name("node-a").Label("zone", "zone1").Label(v1.LabelHostname, "node-a").Obj(),
|
||||||
st.MakeNode().Name("node-b").Label("zone", "zone1").Label("node", "node-b").Obj(),
|
st.MakeNode().Name("node-b").Label("zone", "zone1").Label(v1.LabelHostname, "node-b").Obj(),
|
||||||
st.MakeNode().Name("node-x").Label("zone", "zone2").Label("node", "node-x").Obj(),
|
st.MakeNode().Name("node-x").Label("zone", "zone2").Label(v1.LabelHostname, "node-x").Obj(),
|
||||||
},
|
},
|
||||||
want: &preScoreState{
|
want: &preScoreState{
|
||||||
Constraints: []topologySpreadConstraint{
|
Constraints: []topologySpreadConstraint{
|
||||||
@ -64,7 +64,7 @@ func TestPreScoreStateEmptyNodes(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
MaxSkew: 1,
|
MaxSkew: 1,
|
||||||
TopologyKey: "node",
|
TopologyKey: v1.LabelHostname,
|
||||||
Selector: mustConvertLabelSelectorAsSelector(t, st.MakeLabelSelector().Exists("foo").Obj()),
|
Selector: mustConvertLabelSelectorAsSelector(t, st.MakeLabelSelector().Exists("foo").Obj()),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -72,22 +72,20 @@ func TestPreScoreStateEmptyNodes(t *testing.T) {
|
|||||||
TopologyPairToPodCounts: map[topologyPair]*int64{
|
TopologyPairToPodCounts: map[topologyPair]*int64{
|
||||||
{key: "zone", value: "zone1"}: pointer.Int64Ptr(0),
|
{key: "zone", value: "zone1"}: pointer.Int64Ptr(0),
|
||||||
{key: "zone", value: "zone2"}: pointer.Int64Ptr(0),
|
{key: "zone", value: "zone2"}: pointer.Int64Ptr(0),
|
||||||
{key: "node", value: "node-a"}: pointer.Int64Ptr(0),
|
|
||||||
{key: "node", value: "node-b"}: pointer.Int64Ptr(0),
|
|
||||||
{key: "node", value: "node-x"}: pointer.Int64Ptr(0),
|
|
||||||
},
|
},
|
||||||
|
TopologyNormalizingWeight: []float64{topologyNormalizingWeight(2), topologyNormalizingWeight(3)},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "node-x doesn't have label zone",
|
name: "node-x doesn't have label zone",
|
||||||
pod: st.MakePod().Name("p").Label("foo", "").
|
pod: st.MakePod().Name("p").Label("foo", "").
|
||||||
SpreadConstraint(1, "zone", v1.ScheduleAnyway, st.MakeLabelSelector().Exists("foo").Obj()).
|
SpreadConstraint(1, "zone", v1.ScheduleAnyway, st.MakeLabelSelector().Exists("foo").Obj()).
|
||||||
SpreadConstraint(1, "node", v1.ScheduleAnyway, st.MakeLabelSelector().Exists("bar").Obj()).
|
SpreadConstraint(1, v1.LabelHostname, v1.ScheduleAnyway, st.MakeLabelSelector().Exists("bar").Obj()).
|
||||||
Obj(),
|
Obj(),
|
||||||
nodes: []*v1.Node{
|
nodes: []*v1.Node{
|
||||||
st.MakeNode().Name("node-a").Label("zone", "zone1").Label("node", "node-a").Obj(),
|
st.MakeNode().Name("node-a").Label("zone", "zone1").Label(v1.LabelHostname, "node-a").Obj(),
|
||||||
st.MakeNode().Name("node-b").Label("zone", "zone1").Label("node", "node-b").Obj(),
|
st.MakeNode().Name("node-b").Label("zone", "zone1").Label(v1.LabelHostname, "node-b").Obj(),
|
||||||
st.MakeNode().Name("node-x").Label("node", "node-x").Obj(),
|
st.MakeNode().Name("node-x").Label(v1.LabelHostname, "node-x").Obj(),
|
||||||
},
|
},
|
||||||
want: &preScoreState{
|
want: &preScoreState{
|
||||||
Constraints: []topologySpreadConstraint{
|
Constraints: []topologySpreadConstraint{
|
||||||
@ -98,28 +96,27 @@ func TestPreScoreStateEmptyNodes(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
MaxSkew: 1,
|
MaxSkew: 1,
|
||||||
TopologyKey: "node",
|
TopologyKey: v1.LabelHostname,
|
||||||
Selector: mustConvertLabelSelectorAsSelector(t, st.MakeLabelSelector().Exists("bar").Obj()),
|
Selector: mustConvertLabelSelectorAsSelector(t, st.MakeLabelSelector().Exists("bar").Obj()),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
IgnoredNodes: sets.NewString("node-x"),
|
IgnoredNodes: sets.NewString("node-x"),
|
||||||
TopologyPairToPodCounts: map[topologyPair]*int64{
|
TopologyPairToPodCounts: map[topologyPair]*int64{
|
||||||
{key: "zone", value: "zone1"}: pointer.Int64Ptr(0),
|
{key: "zone", value: "zone1"}: pointer.Int64Ptr(0),
|
||||||
{key: "node", value: "node-a"}: pointer.Int64Ptr(0),
|
|
||||||
{key: "node", value: "node-b"}: pointer.Int64Ptr(0),
|
|
||||||
},
|
},
|
||||||
|
TopologyNormalizingWeight: []float64{topologyNormalizingWeight(1), topologyNormalizingWeight(2)},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "defaults constraints and a replica set",
|
name: "defaults constraints and a replica set",
|
||||||
pod: st.MakePod().Name("p").Label("foo", "tar").Label("baz", "sup").Obj(),
|
pod: st.MakePod().Name("p").Label("foo", "tar").Label("baz", "sup").Obj(),
|
||||||
defaultConstraints: []v1.TopologySpreadConstraint{
|
defaultConstraints: []v1.TopologySpreadConstraint{
|
||||||
{MaxSkew: 1, TopologyKey: "node", WhenUnsatisfiable: v1.ScheduleAnyway},
|
{MaxSkew: 1, TopologyKey: v1.LabelHostname, WhenUnsatisfiable: v1.ScheduleAnyway},
|
||||||
{MaxSkew: 2, TopologyKey: "rack", WhenUnsatisfiable: v1.DoNotSchedule},
|
{MaxSkew: 2, TopologyKey: "rack", WhenUnsatisfiable: v1.DoNotSchedule},
|
||||||
{MaxSkew: 2, TopologyKey: "planet", WhenUnsatisfiable: v1.ScheduleAnyway},
|
{MaxSkew: 2, TopologyKey: "planet", WhenUnsatisfiable: v1.ScheduleAnyway},
|
||||||
},
|
},
|
||||||
nodes: []*v1.Node{
|
nodes: []*v1.Node{
|
||||||
st.MakeNode().Name("node-a").Label("rack", "rack1").Label("node", "node-a").Label("planet", "mars").Obj(),
|
st.MakeNode().Name("node-a").Label("rack", "rack1").Label(v1.LabelHostname, "node-a").Label("planet", "mars").Obj(),
|
||||||
},
|
},
|
||||||
objs: []runtime.Object{
|
objs: []runtime.Object{
|
||||||
&appsv1.ReplicaSet{Spec: appsv1.ReplicaSetSpec{Selector: st.MakeLabelSelector().Exists("foo").Obj()}},
|
&appsv1.ReplicaSet{Spec: appsv1.ReplicaSetSpec{Selector: st.MakeLabelSelector().Exists("foo").Obj()}},
|
||||||
@ -128,7 +125,7 @@ func TestPreScoreStateEmptyNodes(t *testing.T) {
|
|||||||
Constraints: []topologySpreadConstraint{
|
Constraints: []topologySpreadConstraint{
|
||||||
{
|
{
|
||||||
MaxSkew: 1,
|
MaxSkew: 1,
|
||||||
TopologyKey: "node",
|
TopologyKey: v1.LabelHostname,
|
||||||
Selector: mustConvertLabelSelectorAsSelector(t, st.MakeLabelSelector().Exists("foo").Obj()),
|
Selector: mustConvertLabelSelectorAsSelector(t, st.MakeLabelSelector().Exists("foo").Obj()),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -139,9 +136,9 @@ func TestPreScoreStateEmptyNodes(t *testing.T) {
|
|||||||
},
|
},
|
||||||
IgnoredNodes: sets.NewString(),
|
IgnoredNodes: sets.NewString(),
|
||||||
TopologyPairToPodCounts: map[topologyPair]*int64{
|
TopologyPairToPodCounts: map[topologyPair]*int64{
|
||||||
{key: "node", value: "node-a"}: pointer.Int64Ptr(0),
|
|
||||||
{key: "planet", value: "mars"}: pointer.Int64Ptr(0),
|
{key: "planet", value: "mars"}: pointer.Int64Ptr(0),
|
||||||
},
|
},
|
||||||
|
TopologyNormalizingWeight: []float64{topologyNormalizingWeight(1), topologyNormalizingWeight(1)},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -186,6 +183,7 @@ func TestPreScoreStateEmptyNodes(t *testing.T) {
|
|||||||
TopologyPairToPodCounts: map[topologyPair]*int64{
|
TopologyPairToPodCounts: map[topologyPair]*int64{
|
||||||
{"planet", "mars"}: pointer.Int64Ptr(0),
|
{"planet", "mars"}: pointer.Int64Ptr(0),
|
||||||
},
|
},
|
||||||
|
TopologyNormalizingWeight: []float64{topologyNormalizingWeight(1)},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -238,11 +236,11 @@ func TestPodTopologySpreadScore(t *testing.T) {
|
|||||||
// if there is only one candidate node, it should be scored to 10
|
// if there is only one candidate node, it should be scored to 10
|
||||||
name: "one constraint on node, no existing pods",
|
name: "one constraint on node, no existing pods",
|
||||||
pod: st.MakePod().Name("p").Label("foo", "").
|
pod: st.MakePod().Name("p").Label("foo", "").
|
||||||
SpreadConstraint(1, "node", v1.ScheduleAnyway, st.MakeLabelSelector().Exists("foo").Obj()).
|
SpreadConstraint(1, v1.LabelHostname, v1.ScheduleAnyway, st.MakeLabelSelector().Exists("foo").Obj()).
|
||||||
Obj(),
|
Obj(),
|
||||||
nodes: []*v1.Node{
|
nodes: []*v1.Node{
|
||||||
st.MakeNode().Name("node-a").Label("node", "node-a").Obj(),
|
st.MakeNode().Name("node-a").Label(v1.LabelHostname, "node-a").Obj(),
|
||||||
st.MakeNode().Name("node-b").Label("node", "node-b").Obj(),
|
st.MakeNode().Name("node-b").Label(v1.LabelHostname, "node-b").Obj(),
|
||||||
},
|
},
|
||||||
want: []framework.NodeScore{
|
want: []framework.NodeScore{
|
||||||
{Name: "node-a", Score: 100},
|
{Name: "node-a", Score: 100},
|
||||||
@ -253,7 +251,7 @@ func TestPodTopologySpreadScore(t *testing.T) {
|
|||||||
// if there is only one candidate node, it should be scored to 10
|
// if there is only one candidate node, it should be scored to 10
|
||||||
name: "one constraint on node, only one node is candidate",
|
name: "one constraint on node, only one node is candidate",
|
||||||
pod: st.MakePod().Name("p").Label("foo", "").
|
pod: st.MakePod().Name("p").Label("foo", "").
|
||||||
SpreadConstraint(1, "node", v1.ScheduleAnyway, st.MakeLabelSelector().Exists("foo").Obj()).
|
SpreadConstraint(1, v1.LabelHostname, v1.ScheduleAnyway, st.MakeLabelSelector().Exists("foo").Obj()).
|
||||||
Obj(),
|
Obj(),
|
||||||
existingPods: []*v1.Pod{
|
existingPods: []*v1.Pod{
|
||||||
st.MakePod().Name("p-a1").Node("node-a").Label("foo", "").Obj(),
|
st.MakePod().Name("p-a1").Node("node-a").Label("foo", "").Obj(),
|
||||||
@ -261,10 +259,10 @@ func TestPodTopologySpreadScore(t *testing.T) {
|
|||||||
st.MakePod().Name("p-b1").Node("node-b").Label("foo", "").Obj(),
|
st.MakePod().Name("p-b1").Node("node-b").Label("foo", "").Obj(),
|
||||||
},
|
},
|
||||||
nodes: []*v1.Node{
|
nodes: []*v1.Node{
|
||||||
st.MakeNode().Name("node-a").Label("node", "node-a").Obj(),
|
st.MakeNode().Name("node-a").Label(v1.LabelHostname, "node-a").Obj(),
|
||||||
},
|
},
|
||||||
failedNodes: []*v1.Node{
|
failedNodes: []*v1.Node{
|
||||||
st.MakeNode().Name("node-b").Label("node", "node-b").Obj(),
|
st.MakeNode().Name("node-b").Label(v1.LabelHostname, "node-b").Obj(),
|
||||||
},
|
},
|
||||||
want: []framework.NodeScore{
|
want: []framework.NodeScore{
|
||||||
{Name: "node-a", Score: 100},
|
{Name: "node-a", Score: 100},
|
||||||
@ -273,15 +271,15 @@ func TestPodTopologySpreadScore(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "one constraint on node, all nodes have the same number of matching pods",
|
name: "one constraint on node, all nodes have the same number of matching pods",
|
||||||
pod: st.MakePod().Name("p").Label("foo", "").
|
pod: st.MakePod().Name("p").Label("foo", "").
|
||||||
SpreadConstraint(1, "node", v1.ScheduleAnyway, st.MakeLabelSelector().Exists("foo").Obj()).
|
SpreadConstraint(1, v1.LabelHostname, v1.ScheduleAnyway, st.MakeLabelSelector().Exists("foo").Obj()).
|
||||||
Obj(),
|
Obj(),
|
||||||
existingPods: []*v1.Pod{
|
existingPods: []*v1.Pod{
|
||||||
st.MakePod().Name("p-a1").Node("node-a").Label("foo", "").Obj(),
|
st.MakePod().Name("p-a1").Node("node-a").Label("foo", "").Obj(),
|
||||||
st.MakePod().Name("p-b1").Node("node-b").Label("foo", "").Obj(),
|
st.MakePod().Name("p-b1").Node("node-b").Label("foo", "").Obj(),
|
||||||
},
|
},
|
||||||
nodes: []*v1.Node{
|
nodes: []*v1.Node{
|
||||||
st.MakeNode().Name("node-a").Label("node", "node-a").Obj(),
|
st.MakeNode().Name("node-a").Label(v1.LabelHostname, "node-a").Obj(),
|
||||||
st.MakeNode().Name("node-b").Label("node", "node-b").Obj(),
|
st.MakeNode().Name("node-b").Label(v1.LabelHostname, "node-b").Obj(),
|
||||||
},
|
},
|
||||||
want: []framework.NodeScore{
|
want: []framework.NodeScore{
|
||||||
{Name: "node-a", Score: 100},
|
{Name: "node-a", Score: 100},
|
||||||
@ -289,12 +287,10 @@ func TestPodTopologySpreadScore(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// matching pods spread as 2/1/0/3, total = 6
|
// matching pods spread as 2/1/0/3.
|
||||||
// after reversing, it's 4/5/6/3
|
|
||||||
// so scores = 400/6, 500/6, 600/6, 300/6
|
|
||||||
name: "one constraint on node, all 4 nodes are candidates",
|
name: "one constraint on node, all 4 nodes are candidates",
|
||||||
pod: st.MakePod().Name("p").Label("foo", "").
|
pod: st.MakePod().Name("p").Label("foo", "").
|
||||||
SpreadConstraint(1, "node", v1.ScheduleAnyway, st.MakeLabelSelector().Exists("foo").Obj()).
|
SpreadConstraint(1, v1.LabelHostname, v1.ScheduleAnyway, st.MakeLabelSelector().Exists("foo").Obj()).
|
||||||
Obj(),
|
Obj(),
|
||||||
existingPods: []*v1.Pod{
|
existingPods: []*v1.Pod{
|
||||||
st.MakePod().Name("p-a1").Node("node-a").Label("foo", "").Obj(),
|
st.MakePod().Name("p-a1").Node("node-a").Label("foo", "").Obj(),
|
||||||
@ -305,26 +301,24 @@ func TestPodTopologySpreadScore(t *testing.T) {
|
|||||||
st.MakePod().Name("p-d3").Node("node-d").Label("foo", "").Obj(),
|
st.MakePod().Name("p-d3").Node("node-d").Label("foo", "").Obj(),
|
||||||
},
|
},
|
||||||
nodes: []*v1.Node{
|
nodes: []*v1.Node{
|
||||||
st.MakeNode().Name("node-a").Label("node", "node-a").Obj(),
|
st.MakeNode().Name("node-a").Label(v1.LabelHostname, "node-a").Obj(),
|
||||||
st.MakeNode().Name("node-b").Label("node", "node-b").Obj(),
|
st.MakeNode().Name("node-b").Label(v1.LabelHostname, "node-b").Obj(),
|
||||||
st.MakeNode().Name("node-c").Label("node", "node-c").Obj(),
|
st.MakeNode().Name("node-c").Label(v1.LabelHostname, "node-c").Obj(),
|
||||||
st.MakeNode().Name("node-d").Label("node", "node-d").Obj(),
|
st.MakeNode().Name("node-d").Label(v1.LabelHostname, "node-d").Obj(),
|
||||||
},
|
},
|
||||||
failedNodes: []*v1.Node{},
|
failedNodes: []*v1.Node{},
|
||||||
want: []framework.NodeScore{
|
want: []framework.NodeScore{
|
||||||
{Name: "node-a", Score: 66},
|
{Name: "node-a", Score: 40},
|
||||||
{Name: "node-b", Score: 83},
|
{Name: "node-b", Score: 80},
|
||||||
{Name: "node-c", Score: 100},
|
{Name: "node-c", Score: 100},
|
||||||
{Name: "node-d", Score: 50},
|
{Name: "node-d", Score: 0},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// matching pods spread as 4/2/1/~3~, total = 4+2+1 = 7 (as node4 is not a candidate)
|
// matching pods spread as 4/2/1/~3~ (node4 is not a candidate)
|
||||||
// after reversing, it's 3/5/6
|
|
||||||
// so scores = 300/6, 500/6, 600/6
|
|
||||||
name: "one constraint on node, 3 out of 4 nodes are candidates",
|
name: "one constraint on node, 3 out of 4 nodes are candidates",
|
||||||
pod: st.MakePod().Name("p").Label("foo", "").
|
pod: st.MakePod().Name("p").Label("foo", "").
|
||||||
SpreadConstraint(1, "node", v1.ScheduleAnyway, st.MakeLabelSelector().Exists("foo").Obj()).
|
SpreadConstraint(1, v1.LabelHostname, v1.ScheduleAnyway, st.MakeLabelSelector().Exists("foo").Obj()).
|
||||||
Obj(),
|
Obj(),
|
||||||
existingPods: []*v1.Pod{
|
existingPods: []*v1.Pod{
|
||||||
st.MakePod().Name("p-a1").Node("node-a").Label("foo", "").Obj(),
|
st.MakePod().Name("p-a1").Node("node-a").Label("foo", "").Obj(),
|
||||||
@ -339,26 +333,24 @@ func TestPodTopologySpreadScore(t *testing.T) {
|
|||||||
st.MakePod().Name("p-y3").Node("node-y").Label("foo", "").Obj(),
|
st.MakePod().Name("p-y3").Node("node-y").Label("foo", "").Obj(),
|
||||||
},
|
},
|
||||||
nodes: []*v1.Node{
|
nodes: []*v1.Node{
|
||||||
st.MakeNode().Name("node-a").Label("node", "node-a").Obj(),
|
st.MakeNode().Name("node-a").Label(v1.LabelHostname, "node-a").Obj(),
|
||||||
st.MakeNode().Name("node-b").Label("node", "node-b").Obj(),
|
st.MakeNode().Name("node-b").Label(v1.LabelHostname, "node-b").Obj(),
|
||||||
st.MakeNode().Name("node-x").Label("node", "node-x").Obj(),
|
st.MakeNode().Name("node-x").Label(v1.LabelHostname, "node-x").Obj(),
|
||||||
},
|
},
|
||||||
failedNodes: []*v1.Node{
|
failedNodes: []*v1.Node{
|
||||||
st.MakeNode().Name("node-y").Label("node", "node-y").Obj(),
|
st.MakeNode().Name("node-y").Label(v1.LabelHostname, "node-y").Obj(),
|
||||||
},
|
},
|
||||||
want: []framework.NodeScore{
|
want: []framework.NodeScore{
|
||||||
{Name: "node-a", Score: 50},
|
{Name: "node-a", Score: 16},
|
||||||
{Name: "node-b", Score: 83},
|
{Name: "node-b", Score: 66},
|
||||||
{Name: "node-x", Score: 100},
|
{Name: "node-x", Score: 100},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// matching pods spread as 4/?2?/1/~3~, total = 4+?+1 = 5 (as node2 is problematic)
|
// matching pods spread as 4/?2?/1/~3~, total = 4+?+1 = 5 (as node2 is problematic)
|
||||||
// after reversing, it's 1/?/4
|
name: "one constraint on node, 3 out of 4 nodes are candidates, one node doesn't match topology key",
|
||||||
// so scores = 100/4, 0, 400/4
|
|
||||||
name: "one constraint on node, 3 out of 4 nodes are candidates",
|
|
||||||
pod: st.MakePod().Name("p").Label("foo", "").
|
pod: st.MakePod().Name("p").Label("foo", "").
|
||||||
SpreadConstraint(1, "node", v1.ScheduleAnyway, st.MakeLabelSelector().Exists("foo").Obj()).
|
SpreadConstraint(1, v1.LabelHostname, v1.ScheduleAnyway, st.MakeLabelSelector().Exists("foo").Obj()).
|
||||||
Obj(),
|
Obj(),
|
||||||
existingPods: []*v1.Pod{
|
existingPods: []*v1.Pod{
|
||||||
st.MakePod().Name("p-a1").Node("node-a").Label("foo", "").Obj(),
|
st.MakePod().Name("p-a1").Node("node-a").Label("foo", "").Obj(),
|
||||||
@ -373,23 +365,21 @@ func TestPodTopologySpreadScore(t *testing.T) {
|
|||||||
st.MakePod().Name("p-y3").Node("node-y").Label("foo", "").Obj(),
|
st.MakePod().Name("p-y3").Node("node-y").Label("foo", "").Obj(),
|
||||||
},
|
},
|
||||||
nodes: []*v1.Node{
|
nodes: []*v1.Node{
|
||||||
st.MakeNode().Name("node-a").Label("node", "node-a").Obj(),
|
st.MakeNode().Name("node-a").Label(v1.LabelHostname, "node-a").Obj(),
|
||||||
st.MakeNode().Name("node-b").Label("n", "node-b").Obj(), // label `n` doesn't match topologyKey
|
st.MakeNode().Name("node-b").Label("n", "node-b").Obj(), // label `n` doesn't match topologyKey
|
||||||
st.MakeNode().Name("node-x").Label("node", "node-x").Obj(),
|
st.MakeNode().Name("node-x").Label(v1.LabelHostname, "node-x").Obj(),
|
||||||
},
|
},
|
||||||
failedNodes: []*v1.Node{
|
failedNodes: []*v1.Node{
|
||||||
st.MakeNode().Name("node-y").Label("node", "node-y").Obj(),
|
st.MakeNode().Name("node-y").Label(v1.LabelHostname, "node-y").Obj(),
|
||||||
},
|
},
|
||||||
want: []framework.NodeScore{
|
want: []framework.NodeScore{
|
||||||
{Name: "node-a", Score: 25},
|
{Name: "node-a", Score: 20},
|
||||||
{Name: "node-b", Score: 0},
|
{Name: "node-b", Score: 0},
|
||||||
{Name: "node-x", Score: 100},
|
{Name: "node-x", Score: 100},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// matching pods spread as 4/2/1/~3~, total = 6+6+4 = 16 (as topologyKey is zone instead of node)
|
// matching pods spread as 4/2/1/~3~
|
||||||
// after reversing, it's 10/10/12
|
|
||||||
// so scores = 1000/12, 1000/12, 1200/12
|
|
||||||
name: "one constraint on zone, 3 out of 4 nodes are candidates",
|
name: "one constraint on zone, 3 out of 4 nodes are candidates",
|
||||||
pod: st.MakePod().Name("p").Label("foo", "").
|
pod: st.MakePod().Name("p").Label("foo", "").
|
||||||
SpreadConstraint(1, "zone", v1.ScheduleAnyway, st.MakeLabelSelector().Exists("foo").Obj()).
|
SpreadConstraint(1, "zone", v1.ScheduleAnyway, st.MakeLabelSelector().Exists("foo").Obj()).
|
||||||
@ -407,27 +397,25 @@ func TestPodTopologySpreadScore(t *testing.T) {
|
|||||||
st.MakePod().Name("p-y3").Node("node-y").Label("foo", "").Obj(),
|
st.MakePod().Name("p-y3").Node("node-y").Label("foo", "").Obj(),
|
||||||
},
|
},
|
||||||
nodes: []*v1.Node{
|
nodes: []*v1.Node{
|
||||||
st.MakeNode().Name("node-a").Label("zone", "zone1").Label("node", "node-a").Obj(),
|
st.MakeNode().Name("node-a").Label("zone", "zone1").Label(v1.LabelHostname, "node-a").Obj(),
|
||||||
st.MakeNode().Name("node-b").Label("zone", "zone1").Label("node", "node-b").Obj(),
|
st.MakeNode().Name("node-b").Label("zone", "zone1").Label(v1.LabelHostname, "node-b").Obj(),
|
||||||
st.MakeNode().Name("node-x").Label("zone", "zone2").Label("node", "node-x").Obj(),
|
st.MakeNode().Name("node-x").Label("zone", "zone2").Label(v1.LabelHostname, "node-x").Obj(),
|
||||||
},
|
},
|
||||||
failedNodes: []*v1.Node{
|
failedNodes: []*v1.Node{
|
||||||
st.MakeNode().Name("node-y").Label("zone", "zone2").Label("node", "node-y").Obj(),
|
st.MakeNode().Name("node-y").Label("zone", "zone2").Label(v1.LabelHostname, "node-y").Obj(),
|
||||||
},
|
},
|
||||||
want: []framework.NodeScore{
|
want: []framework.NodeScore{
|
||||||
{Name: "node-a", Score: 83},
|
{Name: "node-a", Score: 62},
|
||||||
{Name: "node-b", Score: 83},
|
{Name: "node-b", Score: 62},
|
||||||
{Name: "node-x", Score: 100},
|
{Name: "node-x", Score: 100},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// matching pods spread as 2/~1~/2/~4~, total = 2+3 + 2+6 = 13 (zone and node should be both summed up)
|
// matching pods spread as 2/~1~/2/~4~.
|
||||||
// after reversing, it's 8/5
|
|
||||||
// so scores = 800/8, 500/8
|
|
||||||
name: "two Constraints on zone and node, 2 out of 4 nodes are candidates",
|
name: "two Constraints on zone and node, 2 out of 4 nodes are candidates",
|
||||||
pod: st.MakePod().Name("p").Label("foo", "").
|
pod: st.MakePod().Name("p").Label("foo", "").
|
||||||
SpreadConstraint(1, "zone", v1.ScheduleAnyway, st.MakeLabelSelector().Exists("foo").Obj()).
|
SpreadConstraint(1, "zone", v1.ScheduleAnyway, st.MakeLabelSelector().Exists("foo").Obj()).
|
||||||
SpreadConstraint(1, "node", v1.ScheduleAnyway, st.MakeLabelSelector().Exists("foo").Obj()).
|
SpreadConstraint(1, v1.LabelHostname, v1.ScheduleAnyway, st.MakeLabelSelector().Exists("foo").Obj()).
|
||||||
Obj(),
|
Obj(),
|
||||||
existingPods: []*v1.Pod{
|
existingPods: []*v1.Pod{
|
||||||
st.MakePod().Name("p-a1").Node("node-a").Label("foo", "").Obj(),
|
st.MakePod().Name("p-a1").Node("node-a").Label("foo", "").Obj(),
|
||||||
@ -441,16 +429,16 @@ func TestPodTopologySpreadScore(t *testing.T) {
|
|||||||
st.MakePod().Name("p-y4").Node("node-y").Label("foo", "").Obj(),
|
st.MakePod().Name("p-y4").Node("node-y").Label("foo", "").Obj(),
|
||||||
},
|
},
|
||||||
nodes: []*v1.Node{
|
nodes: []*v1.Node{
|
||||||
st.MakeNode().Name("node-a").Label("zone", "zone1").Label("node", "node-a").Obj(),
|
st.MakeNode().Name("node-a").Label("zone", "zone1").Label(v1.LabelHostname, "node-a").Obj(),
|
||||||
st.MakeNode().Name("node-x").Label("zone", "zone2").Label("node", "node-x").Obj(),
|
st.MakeNode().Name("node-x").Label("zone", "zone2").Label(v1.LabelHostname, "node-x").Obj(),
|
||||||
},
|
},
|
||||||
failedNodes: []*v1.Node{
|
failedNodes: []*v1.Node{
|
||||||
st.MakeNode().Name("node-b").Label("zone", "zone1").Label("node", "node-b").Obj(),
|
st.MakeNode().Name("node-b").Label("zone", "zone1").Label(v1.LabelHostname, "node-b").Obj(),
|
||||||
st.MakeNode().Name("node-y").Label("zone", "zone2").Label("node", "node-y").Obj(),
|
st.MakeNode().Name("node-y").Label("zone", "zone2").Label(v1.LabelHostname, "node-y").Obj(),
|
||||||
},
|
},
|
||||||
want: []framework.NodeScore{
|
want: []framework.NodeScore{
|
||||||
{Name: "node-a", Score: 100},
|
{Name: "node-a", Score: 100},
|
||||||
{Name: "node-x", Score: 62},
|
{Name: "node-x", Score: 54},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -464,13 +452,10 @@ func TestPodTopologySpreadScore(t *testing.T) {
|
|||||||
// +--------+-------------+--------+---------------+
|
// +--------+-------------+--------+---------------+
|
||||||
// For the first constraint (zone): the matching pods spread as 2/2/1/1
|
// For the first constraint (zone): the matching pods spread as 2/2/1/1
|
||||||
// For the second constraint (node): the matching pods spread as 0/1/0/1
|
// For the second constraint (node): the matching pods spread as 0/1/0/1
|
||||||
// sum them up gets: 2/3/1/2, and total number is 8.
|
|
||||||
// after reversing, it's 6/5/7/6
|
|
||||||
// so scores = 600/7, 500/7, 700/7, 600/7
|
|
||||||
name: "two Constraints on zone and node, with different labelSelectors",
|
name: "two Constraints on zone and node, with different labelSelectors",
|
||||||
pod: st.MakePod().Name("p").Label("foo", "").Label("bar", "").
|
pod: st.MakePod().Name("p").Label("foo", "").Label("bar", "").
|
||||||
SpreadConstraint(1, "zone", v1.ScheduleAnyway, st.MakeLabelSelector().Exists("foo").Obj()).
|
SpreadConstraint(1, "zone", v1.ScheduleAnyway, st.MakeLabelSelector().Exists("foo").Obj()).
|
||||||
SpreadConstraint(1, "node", v1.ScheduleAnyway, st.MakeLabelSelector().Exists("bar").Obj()).
|
SpreadConstraint(1, v1.LabelHostname, v1.ScheduleAnyway, st.MakeLabelSelector().Exists("bar").Obj()).
|
||||||
Obj(),
|
Obj(),
|
||||||
existingPods: []*v1.Pod{
|
existingPods: []*v1.Pod{
|
||||||
st.MakePod().Name("p-a1").Node("node-a").Label("foo", "").Obj(),
|
st.MakePod().Name("p-a1").Node("node-a").Label("foo", "").Obj(),
|
||||||
@ -479,29 +464,26 @@ func TestPodTopologySpreadScore(t *testing.T) {
|
|||||||
st.MakePod().Name("p-y2").Node("node-y").Label("bar", "").Obj(),
|
st.MakePod().Name("p-y2").Node("node-y").Label("bar", "").Obj(),
|
||||||
},
|
},
|
||||||
nodes: []*v1.Node{
|
nodes: []*v1.Node{
|
||||||
st.MakeNode().Name("node-a").Label("zone", "zone1").Label("node", "node-a").Obj(),
|
st.MakeNode().Name("node-a").Label("zone", "zone1").Label(v1.LabelHostname, "node-a").Obj(),
|
||||||
st.MakeNode().Name("node-b").Label("zone", "zone1").Label("node", "node-b").Obj(),
|
st.MakeNode().Name("node-b").Label("zone", "zone1").Label(v1.LabelHostname, "node-b").Obj(),
|
||||||
st.MakeNode().Name("node-x").Label("zone", "zone2").Label("node", "node-x").Obj(),
|
st.MakeNode().Name("node-x").Label("zone", "zone2").Label(v1.LabelHostname, "node-x").Obj(),
|
||||||
st.MakeNode().Name("node-y").Label("zone", "zone2").Label("node", "node-y").Obj(),
|
st.MakeNode().Name("node-y").Label("zone", "zone2").Label(v1.LabelHostname, "node-y").Obj(),
|
||||||
},
|
},
|
||||||
failedNodes: []*v1.Node{},
|
failedNodes: []*v1.Node{},
|
||||||
want: []framework.NodeScore{
|
want: []framework.NodeScore{
|
||||||
{Name: "node-a", Score: 85},
|
{Name: "node-a", Score: 75},
|
||||||
{Name: "node-b", Score: 71},
|
{Name: "node-b", Score: 25},
|
||||||
{Name: "node-x", Score: 100},
|
{Name: "node-x", Score: 100},
|
||||||
{Name: "node-y", Score: 85},
|
{Name: "node-y", Score: 50},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// For the first constraint (zone): the matching pods spread as 0/0/2/2
|
// For the first constraint (zone): the matching pods spread as 0/0/2/2
|
||||||
// For the second constraint (node): the matching pods spread as 0/1/0/1
|
// For the second constraint (node): the matching pods spread as 0/1/0/1
|
||||||
// sum them up gets: 0/1/2/3, and total number is 6.
|
|
||||||
// after reversing, it's 6/5/4/3.
|
|
||||||
// so scores = 600/6, 500/6, 400/6, 300/6
|
|
||||||
name: "two Constraints on zone and node, with different labelSelectors, some nodes have 0 pods",
|
name: "two Constraints on zone and node, with different labelSelectors, some nodes have 0 pods",
|
||||||
pod: st.MakePod().Name("p").Label("foo", "").Label("bar", "").
|
pod: st.MakePod().Name("p").Label("foo", "").Label("bar", "").
|
||||||
SpreadConstraint(1, "zone", v1.ScheduleAnyway, st.MakeLabelSelector().Exists("foo").Obj()).
|
SpreadConstraint(1, "zone", v1.ScheduleAnyway, st.MakeLabelSelector().Exists("foo").Obj()).
|
||||||
SpreadConstraint(1, "node", v1.ScheduleAnyway, st.MakeLabelSelector().Exists("bar").Obj()).
|
SpreadConstraint(1, v1.LabelHostname, v1.ScheduleAnyway, st.MakeLabelSelector().Exists("bar").Obj()).
|
||||||
Obj(),
|
Obj(),
|
||||||
existingPods: []*v1.Pod{
|
existingPods: []*v1.Pod{
|
||||||
st.MakePod().Name("p-b1").Node("node-b").Label("bar", "").Obj(),
|
st.MakePod().Name("p-b1").Node("node-b").Label("bar", "").Obj(),
|
||||||
@ -509,29 +491,26 @@ func TestPodTopologySpreadScore(t *testing.T) {
|
|||||||
st.MakePod().Name("p-y1").Node("node-y").Label("foo", "").Label("bar", "").Obj(),
|
st.MakePod().Name("p-y1").Node("node-y").Label("foo", "").Label("bar", "").Obj(),
|
||||||
},
|
},
|
||||||
nodes: []*v1.Node{
|
nodes: []*v1.Node{
|
||||||
st.MakeNode().Name("node-a").Label("zone", "zone1").Label("node", "node-a").Obj(),
|
st.MakeNode().Name("node-a").Label("zone", "zone1").Label(v1.LabelHostname, "node-a").Obj(),
|
||||||
st.MakeNode().Name("node-b").Label("zone", "zone1").Label("node", "node-b").Obj(),
|
st.MakeNode().Name("node-b").Label("zone", "zone1").Label(v1.LabelHostname, "node-b").Obj(),
|
||||||
st.MakeNode().Name("node-x").Label("zone", "zone2").Label("node", "node-x").Obj(),
|
st.MakeNode().Name("node-x").Label("zone", "zone2").Label(v1.LabelHostname, "node-x").Obj(),
|
||||||
st.MakeNode().Name("node-y").Label("zone", "zone2").Label("node", "node-y").Obj(),
|
st.MakeNode().Name("node-y").Label("zone", "zone2").Label(v1.LabelHostname, "node-y").Obj(),
|
||||||
},
|
},
|
||||||
failedNodes: []*v1.Node{},
|
failedNodes: []*v1.Node{},
|
||||||
want: []framework.NodeScore{
|
want: []framework.NodeScore{
|
||||||
{Name: "node-a", Score: 100},
|
{Name: "node-a", Score: 100},
|
||||||
{Name: "node-b", Score: 83},
|
{Name: "node-b", Score: 75},
|
||||||
{Name: "node-x", Score: 66},
|
{Name: "node-x", Score: 50},
|
||||||
{Name: "node-y", Score: 50},
|
{Name: "node-y", Score: 0},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// For the first constraint (zone): the matching pods spread as 2/2/1/~1~
|
// For the first constraint (zone): the matching pods spread as 2/2/1/~1~
|
||||||
// For the second constraint (node): the matching pods spread as 0/1/0/~1~
|
// For the second constraint (node): the matching pods spread as 0/1/0/~1~
|
||||||
// sum them up gets: 2/3/1, and total number is 6.
|
|
||||||
// after reversing, it's 4/3/5
|
|
||||||
// so scores = 400/5, 300/5, 500/5
|
|
||||||
name: "two Constraints on zone and node, with different labelSelectors, 3 out of 4 nodes are candidates",
|
name: "two Constraints on zone and node, with different labelSelectors, 3 out of 4 nodes are candidates",
|
||||||
pod: st.MakePod().Name("p").Label("foo", "").Label("bar", "").
|
pod: st.MakePod().Name("p").Label("foo", "").Label("bar", "").
|
||||||
SpreadConstraint(1, "zone", v1.ScheduleAnyway, st.MakeLabelSelector().Exists("foo").Obj()).
|
SpreadConstraint(1, "zone", v1.ScheduleAnyway, st.MakeLabelSelector().Exists("foo").Obj()).
|
||||||
SpreadConstraint(1, "node", v1.ScheduleAnyway, st.MakeLabelSelector().Exists("bar").Obj()).
|
SpreadConstraint(1, v1.LabelHostname, v1.ScheduleAnyway, st.MakeLabelSelector().Exists("bar").Obj()).
|
||||||
Obj(),
|
Obj(),
|
||||||
existingPods: []*v1.Pod{
|
existingPods: []*v1.Pod{
|
||||||
st.MakePod().Name("p-a1").Node("node-a").Label("foo", "").Obj(),
|
st.MakePod().Name("p-a1").Node("node-a").Label("foo", "").Obj(),
|
||||||
@ -540,23 +519,23 @@ func TestPodTopologySpreadScore(t *testing.T) {
|
|||||||
st.MakePod().Name("p-y2").Node("node-y").Label("bar", "").Obj(),
|
st.MakePod().Name("p-y2").Node("node-y").Label("bar", "").Obj(),
|
||||||
},
|
},
|
||||||
nodes: []*v1.Node{
|
nodes: []*v1.Node{
|
||||||
st.MakeNode().Name("node-a").Label("zone", "zone1").Label("node", "node-a").Obj(),
|
st.MakeNode().Name("node-a").Label("zone", "zone1").Label(v1.LabelHostname, "node-a").Obj(),
|
||||||
st.MakeNode().Name("node-b").Label("zone", "zone1").Label("node", "node-b").Obj(),
|
st.MakeNode().Name("node-b").Label("zone", "zone1").Label(v1.LabelHostname, "node-b").Obj(),
|
||||||
st.MakeNode().Name("node-x").Label("zone", "zone2").Label("node", "node-x").Obj(),
|
st.MakeNode().Name("node-x").Label("zone", "zone2").Label(v1.LabelHostname, "node-x").Obj(),
|
||||||
},
|
},
|
||||||
failedNodes: []*v1.Node{
|
failedNodes: []*v1.Node{
|
||||||
st.MakeNode().Name("node-y").Label("zone", "zone2").Label("node", "node-y").Obj(),
|
st.MakeNode().Name("node-y").Label("zone", "zone2").Label(v1.LabelHostname, "node-y").Obj(),
|
||||||
},
|
},
|
||||||
want: []framework.NodeScore{
|
want: []framework.NodeScore{
|
||||||
{Name: "node-a", Score: 80},
|
{Name: "node-a", Score: 75},
|
||||||
{Name: "node-b", Score: 60},
|
{Name: "node-b", Score: 25},
|
||||||
{Name: "node-x", Score: 100},
|
{Name: "node-x", Score: 100},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "existing pods in a different namespace do not count",
|
name: "existing pods in a different namespace do not count",
|
||||||
pod: st.MakePod().Name("p").Label("foo", "").
|
pod: st.MakePod().Name("p").Label("foo", "").
|
||||||
SpreadConstraint(1, "node", v1.ScheduleAnyway, st.MakeLabelSelector().Exists("foo").Obj()).
|
SpreadConstraint(1, v1.LabelHostname, v1.ScheduleAnyway, st.MakeLabelSelector().Exists("foo").Obj()).
|
||||||
Obj(),
|
Obj(),
|
||||||
existingPods: []*v1.Pod{
|
existingPods: []*v1.Pod{
|
||||||
st.MakePod().Name("p-a1").Namespace("ns1").Node("node-a").Label("foo", "").Obj(),
|
st.MakePod().Name("p-a1").Namespace("ns1").Node("node-a").Label("foo", "").Obj(),
|
||||||
@ -565,8 +544,8 @@ func TestPodTopologySpreadScore(t *testing.T) {
|
|||||||
st.MakePod().Name("p-b2").Node("node-b").Label("foo", "").Obj(),
|
st.MakePod().Name("p-b2").Node("node-b").Label("foo", "").Obj(),
|
||||||
},
|
},
|
||||||
nodes: []*v1.Node{
|
nodes: []*v1.Node{
|
||||||
st.MakeNode().Name("node-a").Label("node", "node-a").Obj(),
|
st.MakeNode().Name("node-a").Label(v1.LabelHostname, "node-a").Obj(),
|
||||||
st.MakeNode().Name("node-b").Label("node", "node-b").Obj(),
|
st.MakeNode().Name("node-b").Label(v1.LabelHostname, "node-b").Obj(),
|
||||||
},
|
},
|
||||||
want: []framework.NodeScore{
|
want: []framework.NodeScore{
|
||||||
{Name: "node-a", Score: 100},
|
{Name: "node-a", Score: 100},
|
||||||
@ -576,11 +555,11 @@ func TestPodTopologySpreadScore(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "terminating Pods should be excluded",
|
name: "terminating Pods should be excluded",
|
||||||
pod: st.MakePod().Name("p").Label("foo", "").SpreadConstraint(
|
pod: st.MakePod().Name("p").Label("foo", "").SpreadConstraint(
|
||||||
1, "node", v1.ScheduleAnyway, st.MakeLabelSelector().Exists("foo").Obj(),
|
1, v1.LabelHostname, v1.ScheduleAnyway, st.MakeLabelSelector().Exists("foo").Obj(),
|
||||||
).Obj(),
|
).Obj(),
|
||||||
nodes: []*v1.Node{
|
nodes: []*v1.Node{
|
||||||
st.MakeNode().Name("node-a").Label("node", "node-a").Obj(),
|
st.MakeNode().Name("node-a").Label(v1.LabelHostname, "node-a").Obj(),
|
||||||
st.MakeNode().Name("node-b").Label("node", "node-b").Obj(),
|
st.MakeNode().Name("node-b").Label(v1.LabelHostname, "node-b").Obj(),
|
||||||
},
|
},
|
||||||
existingPods: []*v1.Pod{
|
existingPods: []*v1.Pod{
|
||||||
st.MakePod().Name("p-a").Node("node-a").Label("foo", "").Terminating().Obj(),
|
st.MakePod().Name("p-a").Node("node-a").Label("foo", "").Terminating().Obj(),
|
||||||
|
Loading…
Reference in New Issue
Block a user