mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-19 18:02:01 +00:00
implementation for MatchLabelKeys in TopologySpreadConstraint
Signed-off-by: Alex Wang <wangqingcan1990@gmail.com>
This commit is contained in:
parent
e6c2bf8516
commit
f4bc904376
@ -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},
|
||||
|
@ -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(),
|
||||
|
@ -24,4 +24,5 @@ type Features struct {
|
||||
EnableVolumeCapacityPriority bool
|
||||
EnableMinDomainsInPodTopologySpread bool
|
||||
EnableNodeInclusionPolicyInPodTopologySpread bool
|
||||
EnableMatchLabelKeysInPodTopologySpread bool
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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)
|
||||
|
@ -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(),
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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,
|
||||
|
@ -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{
|
||||
|
@ -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(),
|
||||
|
@ -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
|
||||
|
@ -1076,12 +1076,13 @@ func TestPodTopologySpreadFilter(t *testing.T) {
|
||||
candidateNodes []string // nodes expected to schedule onto
|
||||
enableMinDomains bool
|
||||
enableNodeInclustionPolicy bool
|
||||
enableMatchLabelKeys bool
|
||||
}{
|
||||
// note: naming starts at index 0
|
||||
{
|
||||
name: "place pod on a 1/1/0/1 cluster with MaxSkew=1, node-2 is the only fit",
|
||||
incomingPod: st.MakePod().Name("p").Label("foo", "").Container(pause).
|
||||
SpreadConstraint(1, "node", hardSpread, st.MakeLabelSelector().Exists("foo").Obj(), nil, nil, nil).
|
||||
SpreadConstraint(1, "node", hardSpread, st.MakeLabelSelector().Exists("foo").Obj(), nil, nil, nil, nil).
|
||||
Obj(),
|
||||
existingPods: []*v1.Pod{
|
||||
st.MakePod().Name("p0").Node("node-0").Label("foo", "").Container(pause).Obj(),
|
||||
@ -1095,7 +1096,7 @@ func TestPodTopologySpreadFilter(t *testing.T) {
|
||||
{
|
||||
name: "place pod on a 2/0/0/1 cluster with MaxSkew=2, node-{1,2,3} are good fits",
|
||||
incomingPod: st.MakePod().Name("p").Label("foo", "").Container(pause).
|
||||
SpreadConstraint(2, "node", hardSpread, st.MakeLabelSelector().Exists("foo").Obj(), nil, nil, nil).
|
||||
SpreadConstraint(2, "node", hardSpread, st.MakeLabelSelector().Exists("foo").Obj(), nil, nil, nil, nil).
|
||||
Obj(),
|
||||
existingPods: []*v1.Pod{
|
||||
st.MakePod().Name("p0a").Node("node-0").Label("foo", "").Container(pause).Obj(),
|
||||
@ -1110,7 +1111,7 @@ func TestPodTopologySpreadFilter(t *testing.T) {
|
||||
name: "pod is required to be placed on zone0, so only node-1 fits",
|
||||
incomingPod: st.MakePod().Name("p").Label("foo", "").Container(pause).
|
||||
NodeAffinityIn("zone", []string{"zone-0"}).
|
||||
SpreadConstraint(1, "node", hardSpread, st.MakeLabelSelector().Exists("foo").Obj(), nil, nil, nil).
|
||||
SpreadConstraint(1, "node", hardSpread, st.MakeLabelSelector().Exists("foo").Obj(), nil, nil, nil, nil).
|
||||
Obj(),
|
||||
existingPods: []*v1.Pod{
|
||||
st.MakePod().Name("p0").Node("node-0").Label("foo", "").Container(pause).Obj(),
|
||||
@ -1123,8 +1124,8 @@ func TestPodTopologySpreadFilter(t *testing.T) {
|
||||
{
|
||||
name: "two constraints: pod can only be placed to zone-1/node-2",
|
||||
incomingPod: st.MakePod().Name("p").Label("foo", "").Container(pause).
|
||||
SpreadConstraint(1, "zone", hardSpread, st.MakeLabelSelector().Exists("foo").Obj(), nil, nil, nil).
|
||||
SpreadConstraint(1, "node", hardSpread, st.MakeLabelSelector().Exists("foo").Obj(), nil, nil, nil).
|
||||
SpreadConstraint(1, "zone", hardSpread, st.MakeLabelSelector().Exists("foo").Obj(), nil, nil, nil, nil).
|
||||
SpreadConstraint(1, "node", hardSpread, st.MakeLabelSelector().Exists("foo").Obj(), nil, nil, nil, nil).
|
||||
Obj(),
|
||||
existingPods: []*v1.Pod{
|
||||
st.MakePod().Name("p0").Node("node-0").Label("foo", "").Container(pause).Obj(),
|
||||
@ -1140,8 +1141,8 @@ func TestPodTopologySpreadFilter(t *testing.T) {
|
||||
name: "pod cannot be placed onto any node",
|
||||
incomingPod: st.MakePod().Name("p").Label("foo", "").Container(pause).
|
||||
NodeAffinityNotIn("node", []string{"node-0"}). // mock a 3-node cluster
|
||||
SpreadConstraint(1, "zone", hardSpread, st.MakeLabelSelector().Exists("foo").Obj(), nil, nil, nil).
|
||||
SpreadConstraint(1, "node", hardSpread, st.MakeLabelSelector().Exists("foo").Obj(), nil, nil, nil).
|
||||
SpreadConstraint(1, "zone", hardSpread, st.MakeLabelSelector().Exists("foo").Obj(), nil, nil, nil, nil).
|
||||
SpreadConstraint(1, "node", hardSpread, st.MakeLabelSelector().Exists("foo").Obj(), nil, nil, nil, nil).
|
||||
Obj(),
|
||||
existingPods: []*v1.Pod{
|
||||
st.MakePod().Name("p1a").Node("node-1").Label("foo", "").Container(pause).Obj(),
|
||||
@ -1157,8 +1158,8 @@ func TestPodTopologySpreadFilter(t *testing.T) {
|
||||
name: "high priority pod can preempt others",
|
||||
incomingPod: st.MakePod().Name("p").Label("foo", "").Container(pause).Priority(100).
|
||||
NodeAffinityNotIn("node", []string{"node-0"}). // mock a 3-node cluster
|
||||
SpreadConstraint(1, "zone", hardSpread, st.MakeLabelSelector().Exists("foo").Obj(), nil, nil, nil).
|
||||
SpreadConstraint(1, "node", hardSpread, st.MakeLabelSelector().Exists("foo").Obj(), nil, nil, nil).
|
||||
SpreadConstraint(1, "zone", hardSpread, st.MakeLabelSelector().Exists("foo").Obj(), nil, nil, nil, nil).
|
||||
SpreadConstraint(1, "node", hardSpread, st.MakeLabelSelector().Exists("foo").Obj(), nil, nil, nil, nil).
|
||||
Obj(),
|
||||
existingPods: []*v1.Pod{
|
||||
st.MakePod().ZeroTerminationGracePeriod().Name("p1a").Node("node-1").Label("foo", "").Container(pause).Obj(),
|
||||
@ -1183,6 +1184,7 @@ func TestPodTopologySpreadFilter(t *testing.T) {
|
||||
pointer.Int32(4), // larger than the number of domains (= 3)
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
).
|
||||
Obj(),
|
||||
existingPods: []*v1.Pod{
|
||||
@ -1209,6 +1211,7 @@ func TestPodTopologySpreadFilter(t *testing.T) {
|
||||
pointer.Int32(2), // smaller than the number of domains (= 3)
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
).
|
||||
Obj(),
|
||||
existingPods: []*v1.Pod{
|
||||
@ -1234,6 +1237,7 @@ func TestPodTopologySpreadFilter(t *testing.T) {
|
||||
pointer.Int32(3), // larger than the number of domains(2)
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
).Obj(),
|
||||
existingPods: []*v1.Pod{
|
||||
st.MakePod().Name("p1a").Node("node-0").Label("foo", "").Container(pause).Obj(),
|
||||
@ -1256,6 +1260,7 @@ func TestPodTopologySpreadFilter(t *testing.T) {
|
||||
pointer.Int32(1), // smaller than the number of domains(2)
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
).Obj(),
|
||||
existingPods: []*v1.Pod{
|
||||
st.MakePod().Name("p1a").Node("node-1").Label("foo", "").Container(pause).Obj(),
|
||||
@ -1271,7 +1276,7 @@ func TestPodTopologySpreadFilter(t *testing.T) {
|
||||
name: "NodeAffinityPolicy honored with labelSelectors, pods spread across zone as 2/1",
|
||||
incomingPod: st.MakePod().Name("p").Label("foo", "").Container(pause).
|
||||
NodeSelector(map[string]string{"foo": ""}).
|
||||
SpreadConstraint(1, "zone", v1.DoNotSchedule, st.MakeLabelSelector().Exists("foo").Obj(), nil, nil, nil).
|
||||
SpreadConstraint(1, "zone", v1.DoNotSchedule, st.MakeLabelSelector().Exists("foo").Obj(), nil, nil, nil, nil).
|
||||
Obj(),
|
||||
existingPods: []*v1.Pod{
|
||||
st.MakePod().Name("p1a").Node("node-1").Label("foo", "").Container(pause).Obj(),
|
||||
@ -1293,7 +1298,7 @@ func TestPodTopologySpreadFilter(t *testing.T) {
|
||||
name: "NodeAffinityPolicy ignored with nodeAffinity, pods spread across zone as 1/~2~",
|
||||
incomingPod: st.MakePod().Name("p").Label("foo", "").Container(pause).
|
||||
NodeAffinityIn("foo", []string{""}).
|
||||
SpreadConstraint(1, "zone", v1.DoNotSchedule, st.MakeLabelSelector().Exists("foo").Obj(), nil, &ignorePolicy, nil).
|
||||
SpreadConstraint(1, "zone", v1.DoNotSchedule, st.MakeLabelSelector().Exists("foo").Obj(), nil, &ignorePolicy, nil, nil).
|
||||
Obj(),
|
||||
existingPods: []*v1.Pod{
|
||||
st.MakePod().Name("p1a").Node("node-1").Label("foo", "").Container(pause).Obj(),
|
||||
@ -1313,7 +1318,7 @@ func TestPodTopologySpreadFilter(t *testing.T) {
|
||||
{
|
||||
name: "NodeTaintsPolicy honored, pods spread across zone as 2/1",
|
||||
incomingPod: st.MakePod().Name("p").Label("foo", "").Container(pause).
|
||||
SpreadConstraint(1, "zone", v1.DoNotSchedule, st.MakeLabelSelector().Exists("foo").Obj(), nil, nil, &honorPolicy).
|
||||
SpreadConstraint(1, "zone", v1.DoNotSchedule, st.MakeLabelSelector().Exists("foo").Obj(), nil, nil, &honorPolicy, nil).
|
||||
Obj(),
|
||||
existingPods: []*v1.Pod{
|
||||
st.MakePod().Name("p1a").Node("node-1").Label("foo", "").Container(pause).Obj(),
|
||||
@ -1334,7 +1339,7 @@ func TestPodTopologySpreadFilter(t *testing.T) {
|
||||
{
|
||||
name: "NodeTaintsPolicy ignored, pods spread across zone as 2/2",
|
||||
incomingPod: st.MakePod().Name("p").Label("foo", "").Container(pause).
|
||||
SpreadConstraint(1, "zone", v1.DoNotSchedule, st.MakeLabelSelector().Exists("foo").Obj(), nil, nil, nil).
|
||||
SpreadConstraint(1, "zone", v1.DoNotSchedule, st.MakeLabelSelector().Exists("foo").Obj(), nil, nil, nil, nil).
|
||||
Obj(),
|
||||
existingPods: []*v1.Pod{
|
||||
st.MakePod().Name("p1a").Node("node-1").Label("foo", "").Container(pause).Obj(),
|
||||
@ -1359,8 +1364,8 @@ func TestPodTopologySpreadFilter(t *testing.T) {
|
||||
name: "two node inclusion Constraints, zone: honor/ignore, node: honor/ignore",
|
||||
incomingPod: st.MakePod().Name("p").Label("foo", "").Container(pause).
|
||||
NodeSelector(map[string]string{"foo": ""}).
|
||||
SpreadConstraint(1, "zone", v1.DoNotSchedule, st.MakeLabelSelector().Exists("foo").Obj(), nil, nil, nil).
|
||||
SpreadConstraint(1, "node", 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, "node", v1.DoNotSchedule, st.MakeLabelSelector().Exists("foo").Obj(), nil, nil, nil, nil).
|
||||
Obj(),
|
||||
existingPods: []*v1.Pod{
|
||||
st.MakePod().Name("p1a").Node("node-1").Label("foo", "").Container(pause).Obj(),
|
||||
@ -1385,8 +1390,8 @@ func TestPodTopologySpreadFilter(t *testing.T) {
|
||||
name: "feature gate disabled, two node inclusion Constraints, zone: honor/ignore, node: honor/ignore",
|
||||
incomingPod: st.MakePod().Name("p").Label("foo", "").Container(pause).
|
||||
NodeSelector(map[string]string{"foo": ""}).
|
||||
SpreadConstraint(1, "zone", v1.DoNotSchedule, st.MakeLabelSelector().Exists("foo").Obj(), nil, nil, nil).
|
||||
SpreadConstraint(1, "node", 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, "node", v1.DoNotSchedule, st.MakeLabelSelector().Exists("foo").Obj(), nil, nil, nil, nil).
|
||||
Obj(),
|
||||
existingPods: []*v1.Pod{
|
||||
st.MakePod().Name("p1a").Node("node-1").Label("foo", "").Container(pause).Obj(),
|
||||
@ -1411,8 +1416,8 @@ func TestPodTopologySpreadFilter(t *testing.T) {
|
||||
name: "two node inclusion Constraints, zone: ignore/ignore, node: honor/honor",
|
||||
incomingPod: st.MakePod().Name("p").Label("foo", "").Container(pause).
|
||||
NodeSelector(map[string]string{"foo": ""}).
|
||||
SpreadConstraint(1, "zone", v1.DoNotSchedule, st.MakeLabelSelector().Exists("foo").Obj(), nil, &ignorePolicy, nil).
|
||||
SpreadConstraint(1, "node", v1.DoNotSchedule, st.MakeLabelSelector().Exists("foo").Obj(), nil, nil, &honorPolicy).
|
||||
SpreadConstraint(1, "zone", v1.DoNotSchedule, st.MakeLabelSelector().Exists("foo").Obj(), nil, &ignorePolicy, nil, nil).
|
||||
SpreadConstraint(1, "node", v1.DoNotSchedule, st.MakeLabelSelector().Exists("foo").Obj(), nil, nil, &honorPolicy, nil).
|
||||
Obj(),
|
||||
existingPods: []*v1.Pod{
|
||||
st.MakePod().Name("p1a").Node("node-1").Label("foo", "").Container(pause).Obj(),
|
||||
@ -1430,11 +1435,57 @@ func TestPodTopologySpreadFilter(t *testing.T) {
|
||||
candidateNodes: []string{"node-1", "node-4"},
|
||||
enableNodeInclustionPolicy: true,
|
||||
},
|
||||
{
|
||||
name: "matchLabelKeys ignored when feature gate disabled, pods spread across zone as 2/1",
|
||||
incomingPod: st.MakePod().Name("p").Label("foo", "").Label("bar", "").Container(pause).
|
||||
SpreadConstraint(1, "zone", v1.DoNotSchedule, st.MakeLabelSelector().Exists("foo").Obj(), nil, nil, nil, []string{"bar"}).
|
||||
Obj(),
|
||||
existingPods: []*v1.Pod{
|
||||
st.MakePod().Name("p1a").Node("node-0").Label("foo", "").Container(pause).Obj(),
|
||||
st.MakePod().Name("p2a").Node("node-1").Label("foo", "").Container(pause).Obj(),
|
||||
st.MakePod().Name("p3a").Node("node-2").Label("foo", "").Label("bar", "").Container(pause).Obj(),
|
||||
},
|
||||
fits: true,
|
||||
nodes: defaultNodes,
|
||||
candidateNodes: []string{"node-2", "node-3"},
|
||||
enableMatchLabelKeys: false,
|
||||
},
|
||||
{
|
||||
name: "matchLabelKeys ANDed with LabelSelector when LabelSelector isn't empty, pods spread across zone as 0/1",
|
||||
incomingPod: st.MakePod().Name("p").Label("foo", "").Label("bar", "").Container(pause).
|
||||
SpreadConstraint(1, "zone", v1.DoNotSchedule, st.MakeLabelSelector().Exists("foo").Obj(), nil, nil, nil, []string{"bar"}).
|
||||
Obj(),
|
||||
existingPods: []*v1.Pod{
|
||||
st.MakePod().Name("p1a").Node("node-0").Label("foo", "").Container(pause).Obj(),
|
||||
st.MakePod().Name("p2a").Node("node-1").Label("foo", "").Container(pause).Obj(),
|
||||
st.MakePod().Name("p3a").Node("node-2").Label("foo", "").Label("bar", "").Container(pause).Obj(),
|
||||
},
|
||||
fits: true,
|
||||
nodes: defaultNodes,
|
||||
candidateNodes: []string{"node-0", "node-1"},
|
||||
enableMatchLabelKeys: true,
|
||||
},
|
||||
{
|
||||
name: "matchLabelKeys ANDed with LabelSelector when LabelSelector is empty, pods spread across zone as 2/1",
|
||||
incomingPod: st.MakePod().Name("p").Label("foo", "").Container(pause).
|
||||
SpreadConstraint(1, "zone", v1.DoNotSchedule, st.MakeLabelSelector().Obj(), nil, nil, nil, []string{"foo"}).
|
||||
Obj(),
|
||||
existingPods: []*v1.Pod{
|
||||
st.MakePod().Name("p1a").Node("node-0").Label("foo", "").Container(pause).Obj(),
|
||||
st.MakePod().Name("p2a").Node("node-1").Label("foo", "").Container(pause).Obj(),
|
||||
st.MakePod().Name("p3a").Node("node-2").Label("foo", "").Container(pause).Obj(),
|
||||
},
|
||||
fits: true,
|
||||
nodes: defaultNodes,
|
||||
candidateNodes: []string{"node-2", "node-3"},
|
||||
enableMatchLabelKeys: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.MinDomainsInPodTopologySpread, tt.enableMinDomains)()
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.NodeInclusionPolicyInPodTopologySpread, tt.enableNodeInclustionPolicy)()
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.MatchLabelKeysInPodTopologySpread, tt.enableMatchLabelKeys)()
|
||||
|
||||
testCtx := initTest(t, "pts-predicate")
|
||||
cs := testCtx.ClientSet
|
||||
|
@ -449,13 +449,14 @@ func TestPodTopologySpreadScoring(t *testing.T) {
|
||||
nodes []*v1.Node
|
||||
want []string // nodes expected to schedule onto
|
||||
enableNodeInclustionPolicy bool
|
||||
enableMatchLabelKeys bool
|
||||
}{
|
||||
// note: naming starts at index 0
|
||||
// the symbol ~X~ means that node is infeasible
|
||||
{
|
||||
name: "place pod on a ~0~/1/2/3 cluster with MaxSkew=1, node-1 is the preferred fit",
|
||||
incomingPod: st.MakePod().Name("p").Label("foo", "").Container(pause).
|
||||
SpreadConstraint(1, "node", softSpread, st.MakeLabelSelector().Exists("foo").Obj(), nil, nil, nil).
|
||||
SpreadConstraint(1, "node", softSpread, st.MakeLabelSelector().Exists("foo").Obj(), nil, nil, nil, nil).
|
||||
Obj(),
|
||||
existingPods: []*v1.Pod{
|
||||
st.MakePod().Name("p1").Node("node-1").Label("foo", "").Container(pause).Obj(),
|
||||
@ -472,8 +473,8 @@ func TestPodTopologySpreadScoring(t *testing.T) {
|
||||
{
|
||||
name: "combined with hardSpread constraint on a ~4~/0/1/2 cluster",
|
||||
incomingPod: st.MakePod().Name("p").Label("foo", "").Container(pause).
|
||||
SpreadConstraint(1, "node", softSpread, st.MakeLabelSelector().Exists("foo").Obj(), nil, nil, nil).
|
||||
SpreadConstraint(1, "zone", hardSpread, st.MakeLabelSelector().Exists("foo").Obj(), nil, nil, nil).
|
||||
SpreadConstraint(1, "node", softSpread, st.MakeLabelSelector().Exists("foo").Obj(), nil, nil, nil, nil).
|
||||
SpreadConstraint(1, "zone", hardSpread, st.MakeLabelSelector().Exists("foo").Obj(), nil, nil, nil, nil).
|
||||
Obj(),
|
||||
existingPods: []*v1.Pod{
|
||||
st.MakePod().Name("p0a").Node("node-0").Label("foo", "").Container(pause).Obj(),
|
||||
@ -495,8 +496,8 @@ func TestPodTopologySpreadScoring(t *testing.T) {
|
||||
name: "soft constraint with two node inclusion Constraints, zone: honor/ignore, node: honor/ignore",
|
||||
incomingPod: st.MakePod().Name("p").Label("foo", "").Container(pause).
|
||||
NodeSelector(map[string]string{"foo": ""}).
|
||||
SpreadConstraint(1, "zone", softSpread, st.MakeLabelSelector().Exists("foo").Obj(), nil, nil, nil).
|
||||
SpreadConstraint(1, "node", softSpread, st.MakeLabelSelector().Exists("foo").Obj(), nil, nil, nil).
|
||||
SpreadConstraint(1, "zone", softSpread, st.MakeLabelSelector().Exists("foo").Obj(), nil, nil, nil, nil).
|
||||
SpreadConstraint(1, "node", softSpread, st.MakeLabelSelector().Exists("foo").Obj(), nil, nil, nil, nil).
|
||||
Obj(),
|
||||
existingPods: []*v1.Pod{
|
||||
st.MakePod().Name("p1a").Node("node-1").Label("foo", "").Container(pause).Obj(),
|
||||
@ -521,8 +522,8 @@ func TestPodTopologySpreadScoring(t *testing.T) {
|
||||
name: "soft constraint with two node inclusion Constraints, zone: ignore/ignore, node: honor/honor",
|
||||
incomingPod: st.MakePod().Name("p").Label("foo", "").Container(pause).
|
||||
NodeSelector(map[string]string{"foo": ""}).
|
||||
SpreadConstraint(1, "zone", softSpread, st.MakeLabelSelector().Exists("foo").Obj(), nil, &ignorePolicy, nil).
|
||||
SpreadConstraint(1, "node", softSpread, st.MakeLabelSelector().Exists("foo").Obj(), nil, nil, &honorPolicy).
|
||||
SpreadConstraint(1, "zone", softSpread, st.MakeLabelSelector().Exists("foo").Obj(), nil, &ignorePolicy, nil, nil).
|
||||
SpreadConstraint(1, "node", softSpread, st.MakeLabelSelector().Exists("foo").Obj(), nil, nil, &honorPolicy, nil).
|
||||
Obj(),
|
||||
existingPods: []*v1.Pod{
|
||||
st.MakePod().Name("p1a").Node("node-1").Label("foo", "").Container(pause).Obj(),
|
||||
@ -540,10 +541,65 @@ func TestPodTopologySpreadScoring(t *testing.T) {
|
||||
want: []string{"node-3"},
|
||||
enableNodeInclustionPolicy: true,
|
||||
},
|
||||
{
|
||||
name: "matchLabelKeys ignored when feature gate disabled, node-1 is the preferred fit",
|
||||
incomingPod: st.MakePod().Name("p").Label("foo", "").Label("bar", "").Container(pause).
|
||||
SpreadConstraint(1, "node", softSpread, st.MakeLabelSelector().Exists("foo").Obj(), nil, nil, nil, []string{"bar"}).
|
||||
Obj(),
|
||||
existingPods: []*v1.Pod{
|
||||
st.MakePod().Name("p1").Node("node-1").Label("foo", "").Label("bar", "").Container(pause).Obj(),
|
||||
st.MakePod().Name("p2a").Node("node-2").Label("foo", "").Container(pause).Obj(),
|
||||
st.MakePod().Name("p2b").Node("node-2").Label("foo", "").Container(pause).Obj(),
|
||||
st.MakePod().Name("p3a").Node("node-3").Label("foo", "").Label("bar", "").Container(pause).Obj(),
|
||||
st.MakePod().Name("p3b").Node("node-3").Label("foo", "").Label("bar", "").Container(pause).Obj(),
|
||||
st.MakePod().Name("p3c").Node("node-3").Label("foo", "").Container(pause).Obj(),
|
||||
},
|
||||
fits: true,
|
||||
nodes: defaultNodes,
|
||||
want: []string{"node-1"},
|
||||
enableMatchLabelKeys: false,
|
||||
},
|
||||
{
|
||||
name: "matchLabelKeys ANDed with LabelSelector when LabelSelector isn't empty, node-2 is the preferred fit",
|
||||
incomingPod: st.MakePod().Name("p").Label("foo", "").Label("bar", "").Container(pause).
|
||||
SpreadConstraint(1, "node", softSpread, st.MakeLabelSelector().Exists("foo").Obj(), nil, nil, nil, []string{"bar"}).
|
||||
Obj(),
|
||||
existingPods: []*v1.Pod{
|
||||
st.MakePod().Name("p1").Node("node-1").Label("foo", "").Label("bar", "").Container(pause).Obj(),
|
||||
st.MakePod().Name("p2a").Node("node-2").Label("foo", "").Container(pause).Obj(),
|
||||
st.MakePod().Name("p2b").Node("node-2").Label("foo", "").Container(pause).Obj(),
|
||||
st.MakePod().Name("p3a").Node("node-3").Label("foo", "").Label("bar", "").Container(pause).Obj(),
|
||||
st.MakePod().Name("p3b").Node("node-3").Label("foo", "").Label("bar", "").Container(pause).Obj(),
|
||||
st.MakePod().Name("p3c").Node("node-3").Label("foo", "").Container(pause).Obj(),
|
||||
},
|
||||
fits: true,
|
||||
nodes: defaultNodes,
|
||||
want: []string{"node-2"},
|
||||
enableMatchLabelKeys: true,
|
||||
},
|
||||
{
|
||||
name: "matchLabelKeys ANDed with LabelSelector when LabelSelector is empty, node-1 is the preferred fit",
|
||||
incomingPod: st.MakePod().Name("p").Label("foo", "").Container(pause).
|
||||
SpreadConstraint(1, "node", softSpread, st.MakeLabelSelector().Obj(), nil, nil, nil, []string{"foo"}).
|
||||
Obj(),
|
||||
existingPods: []*v1.Pod{
|
||||
st.MakePod().Name("p1").Node("node-1").Label("foo", "").Container(pause).Obj(),
|
||||
st.MakePod().Name("p2a").Node("node-2").Label("foo", "").Container(pause).Obj(),
|
||||
st.MakePod().Name("p2b").Node("node-2").Label("foo", "").Container(pause).Obj(),
|
||||
st.MakePod().Name("p3a").Node("node-3").Label("foo", "").Container(pause).Obj(),
|
||||
st.MakePod().Name("p3b").Node("node-3").Label("foo", "").Container(pause).Obj(),
|
||||
st.MakePod().Name("p3c").Node("node-3").Label("foo", "").Container(pause).Obj(),
|
||||
},
|
||||
fits: true,
|
||||
nodes: defaultNodes,
|
||||
want: []string{"node-1"},
|
||||
enableMatchLabelKeys: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.NodeInclusionPolicyInPodTopologySpread, tt.enableNodeInclustionPolicy)()
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.MatchLabelKeysInPodTopologySpread, tt.enableMatchLabelKeys)()
|
||||
|
||||
testCtx := initTestSchedulerForPriorityTest(t, podtopologyspread.Name)
|
||||
defer testutils.CleanupTest(t, testCtx)
|
||||
|
Loading…
Reference in New Issue
Block a user