Skip to content

Commit

Permalink
[#495] implement feature request: topologySpreadConstraints
Browse files Browse the repository at this point in the history
  • Loading branch information
kmarteaux authored and zegl committed Feb 24, 2023
1 parent fa023cb commit f5d2695
Show file tree
Hide file tree
Showing 9 changed files with 221 additions and 0 deletions.
57 changes: 57 additions & 0 deletions score/podtopologyspreadconstraints/podtopologyspreadconstraints.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package podtopologyconstraints

import (
ks "github.com/zegl/kube-score/domain"
"github.com/zegl/kube-score/score/checks"
"github.com/zegl/kube-score/scorecard"
)

func Register(allChecks *checks.Checks) {
allChecks.RegisterPodCheck("Pod Topology Spread Constraints", "Pod Topology Spread Constraints", podTopologySpreadConstraints)
}

func podTopologySpreadConstraints(pod ks.PodSpecer) (score scorecard.TestScore, err error) {
spreads := pod.GetPodTemplateSpec().Spec.TopologySpreadConstraints

if spreads == nil {
score.Grade = scorecard.GradeAllOK
score.AddComment("", "Pod Topology Spread Constraints", "No Pod Topology Spread Constraints set, kube-scheduler defaults assumed")
return
}

for _, spread := range spreads {
if spread.LabelSelector == nil {
score.Grade = scorecard.GradeCritical
score.AddComment("", "Pod Topology Spread Constraints", "No labelSelector detected. A label selector is needed determine the number of pods in a topology domain")
return
}

if spread.MaxSkew == 0 {
score.Grade = scorecard.GradeCritical
score.AddComment("", "Pod Topology Spread Constraints", "MaxSkew is set to zero. This is not allowed.")
return
}

if spread.MinDomains != nil && *spread.MinDomains == 0 {
score.Grade = scorecard.GradeCritical
score.AddComment("", "Pod Topology Spread Constraints", "MaxDomain set to zero. This is not allowed. Constraint behaves if minDomains is set to 1 if nil")
return
}

if spread.TopologyKey == "" {
score.Grade = scorecard.GradeCritical
score.AddComment("", "Pod Topology Spread Constraints", "TopologyKey is not set. This is the key of node labels used to bucket nodes into a domain")
return
}

if spread.WhenUnsatisfiable != "DoNotSchedule" && spread.WhenUnsatisfiable != "ScheduleAnyway" {
score.Grade = scorecard.GradeCritical
score.AddComment("", "Pod Topology Spread Constraints", "Invalid WhenUnsatisfiable setting detected")
return
}
}

score.Grade = scorecard.GradeAllOK
score.AddComment("", "Pod Topology Spread Constraints", "Pod Topology Spread Constraints")
return
}
42 changes: 42 additions & 0 deletions score/podtopologyspreadconstraints_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package score

import (
"testing"

"github.com/zegl/kube-score/scorecard"
)

func TestPodTopologySpreadContraintsWithOneConstraint(t *testing.T) {
t.Parallel()
testExpectedScore(t, "pod-topology-spread-constraints-one-constraint.yaml", "Pod Topology Spread Constraints", scorecard.GradeAllOK)
}

func TestPodTopologySpreadContraintsWithTwoConstraints(t *testing.T) {
t.Parallel()
testExpectedScore(t, "pod-topology-spread-constraints-two-constraints.yaml", "Pod Topology Spread Constraints", scorecard.GradeAllOK)
}

func TestPodTopologySpreadContraintsNoLabelSelector(t *testing.T) {
t.Parallel()
testExpectedScore(t, "pod-topology-spread-constraints-no-labelselector.yaml", "Pod Topology Spread Constraints", scorecard.GradeCritical)
}

func TestPodTopologySpreadContraintsInvalidMaxSkew(t *testing.T) {
t.Parallel()
testExpectedScore(t, "pod-topology-spread-constraints-invalid-maxskew.yaml", "Pod Topology Spread Constraints", scorecard.GradeCritical)
}

func TestPodTopologySpreadContraintsInvalidMinDomains(t *testing.T) {
t.Parallel()
testExpectedScore(t, "pod-topology-spread-constraints-invalid-mindomains.yaml", "Pod Topology Spread Constraints", scorecard.GradeCritical)
}

func TestPodTopologySpreadContraintsNoTopologyKey(t *testing.T) {
t.Parallel()
testExpectedScore(t, "pod-topology-spread-constraints-no-topologykey.yaml", "Pod Topology Spread Constraints", scorecard.GradeCritical)
}

func TestPodTopologySpreadContraintsInvalidDirective(t *testing.T) {
t.Parallel()
testExpectedScore(t, "pod-topology-spread-constraints-invalid-whenunsatisfiable.yaml", "Pod Topology Spread Constraints", scorecard.GradeCritical)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
kind: Pod
apiVersion: v1
metadata:
name: mypod
labels:
foo: bar
spec:
topologySpreadConstraints:
- maxSkew: 0
topologyKey: zone
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
foo: bar
containers:
- name: pause
image: registry.k8s.io/pause:3.1
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
kind: Pod
apiVersion: v1
metadata:
name: mypod
labels:
foo: bar
spec:
topologySpreadConstraints:
- maxSkew: 1
minDomains: 0
topologyKey: zone
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
foo: bar
containers:
- name: pause
image: registry.k8s.io/pause:3.1
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
kind: Pod
apiVersion: v1
metadata:
name: mypod
labels:
foo: bar
spec:
topologySpreadConstraints:
- maxSkew: 1
topologyKey: zone
whenUnsatisfiable: DoNotSCHEDULE
labelSelector:
matchLabels:
foo: bar
containers:
- name: pause
image: registry.k8s.io/pause:3.1
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
kind: Pod
apiVersion: v1
metadata:
name: mypod
labels:
foo: bar
spec:
topologySpreadConstraints:
- maxSkew: 1
topologyKey: zone
whenUnsatisfiable: DoNotSchedule
containers:
- name: pause
image: registry.k8s.io/pause:3.1
16 changes: 16 additions & 0 deletions score/testdata/pod-topology-spread-constraints-no-topologykey.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
kind: Pod
apiVersion: v1
metadata:
name: mypod
labels:
foo: bar
spec:
topologySpreadConstraints:
- maxSkew: 1
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
foo: bar
containers:
- name: pause
image: registry.k8s.io/pause:3.1
17 changes: 17 additions & 0 deletions score/testdata/pod-topology-spread-constraints-one-constraint.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
kind: Pod
apiVersion: v1
metadata:
name: mypod
labels:
foo: bar
spec:
topologySpreadConstraints:
- maxSkew: 1
topologyKey: zone
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
foo: bar
containers:
- name: pause
image: registry.k8s.io/pause:3.1
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
kind: Pod
apiVersion: v1
metadata:
name: mypod
labels:
foo: bar
spec:
topologySpreadConstraints:
- maxSkew: 1
topologyKey: zone
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
foo: bar
- maxSkew: 1
topologyKey: node
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
foo: bar
containers:
- name: pause
image: registry.k8s.io/pause:3.1

0 comments on commit f5d2695

Please sign in to comment.