diff --git a/docs/pages/includes/helm-reference/zz_generated.teleport-kube-agent.mdx b/docs/pages/includes/helm-reference/zz_generated.teleport-kube-agent.mdx index d8406c97d7716..e1876a14a2a8f 100644 --- a/docs/pages/includes/helm-reference/zz_generated.teleport-kube-agent.mdx +++ b/docs/pages/includes/helm-reference/zz_generated.teleport-kube-agent.mdx @@ -1421,6 +1421,42 @@ more details on possible values for `extra_fields`. See [the Kubernetes documentation](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity) for more details. +## `disableTopologySpreadConstraints` + +| Type | Default | +|------|---------| +| `bool` | `false` | + +`disableTopologySpreadConstraints` turns off the topology spread constraints. +The feature is automatically turned off on Kubernetes versions below 1.18. + +## `topologySpreadConstraints` + +| Type | Default | +|------|---------| +| `list` | `[]` | + +`topologySpreadConstraints` sets the topology spread constraints for any pods created by the chart. +See [the Kubernetes documentation](https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/) +for more details. + +When unset, the chart defaults to a soft topology spread constraint +that tries to spread pods across hosts and zones. + +``` +topologySpreadConstraints: + - maxSkew: 1 + topologyKey: kubernetes.io/hostname + whenUnsatisfiable: ScheduleAnyway + labelSelector: + matchLabels: # dynamically computed + - maxSkew: 1 + topologyKey: topology.kubernetes.io/zone + whenUnsatisfiable: ScheduleAnyway + labelSelector: + matchLabels: # dynamically computed +``` + ## `dnsConfig` | Type | Default | diff --git a/examples/chart/teleport-kube-agent/.lint/topology-spread-constraints.yaml b/examples/chart/teleport-kube-agent/.lint/topology-spread-constraints.yaml new file mode 100644 index 0000000000000..d6da0270bf2be --- /dev/null +++ b/examples/chart/teleport-kube-agent/.lint/topology-spread-constraints.yaml @@ -0,0 +1,13 @@ +authToken: auth-token +proxyAddr: proxy.example.com:3080 +roles: kube +kubeClusterName: test-kube-cluster +topologySpreadConstraints: + - maxSkew: 1 + topologyKey: kubernetes.io/hostname + whenUnsatisfiable: DoNotSchedule + labelSelector: + matchLabels: + app: foo + matchLabelKeys: + - pod-template-hash diff --git a/examples/chart/teleport-kube-agent/templates/deployment.yaml b/examples/chart/teleport-kube-agent/templates/deployment.yaml index 4eb3f5d48525c..7bd2ef037e2a6 100644 --- a/examples/chart/teleport-kube-agent/templates/deployment.yaml +++ b/examples/chart/teleport-kube-agent/templates/deployment.yaml @@ -81,6 +81,9 @@ spec: {{- end }} {{- end }} {{- end }} + {{- if .Values.topologySpreadConstraints }} + topologySpreadConstraints: {{- toYaml .Values.topologySpreadConstraints | nindent 8 }} + {{- end }} {{- if .Values.tolerations }} tolerations: {{- toYaml .Values.tolerations | nindent 6 }} diff --git a/examples/chart/teleport-kube-agent/templates/statefulset.yaml b/examples/chart/teleport-kube-agent/templates/statefulset.yaml index d3af3026e5024..98a549fa3447f 100644 --- a/examples/chart/teleport-kube-agent/templates/statefulset.yaml +++ b/examples/chart/teleport-kube-agent/templates/statefulset.yaml @@ -2,6 +2,7 @@ # Warning to maintainers, any changes to this file that are not specific to the StatefulSet need to also be duplicated # in the deployment.yaml file. # +{{- $topologySpreadConstraints := and (semverCompare ">=1.18.0-0" .Capabilities.KubeVersion.Version) (not .Values.disableTopologySpreadConstraints) }} {{- $replicaCount := (coalesce .Values.replicaCount .Values.highAvailability.replicaCount "1") }} apiVersion: apps/v1 kind: StatefulSet @@ -84,6 +85,25 @@ spec: {{- end }} {{- end }} {{- end }} +{{- if $topologySpreadConstraints }} + {{- if .Values.topologySpreadConstraints }} + topologySpreadConstraints: {{- toYaml .Values.topologySpreadConstraints | nindent 8 }} + {{- else }} + topologySpreadConstraints: + - maxSkew: 1 + topologyKey: kubernetes.io/hostname + whenUnsatisfiable: ScheduleAnyway + labelSelector: + matchLabels: + app: {{ .Release.Name }} + - maxSkew: 1 + topologyKey: topology.kubernetes.io/zone + whenUnsatisfiable: ScheduleAnyway + labelSelector: + matchLabels: + app: {{ .Release.Name }} + {{- end }} +{{- end }} {{- if .Values.tolerations }} tolerations: {{- toYaml .Values.tolerations | nindent 6 }} diff --git a/examples/chart/teleport-kube-agent/tests/__snapshot__/statefulset_test.yaml.snap b/examples/chart/teleport-kube-agent/tests/__snapshot__/statefulset_test.yaml.snap index d7b96f8ae9945..69924b06014f3 100644 --- a/examples/chart/teleport-kube-agent/tests/__snapshot__/statefulset_test.yaml.snap +++ b/examples/chart/teleport-kube-agent/tests/__snapshot__/statefulset_test.yaml.snap @@ -64,6 +64,19 @@ sets Pod annotations when specified: fsGroup: 9807 serviceAccountName: RELEASE-NAME terminationGracePeriodSeconds: 30 + topologySpreadConstraints: + - labelSelector: + matchLabels: + app: RELEASE-NAME + maxSkew: 1 + topologyKey: kubernetes.io/hostname + whenUnsatisfiable: ScheduleAnyway + - labelSelector: + matchLabels: + app: RELEASE-NAME + maxSkew: 1 + topologyKey: topology.kubernetes.io/zone + whenUnsatisfiable: ScheduleAnyway volumes: - configMap: name: RELEASE-NAME @@ -137,6 +150,19 @@ sets Pod labels when specified: fsGroup: 9807 serviceAccountName: RELEASE-NAME terminationGracePeriodSeconds: 30 + topologySpreadConstraints: + - labelSelector: + matchLabels: + app: RELEASE-NAME + maxSkew: 1 + topologyKey: kubernetes.io/hostname + whenUnsatisfiable: ScheduleAnyway + - labelSelector: + matchLabels: + app: RELEASE-NAME + maxSkew: 1 + topologyKey: topology.kubernetes.io/zone + whenUnsatisfiable: ScheduleAnyway volumes: - configMap: name: RELEASE-NAME @@ -234,6 +260,19 @@ sets StatefulSet labels when specified: fsGroup: 9807 serviceAccountName: RELEASE-NAME terminationGracePeriodSeconds: 30 + topologySpreadConstraints: + - labelSelector: + matchLabels: + app: RELEASE-NAME + maxSkew: 1 + topologyKey: kubernetes.io/hostname + whenUnsatisfiable: ScheduleAnyway + - labelSelector: + matchLabels: + app: RELEASE-NAME + maxSkew: 1 + topologyKey: topology.kubernetes.io/zone + whenUnsatisfiable: ScheduleAnyway volumes: - configMap: name: RELEASE-NAME @@ -339,6 +378,19 @@ should add insecureSkipProxyTLSVerify to args when set in values: fsGroup: 9807 serviceAccountName: RELEASE-NAME terminationGracePeriodSeconds: 30 + topologySpreadConstraints: + - labelSelector: + matchLabels: + app: RELEASE-NAME + maxSkew: 1 + topologyKey: kubernetes.io/hostname + whenUnsatisfiable: ScheduleAnyway + - labelSelector: + matchLabels: + app: RELEASE-NAME + maxSkew: 1 + topologyKey: topology.kubernetes.io/zone + whenUnsatisfiable: ScheduleAnyway volumes: - configMap: name: RELEASE-NAME @@ -412,6 +464,19 @@ should add volumeClaimTemplate for data volume when using StatefulSet and action fsGroup: 9807 serviceAccountName: RELEASE-NAME terminationGracePeriodSeconds: 30 + topologySpreadConstraints: + - labelSelector: + matchLabels: + app: RELEASE-NAME + maxSkew: 1 + topologyKey: kubernetes.io/hostname + whenUnsatisfiable: ScheduleAnyway + - labelSelector: + matchLabels: + app: RELEASE-NAME + maxSkew: 1 + topologyKey: topology.kubernetes.io/zone + whenUnsatisfiable: ScheduleAnyway volumes: - configMap: name: RELEASE-NAME @@ -505,6 +570,19 @@ should add volumeClaimTemplate for data volume when using StatefulSet and is Fre fsGroup: 9807 serviceAccountName: RELEASE-NAME terminationGracePeriodSeconds: 30 + topologySpreadConstraints: + - labelSelector: + matchLabels: + app: RELEASE-NAME + maxSkew: 1 + topologyKey: kubernetes.io/hostname + whenUnsatisfiable: ScheduleAnyway + - labelSelector: + matchLabels: + app: RELEASE-NAME + maxSkew: 1 + topologyKey: topology.kubernetes.io/zone + whenUnsatisfiable: ScheduleAnyway volumes: - configMap: name: RELEASE-NAME @@ -588,6 +666,19 @@ should add volumeMount for data volume when using StatefulSet: fsGroup: 9807 serviceAccountName: RELEASE-NAME terminationGracePeriodSeconds: 30 + topologySpreadConstraints: + - labelSelector: + matchLabels: + app: RELEASE-NAME + maxSkew: 1 + topologyKey: kubernetes.io/hostname + whenUnsatisfiable: ScheduleAnyway + - labelSelector: + matchLabels: + app: RELEASE-NAME + maxSkew: 1 + topologyKey: topology.kubernetes.io/zone + whenUnsatisfiable: ScheduleAnyway volumes: - configMap: name: RELEASE-NAME @@ -661,6 +752,19 @@ should expose diag port: fsGroup: 9807 serviceAccountName: RELEASE-NAME terminationGracePeriodSeconds: 30 + topologySpreadConstraints: + - labelSelector: + matchLabels: + app: RELEASE-NAME + maxSkew: 1 + topologyKey: kubernetes.io/hostname + whenUnsatisfiable: ScheduleAnyway + - labelSelector: + matchLabels: + app: RELEASE-NAME + maxSkew: 1 + topologyKey: topology.kubernetes.io/zone + whenUnsatisfiable: ScheduleAnyway volumes: - configMap: name: RELEASE-NAME @@ -734,6 +838,19 @@ should generate Statefulset when storage is disabled and mode is a Upgrade: fsGroup: 9807 serviceAccountName: RELEASE-NAME terminationGracePeriodSeconds: 30 + topologySpreadConstraints: + - labelSelector: + matchLabels: + app: RELEASE-NAME + maxSkew: 1 + topologyKey: kubernetes.io/hostname + whenUnsatisfiable: ScheduleAnyway + - labelSelector: + matchLabels: + app: RELEASE-NAME + maxSkew: 1 + topologyKey: topology.kubernetes.io/zone + whenUnsatisfiable: ScheduleAnyway volumes: - configMap: name: RELEASE-NAME @@ -821,6 +938,19 @@ should have multiple replicas when replicaCount is set (using .replicaCount, dep fsGroup: 9807 serviceAccountName: RELEASE-NAME terminationGracePeriodSeconds: 30 + topologySpreadConstraints: + - labelSelector: + matchLabels: + app: RELEASE-NAME + maxSkew: 1 + topologyKey: kubernetes.io/hostname + whenUnsatisfiable: ScheduleAnyway + - labelSelector: + matchLabels: + app: RELEASE-NAME + maxSkew: 1 + topologyKey: topology.kubernetes.io/zone + whenUnsatisfiable: ScheduleAnyway volumes: - configMap: name: RELEASE-NAME @@ -906,6 +1036,19 @@ should have multiple replicas when replicaCount is set (using highAvailability.r fsGroup: 9807 serviceAccountName: RELEASE-NAME terminationGracePeriodSeconds: 30 + topologySpreadConstraints: + - labelSelector: + matchLabels: + app: RELEASE-NAME + maxSkew: 1 + topologyKey: kubernetes.io/hostname + whenUnsatisfiable: ScheduleAnyway + - labelSelector: + matchLabels: + app: RELEASE-NAME + maxSkew: 1 + topologyKey: topology.kubernetes.io/zone + whenUnsatisfiable: ScheduleAnyway volumes: - configMap: name: RELEASE-NAME @@ -979,6 +1122,19 @@ should have one replica when replicaCount is not set: fsGroup: 9807 serviceAccountName: RELEASE-NAME terminationGracePeriodSeconds: 30 + topologySpreadConstraints: + - labelSelector: + matchLabels: + app: RELEASE-NAME + maxSkew: 1 + topologyKey: kubernetes.io/hostname + whenUnsatisfiable: ScheduleAnyway + - labelSelector: + matchLabels: + app: RELEASE-NAME + maxSkew: 1 + topologyKey: topology.kubernetes.io/zone + whenUnsatisfiable: ScheduleAnyway volumes: - configMap: name: RELEASE-NAME @@ -1052,6 +1208,19 @@ should install Statefulset when storage is disabled and mode is a Fresh Install: fsGroup: 9807 serviceAccountName: RELEASE-NAME terminationGracePeriodSeconds: 30 + topologySpreadConstraints: + - labelSelector: + matchLabels: + app: RELEASE-NAME + maxSkew: 1 + topologyKey: kubernetes.io/hostname + whenUnsatisfiable: ScheduleAnyway + - labelSelector: + matchLabels: + app: RELEASE-NAME + maxSkew: 1 + topologyKey: topology.kubernetes.io/zone + whenUnsatisfiable: ScheduleAnyway volumes: - configMap: name: RELEASE-NAME @@ -1129,6 +1298,19 @@ should mount extraVolumes and extraVolumeMounts: fsGroup: 9807 serviceAccountName: RELEASE-NAME terminationGracePeriodSeconds: 30 + topologySpreadConstraints: + - labelSelector: + matchLabels: + app: RELEASE-NAME + maxSkew: 1 + topologyKey: kubernetes.io/hostname + whenUnsatisfiable: ScheduleAnyway + - labelSelector: + matchLabels: + app: RELEASE-NAME + maxSkew: 1 + topologyKey: topology.kubernetes.io/zone + whenUnsatisfiable: ScheduleAnyway volumes: - configMap: name: RELEASE-NAME @@ -1208,6 +1390,19 @@ should mount jamfCredentialsSecret if it already exists and when role is jamf: fsGroup: 9807 serviceAccountName: RELEASE-NAME terminationGracePeriodSeconds: 30 + topologySpreadConstraints: + - labelSelector: + matchLabels: + app: RELEASE-NAME + maxSkew: 1 + topologyKey: kubernetes.io/hostname + whenUnsatisfiable: ScheduleAnyway + - labelSelector: + matchLabels: + app: RELEASE-NAME + maxSkew: 1 + topologyKey: topology.kubernetes.io/zone + whenUnsatisfiable: ScheduleAnyway volumes: - configMap: name: RELEASE-NAME @@ -1289,6 +1484,19 @@ should mount jamfCredentialsSecret.name when role is jamf: fsGroup: 9807 serviceAccountName: RELEASE-NAME terminationGracePeriodSeconds: 30 + topologySpreadConstraints: + - labelSelector: + matchLabels: + app: RELEASE-NAME + maxSkew: 1 + topologyKey: kubernetes.io/hostname + whenUnsatisfiable: ScheduleAnyway + - labelSelector: + matchLabels: + app: RELEASE-NAME + maxSkew: 1 + topologyKey: topology.kubernetes.io/zone + whenUnsatisfiable: ScheduleAnyway volumes: - configMap: name: RELEASE-NAME @@ -1372,6 +1580,19 @@ should mount tls.existingCASecretName and set environment when set in values: fsGroup: 9807 serviceAccountName: RELEASE-NAME terminationGracePeriodSeconds: 30 + topologySpreadConstraints: + - labelSelector: + matchLabels: + app: RELEASE-NAME + maxSkew: 1 + topologyKey: kubernetes.io/hostname + whenUnsatisfiable: ScheduleAnyway + - labelSelector: + matchLabels: + app: RELEASE-NAME + maxSkew: 1 + topologyKey: topology.kubernetes.io/zone + whenUnsatisfiable: ScheduleAnyway volumes: - configMap: name: RELEASE-NAME @@ -1457,6 +1678,19 @@ should mount tls.existingCASecretName and set extra environment when set in valu fsGroup: 9807 serviceAccountName: RELEASE-NAME terminationGracePeriodSeconds: 30 + topologySpreadConstraints: + - labelSelector: + matchLabels: + app: RELEASE-NAME + maxSkew: 1 + topologyKey: kubernetes.io/hostname + whenUnsatisfiable: ScheduleAnyway + - labelSelector: + matchLabels: + app: RELEASE-NAME + maxSkew: 1 + topologyKey: topology.kubernetes.io/zone + whenUnsatisfiable: ScheduleAnyway volumes: - configMap: name: RELEASE-NAME @@ -1535,6 +1769,19 @@ should not add emptyDir for data when using StatefulSet: fsGroup: 9807 serviceAccountName: RELEASE-NAME terminationGracePeriodSeconds: 30 + topologySpreadConstraints: + - labelSelector: + matchLabels: + app: RELEASE-NAME + maxSkew: 1 + topologyKey: kubernetes.io/hostname + whenUnsatisfiable: ScheduleAnyway + - labelSelector: + matchLabels: + app: RELEASE-NAME + maxSkew: 1 + topologyKey: topology.kubernetes.io/zone + whenUnsatisfiable: ScheduleAnyway volumes: - configMap: name: RELEASE-NAME @@ -1646,6 +1893,19 @@ should provision initContainer correctly when set in values: fsGroup: 9807 serviceAccountName: RELEASE-NAME terminationGracePeriodSeconds: 30 + topologySpreadConstraints: + - labelSelector: + matchLabels: + app: RELEASE-NAME + maxSkew: 1 + topologyKey: kubernetes.io/hostname + whenUnsatisfiable: ScheduleAnyway + - labelSelector: + matchLabels: + app: RELEASE-NAME + maxSkew: 1 + topologyKey: topology.kubernetes.io/zone + whenUnsatisfiable: ScheduleAnyway volumes: - configMap: name: RELEASE-NAME @@ -1739,6 +1999,19 @@ should set affinity when set in values: fsGroup: 9807 serviceAccountName: RELEASE-NAME terminationGracePeriodSeconds: 30 + topologySpreadConstraints: + - labelSelector: + matchLabels: + app: RELEASE-NAME + maxSkew: 1 + topologyKey: kubernetes.io/hostname + whenUnsatisfiable: ScheduleAnyway + - labelSelector: + matchLabels: + app: RELEASE-NAME + maxSkew: 1 + topologyKey: topology.kubernetes.io/zone + whenUnsatisfiable: ScheduleAnyway volumes: - configMap: name: RELEASE-NAME @@ -1812,6 +2085,19 @@ should set default serviceAccountName when not set in values: fsGroup: 9807 serviceAccountName: RELEASE-NAME terminationGracePeriodSeconds: 30 + topologySpreadConstraints: + - labelSelector: + matchLabels: + app: RELEASE-NAME + maxSkew: 1 + topologyKey: kubernetes.io/hostname + whenUnsatisfiable: ScheduleAnyway + - labelSelector: + matchLabels: + app: RELEASE-NAME + maxSkew: 1 + topologyKey: topology.kubernetes.io/zone + whenUnsatisfiable: ScheduleAnyway volumes: - configMap: name: RELEASE-NAME @@ -1898,6 +2184,19 @@ should set environment when extraEnv set in values: fsGroup: 9807 serviceAccountName: RELEASE-NAME terminationGracePeriodSeconds: 30 + topologySpreadConstraints: + - labelSelector: + matchLabels: + app: RELEASE-NAME + maxSkew: 1 + topologyKey: kubernetes.io/hostname + whenUnsatisfiable: ScheduleAnyway + - labelSelector: + matchLabels: + app: RELEASE-NAME + maxSkew: 1 + topologyKey: topology.kubernetes.io/zone + whenUnsatisfiable: ScheduleAnyway volumes: - configMap: name: RELEASE-NAME @@ -1971,6 +2270,19 @@ should set image and tag correctly: fsGroup: 9807 serviceAccountName: RELEASE-NAME terminationGracePeriodSeconds: 30 + topologySpreadConstraints: + - labelSelector: + matchLabels: + app: RELEASE-NAME + maxSkew: 1 + topologyKey: kubernetes.io/hostname + whenUnsatisfiable: ScheduleAnyway + - labelSelector: + matchLabels: + app: RELEASE-NAME + maxSkew: 1 + topologyKey: topology.kubernetes.io/zone + whenUnsatisfiable: ScheduleAnyway volumes: - configMap: name: RELEASE-NAME @@ -2044,6 +2356,19 @@ should set imagePullPolicy when set in values: fsGroup: 9807 serviceAccountName: RELEASE-NAME terminationGracePeriodSeconds: 30 + topologySpreadConstraints: + - labelSelector: + matchLabels: + app: RELEASE-NAME + maxSkew: 1 + topologyKey: kubernetes.io/hostname + whenUnsatisfiable: ScheduleAnyway + - labelSelector: + matchLabels: + app: RELEASE-NAME + maxSkew: 1 + topologyKey: topology.kubernetes.io/zone + whenUnsatisfiable: ScheduleAnyway volumes: - configMap: name: RELEASE-NAME @@ -2119,6 +2444,19 @@ should set nodeSelector if set in values: fsGroup: 9807 serviceAccountName: RELEASE-NAME terminationGracePeriodSeconds: 30 + topologySpreadConstraints: + - labelSelector: + matchLabels: + app: RELEASE-NAME + maxSkew: 1 + topologyKey: kubernetes.io/hostname + whenUnsatisfiable: ScheduleAnyway + - labelSelector: + matchLabels: + app: RELEASE-NAME + maxSkew: 1 + topologyKey: topology.kubernetes.io/zone + whenUnsatisfiable: ScheduleAnyway volumes: - configMap: name: RELEASE-NAME @@ -2204,6 +2542,19 @@ should set preferred affinity when more than one replica is used: fsGroup: 9807 serviceAccountName: RELEASE-NAME terminationGracePeriodSeconds: 30 + topologySpreadConstraints: + - labelSelector: + matchLabels: + app: RELEASE-NAME + maxSkew: 1 + topologyKey: kubernetes.io/hostname + whenUnsatisfiable: ScheduleAnyway + - labelSelector: + matchLabels: + app: RELEASE-NAME + maxSkew: 1 + topologyKey: topology.kubernetes.io/zone + whenUnsatisfiable: ScheduleAnyway volumes: - configMap: name: RELEASE-NAME @@ -2277,6 +2628,19 @@ should set probeTimeoutSeconds when set in values: fsGroup: 9807 serviceAccountName: RELEASE-NAME terminationGracePeriodSeconds: 30 + topologySpreadConstraints: + - labelSelector: + matchLabels: + app: RELEASE-NAME + maxSkew: 1 + topologyKey: kubernetes.io/hostname + whenUnsatisfiable: ScheduleAnyway + - labelSelector: + matchLabels: + app: RELEASE-NAME + maxSkew: 1 + topologyKey: topology.kubernetes.io/zone + whenUnsatisfiable: ScheduleAnyway volumes: - configMap: name: RELEASE-NAME @@ -2360,6 +2724,19 @@ should set required affinity when highAvailability.requireAntiAffinity is set: fsGroup: 9807 serviceAccountName: RELEASE-NAME terminationGracePeriodSeconds: 30 + topologySpreadConstraints: + - labelSelector: + matchLabels: + app: RELEASE-NAME + maxSkew: 1 + topologyKey: kubernetes.io/hostname + whenUnsatisfiable: ScheduleAnyway + - labelSelector: + matchLabels: + app: RELEASE-NAME + maxSkew: 1 + topologyKey: topology.kubernetes.io/zone + whenUnsatisfiable: ScheduleAnyway volumes: - configMap: name: RELEASE-NAME @@ -2440,6 +2817,19 @@ should set resources when set in values: fsGroup: 9807 serviceAccountName: RELEASE-NAME terminationGracePeriodSeconds: 30 + topologySpreadConstraints: + - labelSelector: + matchLabels: + app: RELEASE-NAME + maxSkew: 1 + topologyKey: kubernetes.io/hostname + whenUnsatisfiable: ScheduleAnyway + - labelSelector: + matchLabels: + app: RELEASE-NAME + maxSkew: 1 + topologyKey: topology.kubernetes.io/zone + whenUnsatisfiable: ScheduleAnyway volumes: - configMap: name: RELEASE-NAME @@ -2513,6 +2903,19 @@ should set serviceAccountName when set in values: fsGroup: 9807 serviceAccountName: teleport-kube-agent-sa terminationGracePeriodSeconds: 30 + topologySpreadConstraints: + - labelSelector: + matchLabels: + app: RELEASE-NAME + maxSkew: 1 + topologyKey: kubernetes.io/hostname + whenUnsatisfiable: ScheduleAnyway + - labelSelector: + matchLabels: + app: RELEASE-NAME + maxSkew: 1 + topologyKey: topology.kubernetes.io/zone + whenUnsatisfiable: ScheduleAnyway volumes: - configMap: name: RELEASE-NAME @@ -2586,6 +2989,19 @@ should set storage.requests when set in values and action is an Upgrade: fsGroup: 9807 serviceAccountName: RELEASE-NAME terminationGracePeriodSeconds: 30 + topologySpreadConstraints: + - labelSelector: + matchLabels: + app: RELEASE-NAME + maxSkew: 1 + topologyKey: kubernetes.io/hostname + whenUnsatisfiable: ScheduleAnyway + - labelSelector: + matchLabels: + app: RELEASE-NAME + maxSkew: 1 + topologyKey: topology.kubernetes.io/zone + whenUnsatisfiable: ScheduleAnyway volumes: - configMap: name: RELEASE-NAME @@ -2659,6 +3075,19 @@ should set storage.storageClassName when set in values and action is an Upgrade: fsGroup: 9807 serviceAccountName: RELEASE-NAME terminationGracePeriodSeconds: 30 + topologySpreadConstraints: + - labelSelector: + matchLabels: + app: RELEASE-NAME + maxSkew: 1 + topologyKey: kubernetes.io/hostname + whenUnsatisfiable: ScheduleAnyway + - labelSelector: + matchLabels: + app: RELEASE-NAME + maxSkew: 1 + topologyKey: topology.kubernetes.io/zone + whenUnsatisfiable: ScheduleAnyway volumes: - configMap: name: RELEASE-NAME @@ -2741,6 +3170,19 @@ should set tolerations when set in values: key: dedicated operator: Equal value: teleport + topologySpreadConstraints: + - labelSelector: + matchLabels: + app: RELEASE-NAME + maxSkew: 1 + topologyKey: kubernetes.io/hostname + whenUnsatisfiable: ScheduleAnyway + - labelSelector: + matchLabels: + app: RELEASE-NAME + maxSkew: 1 + topologyKey: topology.kubernetes.io/zone + whenUnsatisfiable: ScheduleAnyway volumes: - configMap: name: RELEASE-NAME diff --git a/examples/chart/teleport-kube-agent/tests/statefulset_test.yaml b/examples/chart/teleport-kube-agent/tests/statefulset_test.yaml index 7b73fa198d13a..e43074c6f3ec1 100644 --- a/examples/chart/teleport-kube-agent/tests/statefulset_test.yaml +++ b/examples/chart/teleport-kube-agent/tests/statefulset_test.yaml @@ -160,6 +160,75 @@ tests: - matchSnapshot: path: spec.template.spec + - it: sets topology spread constraints by default + template: statefulset.yaml + values: + - ../.lint/stateful.yaml + asserts: + - equal: + path: spec.template.spec.topologySpreadConstraints + value: + - maxSkew: 1 + topologyKey: kubernetes.io/hostname + whenUnsatisfiable: ScheduleAnyway + labelSelector: + matchLabels: + app: RELEASE-NAME + - maxSkew: 1 + topologyKey: topology.kubernetes.io/zone + whenUnsatisfiable: ScheduleAnyway + labelSelector: + matchLabels: + app: RELEASE-NAME + + - it: removes topology spread constraints when disabled + template: statefulset.yaml + values: + - ../.lint/stateful.yaml + set: + disableTopologySpreadConstraints: true + asserts: + - isEmpty: + path: spec.template.spec.topologySpreadConstraints + + - it: removes topology spread constraints when running on antique kubernetes + template: statefulset.yaml + values: + - ../.lint/stateful.yaml + capabilities: + majorVersion: 1 + minorVersion: 17 + asserts: + - isEmpty: + path: spec.template.spec.topologySpreadConstraints + + - it: uses custom topology spread constraints when set + template: statefulset.yaml + values: + - ../.lint/stateful.yaml + set: + topologySpreadConstraints: + - maxSkew: 2 + topologyKey: foobar + whenUnsatisfiable: ScheduleAnyway + labelSelector: + matchLabels: + app: baz + # helm unit-test has a bug where capabilities are not reset between tests, we must set back to 1.18 after the 1.17 test. + capabilities: + majorVersion: 1 + minorVersion: 18 + asserts: + - equal: + path: spec.template.spec.topologySpreadConstraints + value: + - maxSkew: 2 + topologyKey: foobar + whenUnsatisfiable: ScheduleAnyway + labelSelector: + matchLabels: + app: baz + - it: should set tolerations when set in values template: statefulset.yaml values: diff --git a/examples/chart/teleport-kube-agent/values.schema.json b/examples/chart/teleport-kube-agent/values.schema.json index 96926f030892e..621a1f2f306fc 100644 --- a/examples/chart/teleport-kube-agent/values.schema.json +++ b/examples/chart/teleport-kube-agent/values.schema.json @@ -524,6 +524,11 @@ "type": "object", "default": {} }, + "topologySpreadConstraints": { + "$id": "#/properties/topologySpreadConstraints", + "type": "array", + "default": [] + }, "dnsConfig": { "$id": "#/properties/dnsConfig", "type": "object", diff --git a/examples/chart/teleport-kube-agent/values.yaml b/examples/chart/teleport-kube-agent/values.yaml index 9610bf345ca17..b356e2c619447 100644 --- a/examples/chart/teleport-kube-agent/values.yaml +++ b/examples/chart/teleport-kube-agent/values.yaml @@ -1092,6 +1092,32 @@ log: # for more details. affinity: {} +# disableTopologySpreadConstraints(bool) -- turns off the topology spread constraints. +# The feature is automatically turned off on Kubernetes versions below 1.18. +disableTopologySpreadConstraints: false + +# topologySpreadConstraints(list) -- sets the topology spread constraints for any pods created by the chart. +# See [the Kubernetes documentation](https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/) +# for more details. +# +# When unset, the chart defaults to a soft topology spread constraint +# that tries to spread pods across hosts and zones. +# +# ``` +# topologySpreadConstraints: +# - maxSkew: 1 +# topologyKey: kubernetes.io/hostname +# whenUnsatisfiable: ScheduleAnyway +# labelSelector: +# matchLabels: # dynamically computed +# - maxSkew: 1 +# topologyKey: topology.kubernetes.io/zone +# whenUnsatisfiable: ScheduleAnyway +# labelSelector: +# matchLabels: # dynamically computed +# ``` +topologySpreadConstraints: [] + # dnsConfig(object) -- contains custom Pod DNS Configuration for the agent pods. # This value is useful if you need to reduce the DNS load: set "ndots" to 0 and # only use FQDNs to refer to applications and databases.