Skip to content

Commit ac55fb0

Browse files
Merge #317
317: score/apps: StatefulSets should have a valid headless serviceName r=zegl a=neglect-yp <!-- Optional: Add this change to the release notes by adding a RELNOTE comment If this shouldn't appear in the notes, simply remove this. --> ``` RELNOTE: Validate serviceName of a StatefulSet ``` This PR closes #315 This adds `statefulset-has-servicename` that checks following rules: - StatefulSets `.spec.serviceName` matches a Service in the same namespace. - The Service is a Headless Service. > StatefulSets currently require a Headless Service to be responsible for the network identity of the Pods. You are responsible for creating this Service. https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#limitations - The Service has a selector that matches the StatefulSet. Co-authored-by: neglect-yp <grandis.hebitombo@gmail.com>
2 parents cedb806 + 4d47a1d commit ac55fb0

10 files changed

+548
-2
lines changed

README_CHECKS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,6 @@
2222
| deployment-has-host-podantiaffinity | Deployment | Makes sure that a podAntiAffinity has been set that prevents multiple pods from being scheduled on the same node. https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ | default |
2323
| statefulset-has-host-podantiaffinity | StatefulSet | Makes sure that a podAntiAffinity has been set that prevents multiple pods from being scheduled on the same node. https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ | default |
2424
| deployment-targeted-by-hpa-does-not-have-replicas-configured | Deployment | Makes sure that Deployments using a HorizontalPodAutoscaler doesn't have a statically configured replica count set | default |
25+
| statefulset-has-servicename | StatefulSet | Makes sure that StatefulSets have a existing serviceName that is headless. | default |
2526
| label-values | all | Validates label values | default |
2627
| horizontalpodautoscaler-has-target | HorizontalPodAutoscaler | Makes sure that the HPA targets a valid object | default |

score/apps/apps.go

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,11 @@ import (
1212
"github.com/zegl/kube-score/scorecard"
1313
)
1414

15-
func Register(allChecks *checks.Checks, allHPAs []ks.HpaTargeter) {
15+
func Register(allChecks *checks.Checks, allHPAs []ks.HpaTargeter, allServices []ks.Service) {
1616
allChecks.RegisterDeploymentCheck("Deployment has host PodAntiAffinity", "Makes sure that a podAntiAffinity has been set that prevents multiple pods from being scheduled on the same node. https://kubernetes.io/docs/concepts/configuration/assign-pod-node/", deploymentHasAntiAffinity)
1717
allChecks.RegisterStatefulSetCheck("StatefulSet has host PodAntiAffinity", "Makes sure that a podAntiAffinity has been set that prevents multiple pods from being scheduled on the same node. https://kubernetes.io/docs/concepts/configuration/assign-pod-node/", statefulsetHasAntiAffinity)
1818
allChecks.RegisterDeploymentCheck("Deployment targeted by HPA does not have replicas configured", "Makes sure that Deployments using a HorizontalPodAutoscaler doesn't have a statically configured replica count set", hpaDeploymentNoReplicas(allHPAs))
19+
allChecks.RegisterStatefulSetCheck("StatefulSet has ServiceName", "Makes sure that StatefulSets have a existing headless serviceName.", statefulsetHasServiceName(allServices))
1920
}
2021

2122
func hpaDeploymentNoReplicas(allHPAs []ks.HpaTargeter) func(deployment appsv1.Deployment) (scorecard.TestScore, error) {
@@ -133,3 +134,27 @@ func hasPodAntiAffinity(selfLables internal.MapLables, affinity *corev1.Affinity
133134

134135
return false
135136
}
137+
138+
func statefulsetHasServiceName(allServices []ks.Service) func(statefulset appsv1.StatefulSet) (scorecard.TestScore, error) {
139+
return func(statefulset appsv1.StatefulSet) (score scorecard.TestScore, err error) {
140+
for _, service := range allServices {
141+
if service.Service().Namespace != statefulset.Namespace ||
142+
service.Service().Name != statefulset.Spec.ServiceName ||
143+
service.Service().Spec.ClusterIP != "None" {
144+
continue
145+
}
146+
147+
if internal.LabelSelectorMatchesLabels(
148+
service.Service().Spec.Selector,
149+
statefulset.Spec.Template.GetObjectMeta().GetLabels(),
150+
) {
151+
score.Grade = scorecard.GradeAllOK
152+
return
153+
}
154+
}
155+
156+
score.Grade = scorecard.GradeCritical
157+
score.AddComment("", "StatefulSet does not have a valid serviceName", "StatefulSets currently require a Headless Service to be responsible for the network identity of the Pods. You are responsible for creating this Service. https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#limitations")
158+
return
159+
}
160+
}

0 commit comments

Comments
 (0)