implementation for MatchLabelKeys in TopologySpreadConstraint

Signed-off-by: Alex Wang <wangqingcan1990@gmail.com>
This commit is contained in:
Alex Wang
2022-07-30 13:23:49 +08:00
parent e6c2bf8516
commit f4bc904376
14 changed files with 576 additions and 188 deletions

View File

@@ -515,6 +515,13 @@ const (
// Enables scaling down replicas via logarithmic comparison of creation/ready timestamps
LogarithmicScaleDown featuregate.Feature = "LogarithmicScaleDown"
// owner: @denkensk
// kep: http://kep.k8s.io/3243
// alpha: v1.25
//
// Enable MatchLabelKeys in PodTopologySpread.
MatchLabelKeysInPodTopologySpread featuregate.Feature = "MatchLabelKeysInPodTopologySpread"
// owner: @krmayankk
// alpha: v1.24
//
@@ -948,6 +955,8 @@ var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureS
LogarithmicScaleDown: {Default: true, PreRelease: featuregate.Beta},
MatchLabelKeysInPodTopologySpread: {Default: false, PreRelease: featuregate.Alpha},
MaxUnavailableStatefulSet: {Default: false, PreRelease: featuregate.Alpha},
MemoryManager: {Default: true, PreRelease: featuregate.Beta},

View File

@@ -644,8 +644,8 @@ func TestDryRunPreemption(t *testing.T) {
nodeNames: []string{"node-a/zone1", "node-b/zone1", "node-x/zone2"},
testPods: []*v1.Pod{
st.MakePod().Name("p").UID("p").Label("foo", "").Priority(highPriority).
SpreadConstraint(1, "zone", v1.DoNotSchedule, st.MakeLabelSelector().Exists("foo").Obj(), nil, nil, nil).
SpreadConstraint(1, "hostname", v1.DoNotSchedule, st.MakeLabelSelector().Exists("foo").Obj(), nil, nil, nil).
SpreadConstraint(1, "zone", v1.DoNotSchedule, st.MakeLabelSelector().Exists("foo").Obj(), nil, nil, nil, nil).
SpreadConstraint(1, "hostname", v1.DoNotSchedule, st.MakeLabelSelector().Exists("foo").Obj(), nil, nil, nil, nil).
Obj(),
},
initPods: []*v1.Pod{
@@ -1486,8 +1486,8 @@ func TestPreempt(t *testing.T) {
{
name: "preemption for topology spread constraints",
pod: st.MakePod().Name("p").UID("p").Namespace(v1.NamespaceDefault).Label("foo", "").Priority(highPriority).
SpreadConstraint(1, "zone", v1.DoNotSchedule, st.MakeLabelSelector().Exists("foo").Obj(), nil, nil, nil).
SpreadConstraint(1, "hostname", v1.DoNotSchedule, st.MakeLabelSelector().Exists("foo").Obj(), nil, nil, nil).
SpreadConstraint(1, "zone", v1.DoNotSchedule, st.MakeLabelSelector().Exists("foo").Obj(), nil, nil, nil, nil).
SpreadConstraint(1, "hostname", v1.DoNotSchedule, st.MakeLabelSelector().Exists("foo").Obj(), nil, nil, nil, nil).
Obj(),
pods: []*v1.Pod{
st.MakePod().Name("p-a1").UID("p-a1").Namespace(v1.NamespaceDefault).Node("node-a").Label("foo", "").Priority(highPriority).Obj(),

View File

@@ -24,4 +24,5 @@ type Features struct {
EnableVolumeCapacityPriority bool
EnableMinDomainsInPodTopologySpread bool
EnableNodeInclusionPolicyInPodTopologySpread bool
EnableMatchLabelKeysInPodTopologySpread bool
}

View File

@@ -63,7 +63,7 @@ func (tsc *topologySpreadConstraint) matchNodeInclusionPolicies(pod *v1.Pod, nod
// .DefaultConstraints and the selectors from the services, replication
// controllers, replica sets and stateful sets that match the pod.
func (pl *PodTopologySpread) buildDefaultConstraints(p *v1.Pod, action v1.UnsatisfiableConstraintAction) ([]topologySpreadConstraint, error) {
constraints, err := filterTopologySpreadConstraints(pl.defaultConstraints, action, pl.enableMinDomainsInPodTopologySpread, pl.enableNodeInclusionPolicyInPodTopologySpread)
constraints, err := pl.filterTopologySpreadConstraints(pl.defaultConstraints, p.Labels, action)
if err != nil || len(constraints) == 0 {
return nil, err
}
@@ -87,7 +87,7 @@ func nodeLabelsMatchSpreadConstraints(nodeLabels map[string]string, constraints
return true
}
func filterTopologySpreadConstraints(constraints []v1.TopologySpreadConstraint, action v1.UnsatisfiableConstraintAction, enableMinDomainsInPodTopologySpread, enableNodeInclusionPolicyInPodTopologySpread bool) ([]topologySpreadConstraint, error) {
func (pl *PodTopologySpread) filterTopologySpreadConstraints(constraints []v1.TopologySpreadConstraint, podLabels map[string]string, action v1.UnsatisfiableConstraintAction) ([]topologySpreadConstraint, error) {
var result []topologySpreadConstraint
for _, c := range constraints {
if c.WhenUnsatisfiable == action {
@@ -95,6 +95,19 @@ func filterTopologySpreadConstraints(constraints []v1.TopologySpreadConstraint,
if err != nil {
return nil, err
}
if pl.enableMatchLabelKeysInPodTopologySpread && len(c.MatchLabelKeys) > 0 {
matchLabels := make(labels.Set)
for _, labelKey := range c.MatchLabelKeys {
if value, ok := podLabels[labelKey]; ok {
matchLabels[labelKey] = value
}
}
if len(matchLabels) > 0 {
selector = mergeLabelSetWithSelector(matchLabels, selector)
}
}
tsc := topologySpreadConstraint{
MaxSkew: c.MaxSkew,
TopologyKey: c.TopologyKey,
@@ -103,10 +116,10 @@ func filterTopologySpreadConstraints(constraints []v1.TopologySpreadConstraint,
NodeAffinityPolicy: v1.NodeInclusionPolicyHonor, // If NodeAffinityPolicy is nil, we treat NodeAffinityPolicy as "Honor".
NodeTaintsPolicy: v1.NodeInclusionPolicyIgnore, // If NodeTaintsPolicy is nil, we treat NodeTaintsPolicy as "Ignore".
}
if enableMinDomainsInPodTopologySpread && c.MinDomains != nil {
if pl.enableMinDomainsInPodTopologySpread && c.MinDomains != nil {
tsc.MinDomains = *c.MinDomains
}
if enableNodeInclusionPolicyInPodTopologySpread {
if pl.enableNodeInclusionPolicyInPodTopologySpread {
if c.NodeAffinityPolicy != nil {
tsc.NodeAffinityPolicy = *c.NodeAffinityPolicy
}
@@ -120,6 +133,17 @@ func filterTopologySpreadConstraints(constraints []v1.TopologySpreadConstraint,
return result, nil
}
func mergeLabelSetWithSelector(matchLabels labels.Set, s labels.Selector) labels.Selector {
mergedSelector := labels.SelectorFromSet(matchLabels)
if requirements, ok := s.Requirements(); ok {
for _, r := range requirements {
mergedSelector = mergedSelector.Add(r)
}
}
return mergedSelector
}
func countPodsMatchSelector(podInfos []*framework.PodInfo, selector labels.Selector, ns string) int {
count := 0
for _, p := range podInfos {

View File

@@ -244,11 +244,10 @@ func (pl *PodTopologySpread) calPreFilterState(ctx context.Context, pod *v1.Pod)
if len(pod.Spec.TopologySpreadConstraints) > 0 {
// We have feature gating in APIServer to strip the spec
// so don't need to re-check feature gate, just check length of Constraints.
constraints, err = filterTopologySpreadConstraints(
constraints, err = pl.filterTopologySpreadConstraints(
pod.Spec.TopologySpreadConstraints,
pod.Labels,
v1.DoNotSchedule,
pl.enableMinDomainsInPodTopologySpread,
pl.enableNodeInclusionPolicyInPodTopologySpread,
)
if err != nil {
return nil, fmt.Errorf("obtaining pod's hard topology spread constraints: %w", err)

View File

@@ -55,7 +55,8 @@ var (
honorPolicy = v1.NodeInclusionPolicyHonor
fooSelector = st.MakeLabelSelector().Exists("foo").Obj()
barSelector = st.MakeLabelSelector().Exists("bar").Obj()
taints = []v1.Taint{{Key: v1.TaintNodeUnschedulable, Value: "", Effect: v1.TaintEffectPreferNoSchedule}}
taints = []v1.Taint{{Key: v1.TaintNodeUnschedulable, Value: "", Effect: v1.TaintEffectPreferNoSchedule}}
)
func (p *criticalPaths) sort() {
@@ -77,11 +78,12 @@ func TestPreFilterState(t *testing.T) {
want *preFilterState
enableMinDomains bool
enableNodeInclustionPolicy bool
enableMatchLabelKeys bool
}{
{
name: "clean cluster with one spreadConstraint",
pod: st.MakePod().Name("p").Label("foo", "").
SpreadConstraint(5, "zone", v1.DoNotSchedule, st.MakeLabelSelector().Label("foo", "bar").Obj(), nil, nil, nil).
SpreadConstraint(5, "zone", v1.DoNotSchedule, st.MakeLabelSelector().Label("foo", "bar").Obj(), nil, nil, nil, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("zone", "zone1").Label("node", "node-a").Obj(),
@@ -112,7 +114,7 @@ func TestPreFilterState(t *testing.T) {
{
name: "normal case with one spreadConstraint",
pod: st.MakePod().Name("p").Label("foo", "").
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil).
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("zone", "zone1").Label("node", "node-a").Obj(),
@@ -150,7 +152,7 @@ func TestPreFilterState(t *testing.T) {
{
name: "normal case with one spreadConstraint, on a 3-zone cluster",
pod: st.MakePod().Name("p").Label("foo", "").
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil).
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("zone", "zone1").Label("node", "node-a").Obj(),
@@ -191,7 +193,7 @@ func TestPreFilterState(t *testing.T) {
{
name: "namespace mismatch doesn't count",
pod: st.MakePod().Name("p").Label("foo", "").
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil).
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("zone", "zone1").Label("node", "node-a").Obj(),
@@ -229,8 +231,8 @@ func TestPreFilterState(t *testing.T) {
{
name: "normal case with two spreadConstraints",
pod: st.MakePod().Name("p").Label("foo", "").
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil).
SpreadConstraint(1, "node", v1.DoNotSchedule, fooSelector, nil, nil, nil).
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil, nil).
SpreadConstraint(1, "node", v1.DoNotSchedule, fooSelector, nil, nil, nil, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("zone", "zone1").Label("node", "node-a").Obj(),
@@ -283,10 +285,10 @@ func TestPreFilterState(t *testing.T) {
{
name: "soft spreadConstraints should be bypassed",
pod: st.MakePod().Name("p").Label("foo", "").
SpreadConstraint(1, "zone", v1.ScheduleAnyway, fooSelector, nil, nil, nil).
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil).
SpreadConstraint(1, "node", v1.ScheduleAnyway, fooSelector, nil, nil, nil).
SpreadConstraint(1, "node", v1.DoNotSchedule, fooSelector, nil, nil, nil).
SpreadConstraint(1, "zone", v1.ScheduleAnyway, fooSelector, nil, nil, nil, nil).
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil, nil).
SpreadConstraint(1, "node", v1.ScheduleAnyway, fooSelector, nil, nil, nil, nil).
SpreadConstraint(1, "node", v1.DoNotSchedule, fooSelector, nil, nil, nil, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("zone", "zone1").Label("node", "node-a").Obj(),
@@ -337,8 +339,8 @@ func TestPreFilterState(t *testing.T) {
{
name: "different labelSelectors - simple version",
pod: st.MakePod().Name("p").Label("foo", "").Label("bar", "").
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil).
SpreadConstraint(1, "node", v1.DoNotSchedule, barSelector, nil, nil, nil).
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil, nil).
SpreadConstraint(1, "node", v1.DoNotSchedule, barSelector, nil, nil, nil, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("zone", "zone1").Label("node", "node-a").Obj(),
@@ -384,8 +386,8 @@ func TestPreFilterState(t *testing.T) {
{
name: "different labelSelectors - complex pods",
pod: st.MakePod().Name("p").Label("foo", "").Label("bar", "").
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil).
SpreadConstraint(1, "node", v1.DoNotSchedule, barSelector, nil, nil, nil).
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil, nil).
SpreadConstraint(1, "node", v1.DoNotSchedule, barSelector, nil, nil, nil, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("zone", "zone1").Label("node", "node-a").Obj(),
@@ -437,8 +439,8 @@ func TestPreFilterState(t *testing.T) {
name: "two spreadConstraints, and with podAffinity",
pod: st.MakePod().Name("p").Label("foo", "").
NodeAffinityNotIn("node", []string{"node-x"}). // exclude node-x
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil).
SpreadConstraint(1, "node", v1.DoNotSchedule, fooSelector, nil, nil, nil).
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil, nil).
SpreadConstraint(1, "node", v1.DoNotSchedule, fooSelector, nil, nil, nil, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("zone", "zone1").Label("node", "node-a").Obj(),
@@ -538,8 +540,8 @@ func TestPreFilterState(t *testing.T) {
{
name: "default constraints and a service, but pod has constraints",
pod: st.MakePod().Name("p").Label("foo", "bar").Label("baz", "tar").
SpreadConstraint(1, "zone", v1.DoNotSchedule, st.MakeLabelSelector().Label("baz", "tar").Obj(), nil, nil, nil).
SpreadConstraint(2, "planet", v1.ScheduleAnyway, st.MakeLabelSelector().Label("fot", "rok").Obj(), nil, nil, nil).
SpreadConstraint(1, "zone", v1.DoNotSchedule, st.MakeLabelSelector().Label("baz", "tar").Obj(), nil, nil, nil, nil).
SpreadConstraint(2, "planet", v1.ScheduleAnyway, st.MakeLabelSelector().Label("fot", "rok").Obj(), nil, nil, nil, nil).
Obj(),
defaultConstraints: []v1.TopologySpreadConstraint{
{MaxSkew: 2, TopologyKey: "node", WhenUnsatisfiable: v1.DoNotSchedule},
@@ -578,8 +580,8 @@ func TestPreFilterState(t *testing.T) {
{
name: "TpKeyToDomainsNum is calculated when MinDomains is enabled",
pod: st.MakePod().Name("p").Label("foo", "").
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil).
SpreadConstraint(1, "node", v1.DoNotSchedule, fooSelector, nil, nil, nil).
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil, nil).
SpreadConstraint(1, "node", v1.DoNotSchedule, fooSelector, nil, nil, nil, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("zone", "zone1").Label("node", "node-a").Obj(),
@@ -638,7 +640,7 @@ func TestPreFilterState(t *testing.T) {
name: "feature gate disabled with NodeAffinityPolicy",
pod: st.MakePod().Name("p").Label("foo", "").
NodeSelector(map[string]string{"foo": ""}).
SpreadConstraint(1, "node", v1.DoNotSchedule, barSelector, nil, nil, nil).
SpreadConstraint(1, "node", v1.DoNotSchedule, barSelector, nil, nil, nil, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("node", "node-a").Label("foo", "").Obj(),
@@ -676,7 +678,7 @@ func TestPreFilterState(t *testing.T) {
name: "NodeAffinityPolicy honored with labelSelectors",
pod: st.MakePod().Name("p").Label("foo", "").
NodeSelector(map[string]string{"foo": ""}).
SpreadConstraint(1, "node", v1.DoNotSchedule, barSelector, nil, nil, nil).
SpreadConstraint(1, "node", v1.DoNotSchedule, barSelector, nil, nil, nil, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("node", "node-a").Label("foo", "").Obj(),
@@ -714,7 +716,7 @@ func TestPreFilterState(t *testing.T) {
name: "NodeAffinityPolicy ignored with labelSelectors",
pod: st.MakePod().Name("p").Label("foo", "").
NodeSelector(map[string]string{"foo": ""}).
SpreadConstraint(1, "node", v1.DoNotSchedule, barSelector, nil, &ignorePolicy, nil).
SpreadConstraint(1, "node", v1.DoNotSchedule, barSelector, nil, &ignorePolicy, nil, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("node", "node-a").Label("foo", "").Obj(),
@@ -753,7 +755,7 @@ func TestPreFilterState(t *testing.T) {
name: "NodeAffinityPolicy honored with nodeAffinity",
pod: st.MakePod().Name("p").Label("foo", "").
NodeAffinityIn("foo", []string{""}).
SpreadConstraint(1, "node", v1.DoNotSchedule, barSelector, nil, nil, nil).
SpreadConstraint(1, "node", v1.DoNotSchedule, barSelector, nil, nil, nil, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("node", "node-a").Label("foo", "").Obj(),
@@ -791,7 +793,7 @@ func TestPreFilterState(t *testing.T) {
name: "NodeAffinityPolicy ignored with nodeAffinity",
pod: st.MakePod().Name("p").Label("foo", "").
NodeAffinityIn("foo", []string{""}).
SpreadConstraint(1, "node", v1.DoNotSchedule, barSelector, nil, &ignorePolicy, nil).
SpreadConstraint(1, "node", v1.DoNotSchedule, barSelector, nil, &ignorePolicy, nil, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("node", "node-a").Label("foo", "").Obj(),
@@ -829,7 +831,7 @@ func TestPreFilterState(t *testing.T) {
{
name: "feature gate disabled with NodeTaintsPolicy",
pod: st.MakePod().Name("p").Label("foo", "").
SpreadConstraint(1, "node", v1.DoNotSchedule, barSelector, nil, nil, nil).
SpreadConstraint(1, "node", v1.DoNotSchedule, barSelector, nil, nil, nil, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("node", "node-a").Obj(),
@@ -867,7 +869,7 @@ func TestPreFilterState(t *testing.T) {
{
name: "NodeTaintsPolicy ignored",
pod: st.MakePod().Name("p").Label("foo", "").
SpreadConstraint(1, "node", v1.DoNotSchedule, barSelector, nil, nil, nil).
SpreadConstraint(1, "node", v1.DoNotSchedule, barSelector, nil, nil, nil, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("node", "node-a").Obj(),
@@ -905,7 +907,7 @@ func TestPreFilterState(t *testing.T) {
{
name: "NodeTaintsPolicy honored",
pod: st.MakePod().Name("p").Label("foo", "").
SpreadConstraint(1, "node", v1.DoNotSchedule, barSelector, nil, nil, &honorPolicy).
SpreadConstraint(1, "node", v1.DoNotSchedule, barSelector, nil, nil, &honorPolicy, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("node", "node-a").Obj(),
@@ -943,7 +945,7 @@ func TestPreFilterState(t *testing.T) {
name: "NodeTaintsPolicy honored with tolerated taints",
pod: st.MakePod().Name("p").Label("foo", "").
Toleration(v1.TaintNodeUnschedulable).
SpreadConstraint(1, "node", v1.DoNotSchedule, barSelector, nil, nil, &honorPolicy).
SpreadConstraint(1, "node", v1.DoNotSchedule, barSelector, nil, nil, &honorPolicy, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("node", "node-a").Obj(),
@@ -982,8 +984,8 @@ func TestPreFilterState(t *testing.T) {
name: "two node inclusion Constraints, zone: honor/ignore, node: ignore/ignore",
pod: st.MakePod().Name("p").Label("foo", "").
NodeSelector(map[string]string{"foo": ""}).
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil).
SpreadConstraint(1, "node", v1.DoNotSchedule, fooSelector, nil, &ignorePolicy, nil).
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil, nil).
SpreadConstraint(1, "node", v1.DoNotSchedule, fooSelector, nil, &ignorePolicy, nil, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("zone", "zone1").Label("node", "node-a").Label("foo", "").Obj(),
@@ -1031,8 +1033,8 @@ func TestPreFilterState(t *testing.T) {
{
name: "two node inclusion Constraints, zone: honor/honor, node: honor/ignore",
pod: st.MakePod().Name("p").Label("foo", "").
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, &honorPolicy).
SpreadConstraint(1, "node", v1.DoNotSchedule, fooSelector, nil, nil, nil).
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, &honorPolicy, nil).
SpreadConstraint(1, "node", v1.DoNotSchedule, fooSelector, nil, nil, nil, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("zone", "zone1").Label("node", "node-a").Label("foo", "").Obj(),
@@ -1081,8 +1083,8 @@ func TestPreFilterState(t *testing.T) {
name: "two node inclusion Constraints, zone: honor/ignore, node: honor/ignore",
pod: st.MakePod().Name("p").Label("foo", "").
NodeSelector(map[string]string{"foo": ""}).
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil).
SpreadConstraint(1, "node", v1.DoNotSchedule, fooSelector, nil, nil, nil).
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil, nil).
SpreadConstraint(1, "node", v1.DoNotSchedule, fooSelector, nil, nil, nil, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("zone", "zone1").Label("node", "node-a").Obj(),
@@ -1132,8 +1134,8 @@ func TestPreFilterState(t *testing.T) {
name: "two node inclusion Constraints, zone: ignore/ignore, node: honor/honor",
pod: st.MakePod().Name("p").Label("foo", "").
NodeSelector(map[string]string{"foo": ""}).
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, &ignorePolicy, nil).
SpreadConstraint(1, "node", v1.DoNotSchedule, fooSelector, nil, nil, &honorPolicy).
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, &ignorePolicy, nil, nil).
SpreadConstraint(1, "node", v1.DoNotSchedule, fooSelector, nil, nil, &honorPolicy, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("zone", "zone1").Label("node", "node-a").Obj(),
@@ -1180,6 +1182,162 @@ func TestPreFilterState(t *testing.T) {
},
enableNodeInclustionPolicy: true,
},
{
name: "matchLabelKeys ignored when feature gate disabled",
pod: st.MakePod().Name("p").Label("foo", "").Label("bar", "").
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil, []string{"bar"}).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("zone", "zone1").Label("node", "node-a").Obj(),
st.MakeNode().Name("node-b").Label("zone", "zone1").Label("node", "node-b").Obj(),
st.MakeNode().Name("node-x").Label("zone", "zone2").Label("node", "node-x").Obj(),
st.MakeNode().Name("node-y").Label("zone", "zone2").Label("node", "node-y").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-y1").Node("node-y").Label("foo", "").Obj(),
st.MakePod().Name("p-y2").Node("node-y").Label("foo", "").Obj(),
},
want: &preFilterState{
Constraints: []topologySpreadConstraint{
{
MaxSkew: 1,
TopologyKey: "zone",
Selector: mustConvertLabelSelectorAsSelector(t, fooSelector),
MinDomains: 1,
NodeAffinityPolicy: v1.NodeInclusionPolicyHonor,
NodeTaintsPolicy: v1.NodeInclusionPolicyIgnore,
},
},
TpKeyToCriticalPaths: map[string]*criticalPaths{
"zone": {{"zone2", 2}, {"zone1", 3}},
},
TpPairToMatchNum: map[topologyPair]int{
{key: "zone", value: "zone1"}: 3,
{key: "zone", value: "zone2"}: 2,
},
},
enableMatchLabelKeys: false,
},
{
name: "matchLabelKeys ANDed with LabelSelector when LabelSelector isn't empty",
pod: st.MakePod().Name("p").Label("foo", "").Label("bar", "a").
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil, []string{"bar"}).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("zone", "zone1").Label("node", "node-a").Obj(),
st.MakeNode().Name("node-b").Label("zone", "zone1").Label("node", "node-b").Obj(),
st.MakeNode().Name("node-x").Label("zone", "zone2").Label("node", "node-x").Obj(),
st.MakeNode().Name("node-y").Label("zone", "zone2").Label("node", "node-y").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", "").Label("bar", "a").Obj(),
st.MakePod().Name("p-b1").Node("node-b").Label("foo", "").Obj(),
st.MakePod().Name("p-y1").Node("node-y").Label("foo", "").Label("bar", "a").Obj(),
st.MakePod().Name("p-y2").Node("node-y").Label("bar", "").Obj(),
},
want: &preFilterState{
Constraints: []topologySpreadConstraint{
{
MaxSkew: 1,
TopologyKey: "zone",
Selector: mustConvertLabelSelectorAsSelector(t, st.MakeLabelSelector().Exists("foo").Label("bar", "a").Obj()),
MinDomains: 1,
NodeAffinityPolicy: v1.NodeInclusionPolicyHonor,
NodeTaintsPolicy: v1.NodeInclusionPolicyIgnore,
},
},
TpKeyToCriticalPaths: map[string]*criticalPaths{
"zone": {{"zone2", 1}, {"zone1", 1}},
},
TpPairToMatchNum: map[topologyPair]int{
{key: "zone", value: "zone1"}: 1,
{key: "zone", value: "zone2"}: 1,
},
},
enableMatchLabelKeys: true,
},
{
name: "matchLabelKeys ANDed with LabelSelector when LabelSelector is empty",
pod: st.MakePod().Name("p").Label("foo", "a").
SpreadConstraint(1, "zone", v1.DoNotSchedule, st.MakeLabelSelector().Obj(), nil, nil, nil, []string{"foo"}).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("zone", "zone1").Label("node", "node-a").Obj(),
st.MakeNode().Name("node-b").Label("zone", "zone1").Label("node", "node-b").Obj(),
st.MakeNode().Name("node-x").Label("zone", "zone2").Label("node", "node-x").Obj(),
st.MakeNode().Name("node-y").Label("zone", "zone2").Label("node", "node-y").Obj(),
},
existingPods: []*v1.Pod{
st.MakePod().Name("p-a1").Node("node-a").Label("foo", "a").Obj(),
st.MakePod().Name("p-a2").Node("node-a").Label("foo", "a").Obj(),
st.MakePod().Name("p-b1").Node("node-b").Label("foo", "a").Obj(),
st.MakePod().Name("p-y1").Node("node-y").Label("foo", "a").Obj(),
st.MakePod().Name("p-y2").Node("node-y").Label("foo", "a").Obj(),
},
want: &preFilterState{
Constraints: []topologySpreadConstraint{
{
MaxSkew: 1,
TopologyKey: "zone",
Selector: mustConvertLabelSelectorAsSelector(t, st.MakeLabelSelector().Label("foo", "a").Obj()),
MinDomains: 1,
NodeAffinityPolicy: v1.NodeInclusionPolicyHonor,
NodeTaintsPolicy: v1.NodeInclusionPolicyIgnore,
},
},
TpKeyToCriticalPaths: map[string]*criticalPaths{
"zone": {{"zone2", 2}, {"zone1", 3}},
},
TpPairToMatchNum: map[topologyPair]int{
{key: "zone", value: "zone1"}: 3,
{key: "zone", value: "zone2"}: 2,
},
},
enableMatchLabelKeys: true,
},
{
name: "key in matchLabelKeys is ignored when it isn't exist in pod.labels",
pod: st.MakePod().Name("p").Label("foo", "").
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil, []string{"bar"}).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("zone", "zone1").Label("node", "node-a").Obj(),
st.MakeNode().Name("node-b").Label("zone", "zone1").Label("node", "node-b").Obj(),
st.MakeNode().Name("node-x").Label("zone", "zone2").Label("node", "node-x").Obj(),
st.MakeNode().Name("node-y").Label("zone", "zone2").Label("node", "node-y").Obj(),
},
existingPods: []*v1.Pod{
st.MakePod().Name("p-a1").Node("node-a").Label("foo", "a").Obj(),
st.MakePod().Name("p-a2").Node("node-a").Label("foo", "a").Obj(),
st.MakePod().Name("p-b1").Node("node-b").Label("foo", "a").Obj(),
st.MakePod().Name("p-y1").Node("node-y").Label("foo", "a").Obj(),
st.MakePod().Name("p-y2").Node("node-y").Label("foo", "a").Obj(),
},
want: &preFilterState{
Constraints: []topologySpreadConstraint{
{
MaxSkew: 1,
TopologyKey: "zone",
Selector: mustConvertLabelSelectorAsSelector(t, fooSelector),
MinDomains: 1,
NodeAffinityPolicy: v1.NodeInclusionPolicyHonor,
NodeTaintsPolicy: v1.NodeInclusionPolicyIgnore,
},
},
TpKeyToCriticalPaths: map[string]*criticalPaths{
"zone": {{"zone2", 2}, {"zone1", 3}},
},
TpPairToMatchNum: map[topologyPair]int{
{key: "zone", value: "zone1"}: 3,
{key: "zone", value: "zone2"}: 2,
},
},
enableMatchLabelKeys: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@@ -1193,6 +1351,7 @@ func TestPreFilterState(t *testing.T) {
p := plugintesting.SetupPluginWithInformers(ctx, t, topologySpreadFunc, args, cache.NewSnapshot(tt.existingPods, tt.nodes), tt.objs)
p.(*PodTopologySpread).enableMinDomainsInPodTopologySpread = tt.enableMinDomains
p.(*PodTopologySpread).enableNodeInclusionPolicyInPodTopologySpread = tt.enableNodeInclustionPolicy
p.(*PodTopologySpread).enableMatchLabelKeysInPodTopologySpread = tt.enableMatchLabelKeys
cs := framework.NewCycleState()
if _, s := p.(*PodTopologySpread).PreFilter(ctx, cs, tt.pod); !s.IsSuccess() {
@@ -1233,7 +1392,7 @@ func TestPreFilterStateAddPod(t *testing.T) {
{
name: "node a and b both impact current min match",
preemptor: st.MakePod().Name("p").Label("foo", "").
SpreadConstraint(1, "node", v1.DoNotSchedule, fooSelector, nil, nil, nil).
SpreadConstraint(1, "node", v1.DoNotSchedule, fooSelector, nil, nil, nil, nil).
Obj(),
addedPod: st.MakePod().Name("p-a1").Node("node-a").Label("foo", "").Obj(),
existingPods: nil, // it's an empty cluster
@@ -1256,7 +1415,7 @@ func TestPreFilterStateAddPod(t *testing.T) {
{
name: "only node a impacts current min match",
preemptor: st.MakePod().Name("p").Label("foo", "").
SpreadConstraint(1, "node", v1.DoNotSchedule, fooSelector, nil, nil, nil).
SpreadConstraint(1, "node", v1.DoNotSchedule, fooSelector, nil, nil, nil, nil).
Obj(),
addedPod: st.MakePod().Name("p-a1").Node("node-a").Label("foo", "").Obj(),
existingPods: []*v1.Pod{
@@ -1281,7 +1440,7 @@ func TestPreFilterStateAddPod(t *testing.T) {
{
name: "add a pod in a different namespace doesn't change topologyKeyToMinPodsMap",
preemptor: st.MakePod().Name("p").Label("foo", "").
SpreadConstraint(1, "node", v1.DoNotSchedule, fooSelector, nil, nil, nil).
SpreadConstraint(1, "node", v1.DoNotSchedule, fooSelector, nil, nil, nil, nil).
Obj(),
addedPod: st.MakePod().Name("p-a1").Namespace("ns1").Node("node-a").Label("foo", "").Obj(),
existingPods: []*v1.Pod{
@@ -1306,7 +1465,7 @@ func TestPreFilterStateAddPod(t *testing.T) {
{
name: "add pod on non-critical node won't trigger re-calculation",
preemptor: st.MakePod().Name("p").Label("foo", "").
SpreadConstraint(1, "node", v1.DoNotSchedule, fooSelector, nil, nil, nil).
SpreadConstraint(1, "node", v1.DoNotSchedule, fooSelector, nil, nil, nil, nil).
Obj(),
addedPod: st.MakePod().Name("p-b2").Node("node-b").Label("foo", "").Obj(),
existingPods: []*v1.Pod{
@@ -1331,8 +1490,8 @@ func TestPreFilterStateAddPod(t *testing.T) {
{
name: "node a and x both impact topologyKeyToMinPodsMap on zone and node",
preemptor: st.MakePod().Name("p").Label("foo", "").
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil).
SpreadConstraint(1, "node", v1.DoNotSchedule, fooSelector, nil, nil, nil).
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil, nil).
SpreadConstraint(1, "node", v1.DoNotSchedule, fooSelector, nil, nil, nil, nil).
Obj(),
addedPod: st.MakePod().Name("p-a1").Node("node-a").Label("foo", "").Obj(),
existingPods: nil, // it's an empty cluster
@@ -1358,8 +1517,8 @@ func TestPreFilterStateAddPod(t *testing.T) {
{
name: "only node a impacts topologyKeyToMinPodsMap on zone and node",
preemptor: st.MakePod().Name("p").Label("foo", "").
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil).
SpreadConstraint(1, "node", v1.DoNotSchedule, fooSelector, nil, nil, nil).
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil, nil).
SpreadConstraint(1, "node", v1.DoNotSchedule, fooSelector, nil, nil, nil, nil).
Obj(),
addedPod: st.MakePod().Name("p-a1").Node("node-a").Label("foo", "").Obj(),
existingPods: []*v1.Pod{
@@ -1387,8 +1546,8 @@ func TestPreFilterStateAddPod(t *testing.T) {
{
name: "node a impacts topologyKeyToMinPodsMap on node, node x impacts topologyKeyToMinPodsMap on zone",
preemptor: st.MakePod().Name("p").Label("foo", "").
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil).
SpreadConstraint(1, "node", v1.DoNotSchedule, fooSelector, nil, nil, nil).
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil, nil).
SpreadConstraint(1, "node", v1.DoNotSchedule, fooSelector, nil, nil, nil, nil).
Obj(),
addedPod: st.MakePod().Name("p-a1").Node("node-a").Label("foo", "").Obj(),
existingPods: []*v1.Pod{
@@ -1420,8 +1579,8 @@ func TestPreFilterStateAddPod(t *testing.T) {
{
name: "Constraints hold different labelSelectors, node a impacts topologyKeyToMinPodsMap on zone",
preemptor: st.MakePod().Name("p").Label("foo", "").Label("bar", "").
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil).
SpreadConstraint(1, "node", v1.DoNotSchedule, barSelector, nil, nil, nil).
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil, nil).
SpreadConstraint(1, "node", v1.DoNotSchedule, barSelector, nil, nil, nil, nil).
Obj(),
addedPod: st.MakePod().Name("p-a1").Node("node-a").Label("foo", "").Obj(),
existingPods: []*v1.Pod{
@@ -1463,8 +1622,8 @@ func TestPreFilterStateAddPod(t *testing.T) {
{
name: "Constraints hold different labelSelectors, node a impacts topologyKeyToMinPodsMap on both zone and node",
preemptor: st.MakePod().Name("p").Label("foo", "").Label("bar", "").
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil).
SpreadConstraint(1, "node", v1.DoNotSchedule, barSelector, nil, nil, nil).
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil, nil).
SpreadConstraint(1, "node", v1.DoNotSchedule, barSelector, nil, nil, nil, nil).
Obj(),
addedPod: st.MakePod().Name("p-a1").Node("node-a").Label("foo", "").Label("bar", "").Obj(),
existingPods: []*v1.Pod{
@@ -1506,7 +1665,7 @@ func TestPreFilterStateAddPod(t *testing.T) {
{
name: "add a pod that doesn't match node affinity when NodeInclustionPolicy disabled",
preemptor: st.MakePod().Name("p").Label("foo", "").NodeAffinityNotIn("foo", []string{"bar"}).
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil).
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil, nil).
Obj(),
nodeIdx: 0,
addedPod: st.MakePod().Name("p-a1").Node("node-b").Label("foo", "").Label("zone", "zone2").Obj(),
@@ -1532,7 +1691,7 @@ func TestPreFilterStateAddPod(t *testing.T) {
{
name: "add a pod that doesn't match node affinity when NodeInclustionPolicy enabled",
preemptor: st.MakePod().Name("p").Label("foo", "").NodeAffinityNotIn("foo", []string{"bar"}).
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil).
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil, nil).
Obj(),
nodeIdx: 0,
addedPod: st.MakePod().Name("p-a1").Node("node-b").Label("foo", "").Label("zone", "zone2").Obj(),
@@ -1612,7 +1771,7 @@ func TestPreFilterStateRemovePod(t *testing.T) {
// So preemption is triggered.
name: "one spreadConstraint on zone, topologyKeyToMinPodsMap unchanged",
preemptor: st.MakePod().Name("p").Label("foo", "").
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil).
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("zone", "zone1").Label("node", "node-a").Obj(),
@@ -1640,7 +1799,7 @@ func TestPreFilterStateRemovePod(t *testing.T) {
{
name: "one spreadConstraint on node, topologyKeyToMinPodsMap changed",
preemptor: st.MakePod().Name("p").Label("foo", "").
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil).
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("zone", "zone1").Label("node", "node-a").Obj(),
@@ -1670,7 +1829,7 @@ func TestPreFilterStateRemovePod(t *testing.T) {
{
name: "delete an irrelevant pod won't help",
preemptor: st.MakePod().Name("p").Label("foo", "").
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil).
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("zone", "zone1").Label("node", "node-a").Obj(),
@@ -1701,7 +1860,7 @@ func TestPreFilterStateRemovePod(t *testing.T) {
{
name: "delete a non-existing pod won't help",
preemptor: st.MakePod().Name("p").Label("foo", "").
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil).
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("zone", "zone1").Label("node", "node-a").Obj(),
@@ -1732,8 +1891,8 @@ func TestPreFilterStateRemovePod(t *testing.T) {
{
name: "two spreadConstraints",
preemptor: st.MakePod().Name("p").Label("foo", "").
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil).
SpreadConstraint(1, "node", v1.DoNotSchedule, fooSelector, nil, nil, nil).
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil, nil).
SpreadConstraint(1, "node", v1.DoNotSchedule, fooSelector, nil, nil, nil, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("zone", "zone1").Label("node", "node-a").Obj(),
@@ -1811,7 +1970,7 @@ func BenchmarkFilter(b *testing.B) {
{
name: "1000nodes/single-constraint-zone",
pod: st.MakePod().Name("p").Label("foo", "").
SpreadConstraint(1, v1.LabelTopologyZone, v1.DoNotSchedule, fooSelector, nil, nil, nil).
SpreadConstraint(1, v1.LabelTopologyZone, v1.DoNotSchedule, fooSelector, nil, nil, nil, nil).
Obj(),
existingPodsNum: 10000,
allNodesNum: 1000,
@@ -1820,7 +1979,7 @@ func BenchmarkFilter(b *testing.B) {
{
name: "1000nodes/single-constraint-node",
pod: st.MakePod().Name("p").Label("foo", "").
SpreadConstraint(1, v1.LabelHostname, v1.DoNotSchedule, fooSelector, nil, nil, nil).
SpreadConstraint(1, v1.LabelHostname, v1.DoNotSchedule, fooSelector, nil, nil, nil, nil).
Obj(),
existingPodsNum: 10000,
allNodesNum: 1000,
@@ -1829,8 +1988,8 @@ func BenchmarkFilter(b *testing.B) {
{
name: "1000nodes/two-Constraints-zone-node",
pod: st.MakePod().Name("p").Label("foo", "").Label("bar", "").
SpreadConstraint(1, v1.LabelTopologyZone, v1.DoNotSchedule, fooSelector, nil, nil, nil).
SpreadConstraint(1, v1.LabelHostname, v1.DoNotSchedule, barSelector, nil, nil, nil).
SpreadConstraint(1, v1.LabelTopologyZone, v1.DoNotSchedule, fooSelector, nil, nil, nil, nil).
SpreadConstraint(1, v1.LabelHostname, v1.DoNotSchedule, barSelector, nil, nil, nil, nil).
Obj(),
existingPodsNum: 10000,
allNodesNum: 1000,
@@ -1887,7 +2046,7 @@ func TestSingleConstraint(t *testing.T) {
{
name: "no existing pods",
pod: st.MakePod().Name("p").Label("foo", "").
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil).
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("zone", "zone1").Label("node", "node-a").Obj(),
@@ -1905,7 +2064,7 @@ func TestSingleConstraint(t *testing.T) {
{
name: "no existing pods, incoming pod doesn't match itself",
pod: st.MakePod().Name("p").Label("foo", "").
SpreadConstraint(1, "zone", v1.DoNotSchedule, barSelector, nil, nil, nil).
SpreadConstraint(1, "zone", v1.DoNotSchedule, barSelector, nil, nil, nil, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("zone", "zone1").Label("node", "node-a").Obj(),
@@ -1923,7 +2082,7 @@ func TestSingleConstraint(t *testing.T) {
{
name: "existing pods in a different namespace do not count",
pod: st.MakePod().Name("p").Label("foo", "").
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil).
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("zone", "zone1").Label("node", "node-a").Obj(),
@@ -1947,7 +2106,7 @@ func TestSingleConstraint(t *testing.T) {
{
name: "pods spread across zones as 3/3, all nodes fit",
pod: st.MakePod().Name("p").Label("foo", "").
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil).
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("zone", "zone1").Label("node", "node-a").Obj(),
@@ -1975,7 +2134,7 @@ func TestSingleConstraint(t *testing.T) {
// can cause unexpected behavior
name: "pods spread across zones as 1/2 due to absence of label 'zone' on node-b",
pod: st.MakePod().Name("p").Label("foo", "").
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil).
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("zone", "zone1").Label("node", "node-a").Obj(),
@@ -1999,7 +2158,7 @@ func TestSingleConstraint(t *testing.T) {
{
name: "pod cannot be scheduled as all nodes don't have label 'rack'",
pod: st.MakePod().Name("p").Label("foo", "").
SpreadConstraint(1, "rack", v1.DoNotSchedule, fooSelector, nil, nil, nil).
SpreadConstraint(1, "rack", v1.DoNotSchedule, fooSelector, nil, nil, nil, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("zone", "zone1").Label("node", "node-a").Obj(),
@@ -2013,7 +2172,7 @@ func TestSingleConstraint(t *testing.T) {
{
name: "pods spread across nodes as 2/1/0/3, only node-x fits",
pod: st.MakePod().Name("p").Label("foo", "").
SpreadConstraint(1, "node", v1.DoNotSchedule, fooSelector, nil, nil, nil).
SpreadConstraint(1, "node", v1.DoNotSchedule, fooSelector, nil, nil, nil, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("zone", "zone1").Label("node", "node-a").Obj(),
@@ -2039,7 +2198,7 @@ func TestSingleConstraint(t *testing.T) {
{
name: "pods spread across nodes as 2/1/0/3, maxSkew is 2, node-b and node-x fit",
pod: st.MakePod().Name("p").Label("foo", "").
SpreadConstraint(2, "node", v1.DoNotSchedule, fooSelector, nil, nil, nil).
SpreadConstraint(2, "node", v1.DoNotSchedule, fooSelector, nil, nil, nil, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("zone", "zone1").Label("node", "node-a").Obj(),
@@ -2069,7 +2228,7 @@ func TestSingleConstraint(t *testing.T) {
// as the incoming pod doesn't have label "foo"
name: "pods spread across nodes as 2/1/0/3, but pod doesn't match itself",
pod: st.MakePod().Name("p").Label("bar", "").
SpreadConstraint(1, "node", v1.DoNotSchedule, fooSelector, nil, nil, nil).
SpreadConstraint(1, "node", v1.DoNotSchedule, fooSelector, nil, nil, nil, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("zone", "zone1").Label("node", "node-a").Obj(),
@@ -2101,7 +2260,7 @@ func TestSingleConstraint(t *testing.T) {
name: "incoming pod has nodeAffinity, pods spread as 2/~1~/~0~/3, hence node-a fits",
pod: st.MakePod().Name("p").Label("foo", "").
NodeAffinityIn("node", []string{"node-a", "node-y"}).
SpreadConstraint(1, "node", v1.DoNotSchedule, fooSelector, nil, nil, nil).
SpreadConstraint(1, "node", v1.DoNotSchedule, fooSelector, nil, nil, nil, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("zone", "zone1").Label("node", "node-a").Obj(),
@@ -2127,7 +2286,7 @@ func TestSingleConstraint(t *testing.T) {
{
name: "terminating Pods should be excluded",
pod: st.MakePod().Name("p").Label("foo", "").
SpreadConstraint(1, "node", v1.DoNotSchedule, fooSelector, nil, nil, nil).
SpreadConstraint(1, "node", v1.DoNotSchedule, fooSelector, nil, nil, nil, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("node", "node-a").Obj(),
@@ -2147,7 +2306,7 @@ func TestSingleConstraint(t *testing.T) {
name: "incoming pod has nodeAffinity, pods spread as 0/~2~/0/1, hence node-a fits",
pod: st.MakePod().Name("p").Label("foo", "").
NodeAffinityNotIn("node", []string{"node-b"}).
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil).
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("zone", "zone1").Label("node", "node-a").Obj(),
@@ -2177,6 +2336,7 @@ func TestSingleConstraint(t *testing.T) {
pointer.Int32(4), // larger than the number of domains(3)
nil,
nil,
nil,
).Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("node", "node-a").Obj(),
@@ -2207,6 +2367,7 @@ func TestSingleConstraint(t *testing.T) {
pointer.Int32(2), // smaller than the number of domains(3)
nil,
nil,
nil,
).Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("node", "node-a").Obj(),
@@ -2237,6 +2398,7 @@ func TestSingleConstraint(t *testing.T) {
pointer.Int32(3), // larger than the number of domains(2)
nil,
nil,
nil,
).Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("zone", "zone1").Label("node", "node-a").Obj(),
@@ -2267,6 +2429,7 @@ func TestSingleConstraint(t *testing.T) {
pointer.Int32(1), // smaller than the number of domains(2)
nil,
nil,
nil,
).Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("zone", "zone1").Label("node", "node-a").Obj(),
@@ -2292,7 +2455,7 @@ func TestSingleConstraint(t *testing.T) {
name: "NodeAffinityPolicy honored with labelSelectors",
pod: st.MakePod().Name("p").Label("foo", "").
NodeSelector(map[string]string{"foo": ""}).
SpreadConstraint(1, "node", v1.DoNotSchedule, fooSelector, nil, nil, nil).
SpreadConstraint(1, "node", v1.DoNotSchedule, fooSelector, nil, nil, nil, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("node", "node-a").Label("foo", "").Obj(),
@@ -2318,7 +2481,7 @@ func TestSingleConstraint(t *testing.T) {
name: "NodeAffinityPolicy ignored with labelSelectors",
pod: st.MakePod().Name("p").Label("foo", "").
NodeSelector(map[string]string{"foo": ""}).
SpreadConstraint(1, "node", v1.DoNotSchedule, fooSelector, nil, &ignorePolicy, nil).
SpreadConstraint(1, "node", v1.DoNotSchedule, fooSelector, nil, &ignorePolicy, nil, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("node", "node-a").Label("foo", "").Obj(),
@@ -2344,7 +2507,7 @@ func TestSingleConstraint(t *testing.T) {
name: "NodeAffinityPolicy honored with nodeAffinity",
pod: st.MakePod().Name("p").Label("foo", "").
NodeAffinityIn("foo", []string{""}).
SpreadConstraint(1, "node", v1.DoNotSchedule, fooSelector, nil, nil, nil).
SpreadConstraint(1, "node", v1.DoNotSchedule, fooSelector, nil, nil, nil, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("node", "node-a").Label("foo", "").Obj(),
@@ -2370,7 +2533,7 @@ func TestSingleConstraint(t *testing.T) {
name: "NodeAffinityPolicy ignored with labelSelectors",
pod: st.MakePod().Name("p").Label("foo", "").
NodeAffinityIn("foo", []string{""}).
SpreadConstraint(1, "node", v1.DoNotSchedule, fooSelector, nil, &ignorePolicy, nil).
SpreadConstraint(1, "node", v1.DoNotSchedule, fooSelector, nil, &ignorePolicy, nil, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("node", "node-a").Label("foo", "").Obj(),
@@ -2395,7 +2558,7 @@ func TestSingleConstraint(t *testing.T) {
// pods spread across node as 1/1/0/~0~
name: "NodeTaintsPolicy honored",
pod: st.MakePod().Name("p").Label("foo", "").
SpreadConstraint(1, "node", v1.DoNotSchedule, fooSelector, nil, nil, &honorPolicy).
SpreadConstraint(1, "node", v1.DoNotSchedule, fooSelector, nil, nil, &honorPolicy, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("node", "node-a").Label("foo", "").Obj(),
@@ -2420,7 +2583,7 @@ func TestSingleConstraint(t *testing.T) {
// pods spread across node as 1/1/0/~1~
name: "NodeTaintsPolicy ignored",
pod: st.MakePod().Name("p").Label("foo", "").
SpreadConstraint(1, "node", v1.DoNotSchedule, fooSelector, nil, nil, nil).
SpreadConstraint(1, "node", v1.DoNotSchedule, fooSelector, nil, nil, nil, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("node", "node-a").Label("foo", "").Obj(),
@@ -2480,8 +2643,8 @@ func TestMultipleConstraints(t *testing.T) {
// intersection of (1) and (2) returns node-x
name: "two Constraints on zone and node, spreads = [3/3, 2/1/0/3]",
pod: st.MakePod().Name("p").Label("foo", "").
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil).
SpreadConstraint(1, "node", v1.DoNotSchedule, fooSelector, nil, nil, nil).
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil, nil).
SpreadConstraint(1, "node", v1.DoNotSchedule, fooSelector, nil, nil, nil, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("zone", "zone1").Label("node", "node-a").Obj(),
@@ -2510,8 +2673,8 @@ func TestMultipleConstraints(t *testing.T) {
// intersection of (1) and (2) returns no node
name: "two Constraints on zone and node, spreads = [3/4, 2/1/0/4]",
pod: st.MakePod().Name("p").Label("foo", "").
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil).
SpreadConstraint(1, "node", v1.DoNotSchedule, fooSelector, nil, nil, nil).
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil, nil).
SpreadConstraint(1, "node", v1.DoNotSchedule, fooSelector, nil, nil, nil, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("zone", "zone1").Label("node", "node-a").Obj(),
@@ -2541,8 +2704,8 @@ func TestMultipleConstraints(t *testing.T) {
// intersection of (1) and (2) returns node-x
name: "Constraints hold different labelSelectors, spreads = [1/0, 1/0/0/1]",
pod: st.MakePod().Name("p").Label("foo", "").Label("bar", "").
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil).
SpreadConstraint(1, "node", v1.DoNotSchedule, barSelector, nil, nil, nil).
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil, nil).
SpreadConstraint(1, "node", v1.DoNotSchedule, barSelector, nil, nil, nil, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("zone", "zone1").Label("node", "node-a").Obj(),
@@ -2567,8 +2730,8 @@ func TestMultipleConstraints(t *testing.T) {
// intersection of (1) and (2) returns no node
name: "Constraints hold different labelSelectors, spreads = [1/0, 0/0/1/1]",
pod: st.MakePod().Name("p").Label("foo", "").Label("bar", "").
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil).
SpreadConstraint(1, "node", v1.DoNotSchedule, barSelector, nil, nil, nil).
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil, nil).
SpreadConstraint(1, "node", v1.DoNotSchedule, barSelector, nil, nil, nil, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("zone", "zone1").Label("node", "node-a").Obj(),
@@ -2594,8 +2757,8 @@ func TestMultipleConstraints(t *testing.T) {
// intersection of (1) and (2) returns node-b
name: "Constraints hold different labelSelectors, spreads = [2/3, 1/0/0/1]",
pod: st.MakePod().Name("p").Label("foo", "").Label("bar", "").
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil).
SpreadConstraint(1, "node", v1.DoNotSchedule, barSelector, nil, nil, nil).
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil, nil).
SpreadConstraint(1, "node", v1.DoNotSchedule, barSelector, nil, nil, nil, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("zone", "zone1").Label("node", "node-a").Obj(),
@@ -2623,8 +2786,8 @@ func TestMultipleConstraints(t *testing.T) {
// intersection of (1) and (2) returns node-a and node-b
name: "Constraints hold different labelSelectors but pod doesn't match itself on 'zone' constraint",
pod: st.MakePod().Name("p").Label("bar", "").
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil).
SpreadConstraint(1, "node", v1.DoNotSchedule, barSelector, nil, nil, nil).
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil, nil).
SpreadConstraint(1, "node", v1.DoNotSchedule, barSelector, nil, nil, nil, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("zone", "zone1").Label("node", "node-a").Obj(),
@@ -2650,8 +2813,8 @@ func TestMultipleConstraints(t *testing.T) {
// intersection of (1) and (2) returns node-b
name: "two Constraints on zone and node, absence of label 'node' on node-x, spreads = [1/1, 1/0/0/1]",
pod: st.MakePod().Name("p").Label("foo", "").
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil).
SpreadConstraint(1, "node", v1.DoNotSchedule, fooSelector, nil, nil, nil).
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil, nil).
SpreadConstraint(1, "node", v1.DoNotSchedule, fooSelector, nil, nil, nil, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("zone", "zone1").Label("node", "node-a").Obj(),
@@ -2677,8 +2840,8 @@ func TestMultipleConstraints(t *testing.T) {
name: "two node inclusion Constraints, zone: honor/ignore, node: ignore/ignore",
pod: st.MakePod().Name("p").Label("foo", "").
NodeSelector(map[string]string{"foo": ""}).
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil).
SpreadConstraint(1, "node", v1.DoNotSchedule, fooSelector, nil, &ignorePolicy, nil).
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil, nil).
SpreadConstraint(1, "node", v1.DoNotSchedule, fooSelector, nil, &ignorePolicy, nil, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("zone", "zone1").Label("node", "node-a").Label("foo", "").Obj(),
@@ -2705,8 +2868,8 @@ func TestMultipleConstraints(t *testing.T) {
// intersection of (1) and (2) returns node-x
name: "two node inclusion Constraints, zone: honor/honor, node: honor/ignore",
pod: st.MakePod().Name("p").Label("foo", "").
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, &honorPolicy).
SpreadConstraint(1, "node", v1.DoNotSchedule, fooSelector, nil, nil, nil).
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, &honorPolicy, nil).
SpreadConstraint(1, "node", v1.DoNotSchedule, fooSelector, nil, nil, nil, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("zone", "zone1").Label("node", "node-a").Label("foo", "").Obj(),
@@ -2734,8 +2897,8 @@ func TestMultipleConstraints(t *testing.T) {
name: "two node inclusion Constraints, zone: honor/ignore, node: honor/ignore",
pod: st.MakePod().Name("p").Label("foo", "").
NodeSelector(map[string]string{"foo": ""}).
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil).
SpreadConstraint(1, "node", v1.DoNotSchedule, fooSelector, nil, nil, nil).
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, nil, nil).
SpreadConstraint(1, "node", v1.DoNotSchedule, fooSelector, nil, nil, nil, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("zone", "zone1").Label("node", "node-a").Label("foo", "").Obj(),
@@ -2763,8 +2926,8 @@ func TestMultipleConstraints(t *testing.T) {
name: "two node inclusion Constraints, zone: honor/honor, node: ignore/ignore",
pod: st.MakePod().Name("p").Label("foo", "").
NodeSelector(map[string]string{"foo": ""}).
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, &honorPolicy).
SpreadConstraint(1, "node", v1.DoNotSchedule, fooSelector, nil, &ignorePolicy, nil).
SpreadConstraint(1, "zone", v1.DoNotSchedule, fooSelector, nil, nil, &honorPolicy, nil).
SpreadConstraint(1, "node", v1.DoNotSchedule, fooSelector, nil, &ignorePolicy, nil, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("zone", "zone1").Label("node", "node-a").Label("foo", "").Obj(),

View File

@@ -64,6 +64,7 @@ type PodTopologySpread struct {
statefulSets appslisters.StatefulSetLister
enableMinDomainsInPodTopologySpread bool
enableNodeInclusionPolicyInPodTopologySpread bool
enableMatchLabelKeysInPodTopologySpread bool
}
var _ framework.PreFilterPlugin = &PodTopologySpread{}
@@ -98,6 +99,7 @@ func New(plArgs runtime.Object, h framework.Handle, fts feature.Features) (frame
defaultConstraints: args.DefaultConstraints,
enableMinDomainsInPodTopologySpread: fts.EnableMinDomainsInPodTopologySpread,
enableNodeInclusionPolicyInPodTopologySpread: fts.EnableNodeInclusionPolicyInPodTopologySpread,
enableMatchLabelKeysInPodTopologySpread: fts.EnableMatchLabelKeysInPodTopologySpread,
}
if args.DefaultingType == config.SystemDefaulting {
pl.defaultConstraints = systemDefaultConstraints

View File

@@ -59,11 +59,10 @@ func (s *preScoreState) Clone() framework.StateData {
func (pl *PodTopologySpread) initPreScoreState(s *preScoreState, pod *v1.Pod, filteredNodes []*v1.Node, requireAllTopologies bool) error {
var err error
if len(pod.Spec.TopologySpreadConstraints) > 0 {
s.Constraints, err = filterTopologySpreadConstraints(
s.Constraints, err = pl.filterTopologySpreadConstraints(
pod.Spec.TopologySpreadConstraints,
pod.Labels,
v1.ScheduleAnyway,
pl.enableMinDomainsInPodTopologySpread,
pl.enableNodeInclusionPolicyInPodTopologySpread,
)
if err != nil {
return fmt.Errorf("obtaining pod's soft topology spread constraints: %w", err)

View File

@@ -55,8 +55,8 @@ func TestPreScoreStateEmptyNodes(t *testing.T) {
{
name: "normal case",
pod: st.MakePod().Name("p").Label("foo", "").
SpreadConstraint(1, "zone", v1.ScheduleAnyway, fooSelector, nil, nil, nil).
SpreadConstraint(1, v1.LabelHostname, v1.ScheduleAnyway, fooSelector, nil, nil, nil).
SpreadConstraint(1, "zone", v1.ScheduleAnyway, fooSelector, nil, nil, nil, nil).
SpreadConstraint(1, v1.LabelHostname, v1.ScheduleAnyway, fooSelector, nil, nil, nil, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("zone", "zone1").Label(v1.LabelHostname, "node-a").Obj(),
@@ -96,8 +96,8 @@ func TestPreScoreStateEmptyNodes(t *testing.T) {
{
name: "node-x doesn't have label zone",
pod: st.MakePod().Name("p").Label("foo", "").
SpreadConstraint(1, "zone", v1.ScheduleAnyway, fooSelector, nil, nil, nil).
SpreadConstraint(1, v1.LabelHostname, v1.ScheduleAnyway, barSelector, nil, nil, nil).
SpreadConstraint(1, "zone", v1.ScheduleAnyway, fooSelector, nil, nil, nil, nil).
SpreadConstraint(1, v1.LabelHostname, v1.ScheduleAnyway, barSelector, nil, nil, nil, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("zone", "zone1").Label(v1.LabelHostname, "node-a").Obj(),
@@ -253,8 +253,8 @@ func TestPreScoreStateEmptyNodes(t *testing.T) {
name: "default constraints and a replicaset, but pod has constraints",
pod: st.MakePod().Name("p").Namespace("default").Label("foo", "bar").Label("baz", "sup").
OwnerReference("rs1", appsv1.SchemeGroupVersion.WithKind("ReplicaSet")).
SpreadConstraint(1, "zone", v1.DoNotSchedule, barSelector, nil, nil, nil).
SpreadConstraint(2, "planet", v1.ScheduleAnyway, st.MakeLabelSelector().Label("baz", "sup").Obj(), nil, nil, nil).
SpreadConstraint(1, "zone", v1.DoNotSchedule, barSelector, nil, nil, nil, nil).
SpreadConstraint(2, "planet", v1.ScheduleAnyway, st.MakeLabelSelector().Label("baz", "sup").Obj(), nil, nil, nil, nil).
Obj(),
config: config.PodTopologySpreadArgs{
DefaultConstraints: []v1.TopologySpreadConstraint{
@@ -294,7 +294,7 @@ func TestPreScoreStateEmptyNodes(t *testing.T) {
name: "NodeAffinityPolicy honored with labelSelectors",
pod: st.MakePod().Name("p").Label("foo", "").
NodeSelector(map[string]string{"foo": ""}).
SpreadConstraint(1, "zone", v1.ScheduleAnyway, barSelector, nil, nil, nil).
SpreadConstraint(1, "zone", v1.ScheduleAnyway, barSelector, nil, nil, nil, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("zone", "zone1").Label("foo", "").Label(v1.LabelHostname, "node-a").Obj(),
@@ -328,7 +328,7 @@ func TestPreScoreStateEmptyNodes(t *testing.T) {
name: "NodeAffinityPolicy ignored with labelSelectors",
pod: st.MakePod().Name("p").Label("foo", "").
NodeSelector(map[string]string{"foo": ""}).
SpreadConstraint(1, "zone", v1.ScheduleAnyway, barSelector, nil, &ignorePolicy, nil).
SpreadConstraint(1, "zone", v1.ScheduleAnyway, barSelector, nil, &ignorePolicy, nil, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("zone", "zone1").Label("foo", "").Label(v1.LabelHostname, "node-a").Obj(),
@@ -362,7 +362,7 @@ func TestPreScoreStateEmptyNodes(t *testing.T) {
name: "NodeAffinityPolicy honored with nodeAffinity",
pod: st.MakePod().Name("p").Label("foo", "").
NodeAffinityIn("foo", []string{""}).
SpreadConstraint(1, "zone", v1.ScheduleAnyway, barSelector, nil, nil, nil).
SpreadConstraint(1, "zone", v1.ScheduleAnyway, barSelector, nil, nil, nil, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("zone", "zone1").Label("foo", "").Label(v1.LabelHostname, "node-a").Obj(),
@@ -396,7 +396,7 @@ func TestPreScoreStateEmptyNodes(t *testing.T) {
name: "NodeAffinityPolicy ignored with nodeAffinity",
pod: st.MakePod().Name("p").Label("foo", "").
NodeAffinityIn("foo", []string{""}).
SpreadConstraint(1, "zone", v1.ScheduleAnyway, barSelector, nil, &ignorePolicy, nil).
SpreadConstraint(1, "zone", v1.ScheduleAnyway, barSelector, nil, &ignorePolicy, nil, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("zone", "zone1").Label("foo", "").Label(v1.LabelHostname, "node-a").Obj(),
@@ -429,7 +429,7 @@ func TestPreScoreStateEmptyNodes(t *testing.T) {
{
name: "NodeTaintsPolicy honored",
pod: st.MakePod().Name("p").Label("foo", "").
SpreadConstraint(1, "zone", v1.ScheduleAnyway, barSelector, nil, nil, &honorPolicy).
SpreadConstraint(1, "zone", v1.ScheduleAnyway, barSelector, nil, nil, &honorPolicy, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("zone", "zone1").Label("foo", "").Label(v1.LabelHostname, "node-a").Obj(),
@@ -462,7 +462,7 @@ func TestPreScoreStateEmptyNodes(t *testing.T) {
{
name: "NodeTaintsPolicy ignored",
pod: st.MakePod().Name("p").Label("foo", "").
SpreadConstraint(1, "zone", v1.ScheduleAnyway, barSelector, nil, nil, nil).
SpreadConstraint(1, "zone", v1.ScheduleAnyway, barSelector, nil, nil, nil, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("zone", "zone1").Label("foo", "").Label(v1.LabelHostname, "node-a").Obj(),
@@ -537,6 +537,7 @@ func TestPodTopologySpreadScore(t *testing.T) {
objs []runtime.Object
want framework.NodeScoreList
enableNodeInclustionPolicy bool
enableMatchLabelKeys bool
}{
// Explanation on the Legend:
// a) X/Y means there are X matching pods on node1 and Y on node2, both nodes are candidates
@@ -547,7 +548,7 @@ func TestPodTopologySpreadScore(t *testing.T) {
{
name: "one constraint on node, no existing pods",
pod: st.MakePod().Name("p").Label("foo", "").
SpreadConstraint(1, v1.LabelHostname, v1.ScheduleAnyway, fooSelector, nil, nil, nil).
SpreadConstraint(1, v1.LabelHostname, v1.ScheduleAnyway, fooSelector, nil, nil, nil, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label(v1.LabelHostname, "node-a").Obj(),
@@ -562,7 +563,7 @@ func TestPodTopologySpreadScore(t *testing.T) {
// if there is only one candidate node, it should be scored to 100
name: "one constraint on node, only one node is candidate",
pod: st.MakePod().Name("p").Label("foo", "").
SpreadConstraint(1, v1.LabelHostname, v1.ScheduleAnyway, fooSelector, nil, nil, nil).
SpreadConstraint(1, v1.LabelHostname, v1.ScheduleAnyway, fooSelector, nil, nil, nil, nil).
Obj(),
existingPods: []*v1.Pod{
st.MakePod().Name("p-a1").Node("node-a").Label("foo", "").Obj(),
@@ -582,7 +583,7 @@ func TestPodTopologySpreadScore(t *testing.T) {
{
name: "one constraint on node, all nodes have the same number of matching pods",
pod: st.MakePod().Name("p").Label("foo", "").
SpreadConstraint(1, v1.LabelHostname, v1.ScheduleAnyway, fooSelector, nil, nil, nil).
SpreadConstraint(1, v1.LabelHostname, v1.ScheduleAnyway, fooSelector, nil, nil, nil, nil).
Obj(),
existingPods: []*v1.Pod{
st.MakePod().Name("p-a1").Node("node-a").Label("foo", "").Obj(),
@@ -601,7 +602,7 @@ func TestPodTopologySpreadScore(t *testing.T) {
// matching pods spread as 2/1/0/3.
name: "one constraint on node, all 4 nodes are candidates",
pod: st.MakePod().Name("p").Label("foo", "").
SpreadConstraint(1, v1.LabelHostname, v1.ScheduleAnyway, fooSelector, nil, nil, nil).
SpreadConstraint(1, v1.LabelHostname, v1.ScheduleAnyway, fooSelector, nil, nil, nil, nil).
Obj(),
existingPods: []*v1.Pod{
st.MakePod().Name("p-a1").Node("node-a").Label("foo", "").Obj(),
@@ -628,7 +629,7 @@ func TestPodTopologySpreadScore(t *testing.T) {
{
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, fooSelector, nil, nil, nil).
SpreadConstraint(2, v1.LabelHostname, v1.ScheduleAnyway, fooSelector, nil, nil, nil, nil).
Obj(),
// matching pods spread as 2/1/0/3.
existingPods: []*v1.Pod{
@@ -656,7 +657,7 @@ func TestPodTopologySpreadScore(t *testing.T) {
{
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, fooSelector, nil, nil, nil).
SpreadConstraint(3, v1.LabelHostname, v1.ScheduleAnyway, fooSelector, nil, nil, nil, nil).
Obj(),
existingPods: []*v1.Pod{
// matching pods spread as 4/3/2/1.
@@ -723,7 +724,7 @@ func TestPodTopologySpreadScore(t *testing.T) {
// 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", "").
SpreadConstraint(1, v1.LabelHostname, v1.ScheduleAnyway, fooSelector, nil, nil, nil).
SpreadConstraint(1, v1.LabelHostname, v1.ScheduleAnyway, fooSelector, nil, nil, nil, nil).
Obj(),
existingPods: []*v1.Pod{
st.MakePod().Name("p-a1").Node("node-a").Label("foo", "").Obj(),
@@ -755,7 +756,7 @@ func TestPodTopologySpreadScore(t *testing.T) {
// matching pods spread as 4/?2?/1/~3~, total = 4+?+1 = 5 (as node2 is problematic)
name: "one constraint on node, 3 out of 4 nodes are candidates, one node doesn't match topology key",
pod: st.MakePod().Name("p").Label("foo", "").
SpreadConstraint(1, v1.LabelHostname, v1.ScheduleAnyway, fooSelector, nil, nil, nil).
SpreadConstraint(1, v1.LabelHostname, v1.ScheduleAnyway, fooSelector, nil, nil, nil, nil).
Obj(),
existingPods: []*v1.Pod{
st.MakePod().Name("p-a1").Node("node-a").Label("foo", "").Obj(),
@@ -787,7 +788,7 @@ func TestPodTopologySpreadScore(t *testing.T) {
// matching pods spread as 4/2/1/~3~
name: "one constraint on zone, 3 out of 4 nodes are candidates",
pod: st.MakePod().Name("p").Label("foo", "").
SpreadConstraint(1, "zone", v1.ScheduleAnyway, fooSelector, nil, nil, nil).
SpreadConstraint(1, "zone", v1.ScheduleAnyway, fooSelector, nil, nil, nil, nil).
Obj(),
existingPods: []*v1.Pod{
st.MakePod().Name("p-a1").Node("node-a").Label("foo", "").Obj(),
@@ -819,8 +820,8 @@ func TestPodTopologySpreadScore(t *testing.T) {
// matching pods spread as 2/~1~/2/~4~.
name: "two Constraints on zone and node, 2 out of 4 nodes are candidates",
pod: st.MakePod().Name("p").Label("foo", "").
SpreadConstraint(1, "zone", v1.ScheduleAnyway, fooSelector, nil, nil, nil).
SpreadConstraint(1, v1.LabelHostname, v1.ScheduleAnyway, fooSelector, nil, nil, nil).
SpreadConstraint(1, "zone", v1.ScheduleAnyway, fooSelector, nil, nil, nil, nil).
SpreadConstraint(1, v1.LabelHostname, v1.ScheduleAnyway, fooSelector, nil, nil, nil, nil).
Obj(),
existingPods: []*v1.Pod{
st.MakePod().Name("p-a1").Node("node-a").Label("foo", "").Obj(),
@@ -859,8 +860,8 @@ func TestPodTopologySpreadScore(t *testing.T) {
// For the second constraint (node): the matching pods spread as 0/1/0/1
name: "two Constraints on zone and node, with different labelSelectors",
pod: st.MakePod().Name("p").Label("foo", "").Label("bar", "").
SpreadConstraint(1, "zone", v1.ScheduleAnyway, fooSelector, nil, nil, nil).
SpreadConstraint(1, v1.LabelHostname, v1.ScheduleAnyway, barSelector, nil, nil, nil).
SpreadConstraint(1, "zone", v1.ScheduleAnyway, fooSelector, nil, nil, nil, nil).
SpreadConstraint(1, v1.LabelHostname, v1.ScheduleAnyway, barSelector, nil, nil, nil, nil).
Obj(),
existingPods: []*v1.Pod{
st.MakePod().Name("p-a1").Node("node-a").Label("foo", "").Obj(),
@@ -887,8 +888,8 @@ func TestPodTopologySpreadScore(t *testing.T) {
// For the second constraint (node): the matching pods spread as 0/1/0/1
name: "two Constraints on zone and node, with different labelSelectors, some nodes have 0 pods",
pod: st.MakePod().Name("p").Label("foo", "").Label("bar", "").
SpreadConstraint(1, "zone", v1.ScheduleAnyway, fooSelector, nil, nil, nil).
SpreadConstraint(1, v1.LabelHostname, v1.ScheduleAnyway, barSelector, nil, nil, nil).
SpreadConstraint(1, "zone", v1.ScheduleAnyway, fooSelector, nil, nil, nil, nil).
SpreadConstraint(1, v1.LabelHostname, v1.ScheduleAnyway, barSelector, nil, nil, nil, nil).
Obj(),
existingPods: []*v1.Pod{
st.MakePod().Name("p-b1").Node("node-b").Label("bar", "").Obj(),
@@ -914,8 +915,8 @@ func TestPodTopologySpreadScore(t *testing.T) {
// For the second constraint (node): the matching pods spread as 0/1/0/~1~
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", "").
SpreadConstraint(1, "zone", v1.ScheduleAnyway, fooSelector, nil, nil, nil).
SpreadConstraint(1, v1.LabelHostname, v1.ScheduleAnyway, barSelector, nil, nil, nil).
SpreadConstraint(1, "zone", v1.ScheduleAnyway, fooSelector, nil, nil, nil, nil).
SpreadConstraint(1, v1.LabelHostname, v1.ScheduleAnyway, barSelector, nil, nil, nil, nil).
Obj(),
existingPods: []*v1.Pod{
st.MakePod().Name("p-a1").Node("node-a").Label("foo", "").Obj(),
@@ -940,7 +941,7 @@ func TestPodTopologySpreadScore(t *testing.T) {
{
name: "existing pods in a different namespace do not count",
pod: st.MakePod().Name("p").Label("foo", "").
SpreadConstraint(1, v1.LabelHostname, v1.ScheduleAnyway, fooSelector, nil, nil, nil).
SpreadConstraint(1, v1.LabelHostname, v1.ScheduleAnyway, fooSelector, nil, nil, nil, nil).
Obj(),
existingPods: []*v1.Pod{
st.MakePod().Name("p-a1").Namespace("ns1").Node("node-a").Label("foo", "").Obj(),
@@ -960,7 +961,7 @@ func TestPodTopologySpreadScore(t *testing.T) {
{
name: "terminating Pods should be excluded",
pod: st.MakePod().Name("p").Label("foo", "").
SpreadConstraint(1, v1.LabelHostname, v1.ScheduleAnyway, fooSelector, nil, nil, nil).
SpreadConstraint(1, v1.LabelHostname, v1.ScheduleAnyway, fooSelector, nil, nil, nil, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label(v1.LabelHostname, "node-a").Obj(),
@@ -987,6 +988,7 @@ func TestPodTopologySpreadScore(t *testing.T) {
pointer.Int32(10), // larger than the number of domains(3)
nil,
nil,
nil,
).Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("node", "node-a").Obj(),
@@ -1010,7 +1012,7 @@ func TestPodTopologySpreadScore(t *testing.T) {
name: "NodeAffinityPolicy honoed with labelSelectors",
pod: st.MakePod().Name("p").Label("foo", "").
NodeSelector(map[string]string{"foo": ""}).
SpreadConstraint(1, "node", v1.ScheduleAnyway, fooSelector, nil, nil, nil).
SpreadConstraint(1, "node", v1.ScheduleAnyway, fooSelector, nil, nil, nil, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("node", "node-a").Label("foo", "").Obj(),
@@ -1034,7 +1036,7 @@ func TestPodTopologySpreadScore(t *testing.T) {
name: "NodeAffinityPolicy ignored with labelSelectors",
pod: st.MakePod().Name("p").Label("foo", "").
NodeSelector(map[string]string{"foo": ""}).
SpreadConstraint(1, "node", v1.ScheduleAnyway, fooSelector, nil, &ignorePolicy, nil).
SpreadConstraint(1, "node", v1.ScheduleAnyway, fooSelector, nil, &ignorePolicy, nil, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("node", "node-a").Label("foo", "").Obj(),
@@ -1058,7 +1060,7 @@ func TestPodTopologySpreadScore(t *testing.T) {
name: "NodeAffinityPolicy honoed with nodeAffinity",
pod: st.MakePod().Name("p").Label("foo", "").
NodeAffinityIn("foo", []string{""}).
SpreadConstraint(1, "node", v1.ScheduleAnyway, fooSelector, nil, nil, nil).
SpreadConstraint(1, "node", v1.ScheduleAnyway, fooSelector, nil, nil, nil, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("node", "node-a").Label("foo", "").Obj(),
@@ -1082,7 +1084,7 @@ func TestPodTopologySpreadScore(t *testing.T) {
name: "NodeAffinityPolicy ignored with nodeAffinity",
pod: st.MakePod().Name("p").Label("foo", "").
NodeAffinityIn("foo", []string{""}).
SpreadConstraint(1, "node", v1.ScheduleAnyway, fooSelector, nil, &ignorePolicy, nil).
SpreadConstraint(1, "node", v1.ScheduleAnyway, fooSelector, nil, &ignorePolicy, nil, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("node", "node-a").Label("foo", "").Obj(),
@@ -1105,7 +1107,7 @@ func TestPodTopologySpreadScore(t *testing.T) {
{
name: "NodeTaintsPolicy honored",
pod: st.MakePod().Name("p").Label("foo", "").
SpreadConstraint(1, "node", v1.ScheduleAnyway, fooSelector, nil, nil, &honorPolicy).
SpreadConstraint(1, "node", v1.ScheduleAnyway, fooSelector, nil, nil, &honorPolicy, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("node", "node-a").Obj(),
@@ -1128,7 +1130,7 @@ func TestPodTopologySpreadScore(t *testing.T) {
{
name: "NodeTaintsPolicy ignored",
pod: st.MakePod().Name("p").Label("foo", "").
SpreadConstraint(1, "node", v1.ScheduleAnyway, fooSelector, nil, nil, nil).
SpreadConstraint(1, "node", v1.ScheduleAnyway, fooSelector, nil, nil, nil, nil).
Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("node", "node-a").Obj(),
@@ -1148,6 +1150,85 @@ func TestPodTopologySpreadScore(t *testing.T) {
},
enableNodeInclustionPolicy: true,
},
{
name: "matchLabelKeys ignored when feature gate disabled",
pod: st.MakePod().Name("p").Label("foo", "").Label("bar", "").Label("baz", "").
SpreadConstraint(1, "zone", v1.ScheduleAnyway, fooSelector, nil, nil, nil, []string{"baz"}).
SpreadConstraint(1, v1.LabelHostname, v1.ScheduleAnyway, barSelector, nil, nil, nil, []string{"baz"}).
Obj(),
existingPods: []*v1.Pod{
st.MakePod().Name("p-a1").Node("node-a").Label("foo", "").Obj(),
st.MakePod().Name("p-b1").Node("node-b").Label("foo", "").Label("bar", "").Obj(),
st.MakePod().Name("p-y1").Node("node-c").Label("foo", "").Obj(),
st.MakePod().Name("p-y2").Node("node-c").Label("bar", "").Obj(),
},
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("zone", "zone1").Label(v1.LabelHostname, "node-a").Obj(),
st.MakeNode().Name("node-b").Label("zone", "zone1").Label(v1.LabelHostname, "node-b").Obj(),
st.MakeNode().Name("node-c").Label("zone", "zone2").Label(v1.LabelHostname, "node-c").Obj(),
st.MakeNode().Name("node-d").Label("zone", "zone2").Label(v1.LabelHostname, "node-d").Obj(),
},
want: []framework.NodeScore{
{Name: "node-a", Score: 60},
{Name: "node-b", Score: 20},
{Name: "node-c", Score: 60},
{Name: "node-d", Score: 100},
},
enableMatchLabelKeys: false,
},
{
name: "matchLabelKeys ANDed with LabelSelector when LabelSelector is empty",
pod: st.MakePod().Name("p").Label("foo", "").Label("bar", "").
SpreadConstraint(1, "zone", v1.ScheduleAnyway, st.MakeLabelSelector().Obj(), nil, nil, nil, []string{"foo"}).
SpreadConstraint(1, v1.LabelHostname, v1.ScheduleAnyway, st.MakeLabelSelector().Obj(), nil, nil, nil, []string{"bar"}).
Obj(),
existingPods: []*v1.Pod{
st.MakePod().Name("p-a1").Node("node-a").Label("foo", "").Obj(),
st.MakePod().Name("p-b1").Node("node-b").Label("foo", "").Label("bar", "").Obj(),
st.MakePod().Name("p-y1").Node("node-c").Label("foo", "").Obj(),
st.MakePod().Name("p-y2").Node("node-c").Label("bar", "").Obj(),
},
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("zone", "zone1").Label(v1.LabelHostname, "node-a").Obj(),
st.MakeNode().Name("node-b").Label("zone", "zone1").Label(v1.LabelHostname, "node-b").Obj(),
st.MakeNode().Name("node-c").Label("zone", "zone2").Label(v1.LabelHostname, "node-c").Obj(),
st.MakeNode().Name("node-d").Label("zone", "zone2").Label(v1.LabelHostname, "node-d").Obj(),
},
want: []framework.NodeScore{
{Name: "node-a", Score: 60},
{Name: "node-b", Score: 20},
{Name: "node-c", Score: 60},
{Name: "node-d", Score: 100},
},
enableMatchLabelKeys: true,
},
{
name: "matchLabelKeys ANDed with LabelSelector when LabelSelector isn't empty",
pod: st.MakePod().Name("p").Label("foo", "").Label("bar", "").Label("baz", "").
SpreadConstraint(1, "zone", v1.ScheduleAnyway, fooSelector, nil, nil, nil, nil).
SpreadConstraint(1, v1.LabelHostname, v1.ScheduleAnyway, barSelector, nil, nil, nil, []string{"baz"}).
Obj(),
existingPods: []*v1.Pod{
st.MakePod().Name("p-a1").Node("node-a").Label("foo", "").Obj(),
st.MakePod().Name("p-b1").Node("node-b").Label("foo", "").Label("bar", "").Label("baz", "").Obj(),
st.MakePod().Name("p-c1").Node("node-c").Label("foo", "").Obj(),
st.MakePod().Name("p-c2").Node("node-c").Label("bar", "").Obj(),
st.MakePod().Name("p-d3").Node("node-c").Label("bar", "").Label("baz", "").Obj(),
},
nodes: []*v1.Node{
st.MakeNode().Name("node-a").Label("zone", "zone1").Label(v1.LabelHostname, "node-a").Obj(),
st.MakeNode().Name("node-b").Label("zone", "zone1").Label(v1.LabelHostname, "node-b").Obj(),
st.MakeNode().Name("node-c").Label("zone", "zone2").Label(v1.LabelHostname, "node-c").Obj(),
st.MakeNode().Name("node-d").Label("zone", "zone2").Label(v1.LabelHostname, "node-d").Obj(),
},
want: []framework.NodeScore{
{Name: "node-a", Score: 60},
{Name: "node-b", Score: 20},
{Name: "node-c", Score: 60},
{Name: "node-d", Score: 100},
},
enableMatchLabelKeys: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@@ -1159,6 +1240,7 @@ func TestPodTopologySpreadScore(t *testing.T) {
pl := plugintesting.SetupPluginWithInformers(ctx, t, podTopologySpreadFunc, &config.PodTopologySpreadArgs{DefaultingType: config.SystemDefaulting}, cache.NewSnapshot(tt.existingPods, allNodes), tt.objs)
p := pl.(*PodTopologySpread)
p.enableNodeInclusionPolicyInPodTopologySpread = tt.enableNodeInclustionPolicy
p.enableMatchLabelKeysInPodTopologySpread = tt.enableMatchLabelKeys
status := p.PreScore(context.Background(), state, tt.pod, tt.nodes)
if !status.IsSuccess() {
@@ -1199,7 +1281,7 @@ func BenchmarkTestPodTopologySpreadScore(b *testing.B) {
{
name: "1000nodes/single-constraint-zone",
pod: st.MakePod().Name("p").Label("foo", "").
SpreadConstraint(1, v1.LabelTopologyZone, v1.ScheduleAnyway, fooSelector, nil, nil, nil).
SpreadConstraint(1, v1.LabelTopologyZone, v1.ScheduleAnyway, fooSelector, nil, nil, nil, nil).
Obj(),
existingPodsNum: 10000,
allNodesNum: 1000,
@@ -1208,7 +1290,7 @@ func BenchmarkTestPodTopologySpreadScore(b *testing.B) {
{
name: "1000nodes/single-constraint-node",
pod: st.MakePod().Name("p").Label("foo", "").
SpreadConstraint(1, v1.LabelHostname, v1.ScheduleAnyway, fooSelector, nil, nil, nil).
SpreadConstraint(1, v1.LabelHostname, v1.ScheduleAnyway, fooSelector, nil, nil, nil, nil).
Obj(),
existingPodsNum: 10000,
allNodesNum: 1000,
@@ -1217,8 +1299,8 @@ func BenchmarkTestPodTopologySpreadScore(b *testing.B) {
{
name: "1000nodes/two-Constraints-zone-node",
pod: st.MakePod().Name("p").Label("foo", "").Label("bar", "").
SpreadConstraint(1, v1.LabelTopologyZone, v1.ScheduleAnyway, fooSelector, nil, nil, nil).
SpreadConstraint(1, v1.LabelHostname, v1.ScheduleAnyway, barSelector, nil, nil, nil).
SpreadConstraint(1, v1.LabelTopologyZone, v1.ScheduleAnyway, fooSelector, nil, nil, nil, nil).
SpreadConstraint(1, v1.LabelHostname, v1.ScheduleAnyway, barSelector, nil, nil, nil, nil).
Obj(),
existingPodsNum: 10000,
allNodesNum: 1000,

View File

@@ -49,6 +49,7 @@ func NewInTreeRegistry() runtime.Registry {
EnableVolumeCapacityPriority: feature.DefaultFeatureGate.Enabled(features.VolumeCapacityPriority),
EnableMinDomainsInPodTopologySpread: feature.DefaultFeatureGate.Enabled(features.MinDomainsInPodTopologySpread),
EnableNodeInclusionPolicyInPodTopologySpread: feature.DefaultFeatureGate.Enabled(features.NodeInclusionPolicyInPodTopologySpread),
EnableMatchLabelKeysInPodTopologySpread: feature.DefaultFeatureGate.Enabled(features.MatchLabelKeysInPodTopologySpread),
}
return runtime.Registry{

View File

@@ -1759,7 +1759,7 @@ func TestSchedulerSchedulePod(t *testing.T) {
Operator: metav1.LabelSelectorOpExists,
},
},
}, nil, nil, nil).Obj(),
}, nil, nil, nil, nil).Obj(),
pods: []*v1.Pod{
st.MakePod().Name("pod1").UID("pod1").Label("foo", "").Node("node1").Phase(v1.PodRunning).Obj(),
},
@@ -1786,7 +1786,7 @@ func TestSchedulerSchedulePod(t *testing.T) {
Operator: metav1.LabelSelectorOpExists,
},
},
}, nil, nil, nil).Obj(),
}, nil, nil, nil, nil).Obj(),
pods: []*v1.Pod{
st.MakePod().Name("pod1a").UID("pod1a").Label("foo", "").Node("node1").Phase(v1.PodRunning).Obj(),
st.MakePod().Name("pod1b").UID("pod1b").Label("foo", "").Node("node1").Phase(v1.PodRunning).Obj(),

View File

@@ -547,7 +547,7 @@ func (p *PodWrapper) PodAntiAffinityNotIn(labelKey, topologyKey string, vals []s
// SpreadConstraint constructs a TopologySpreadConstraint object and injects
// into the inner pod.
func (p *PodWrapper) SpreadConstraint(maxSkew int, tpKey string, mode v1.UnsatisfiableConstraintAction, selector *metav1.LabelSelector, minDomains *int32, nodeAffinityPolicy, nodeTaintsPolicy *v1.NodeInclusionPolicy) *PodWrapper {
func (p *PodWrapper) SpreadConstraint(maxSkew int, tpKey string, mode v1.UnsatisfiableConstraintAction, selector *metav1.LabelSelector, minDomains *int32, nodeAffinityPolicy, nodeTaintsPolicy *v1.NodeInclusionPolicy, matchLabelKeys []string) *PodWrapper {
c := v1.TopologySpreadConstraint{
MaxSkew: int32(maxSkew),
TopologyKey: tpKey,
@@ -556,6 +556,7 @@ func (p *PodWrapper) SpreadConstraint(maxSkew int, tpKey string, mode v1.Unsatis
MinDomains: minDomains,
NodeAffinityPolicy: nodeAffinityPolicy,
NodeTaintsPolicy: nodeTaintsPolicy,
MatchLabelKeys: matchLabelKeys,
}
p.Spec.TopologySpreadConstraints = append(p.Spec.TopologySpreadConstraints, c)
return p