From 740e0f471e390db37feecae08b86538ac68596e4 Mon Sep 17 00:00:00 2001 From: simonzhekoff Date: Mon, 29 Jun 2026 13:28:34 +0300 Subject: [PATCH 1/2] Added Topology Constaints --- CHANGELOG.md | 5 ++++ README.md | 45 ++++++++++++++++++++++++++++++ templates/graphdb/statefulset.yaml | 24 ++++++++++++++-- templates/proxy/statefulset.yaml | 24 ++++++++++++++-- values.yaml | 24 ++++++++++++++++ 5 files changed, 118 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2410629..96a81d7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,11 @@ Workbench or REST API. - Added `publishNotReadyAddresses` to `service`, `headlessService`, `proxy.service` and `proxy.headlessService`. Headless services default to `true` to allow cluster nodes to communicate before readiness probes pass, enabling proper startup sequencing during rolling upgrades. +- Added `topologySpreadConstraintsPreset` for GraphDB and proxy StatefulSets. When enabled, automatically + configures two topology spread constraints that spread pods across availability zones + (`topology.kubernetes.io/zone`) and nodes (`kubernetes.io/hostname`). Simplifies cloud deployments on + AWS/Azure/GCP with multiple availability zones. Explicit `topologySpreadConstraints` takes precedence + when set. ## Version 12.4.0 diff --git a/README.md b/README.md index 7b34aec..258becb 100644 --- a/README.md +++ b/README.md @@ -250,6 +250,45 @@ The Ingress can be disabled by switching `ingress.enabled` to false. Some cloud Kubernetes clusters have some specifics that should be noted. Here are some useful tips on some cloud K8s clusters: +#### Topology Spread Constraints + +For cloud deployments on AWS (EKS), Azure (AKS), or GCP (GKE) with multiple availability zones, enable the +topology spread constraints preset to automatically spread GraphDB pods across zones and nodes: + +```yaml +topologySpreadConstraintsPreset: + enabled: true + +# For the proxy StatefulSet (when using GraphDB cluster): +proxy: + topologySpreadConstraintsPreset: + enabled: true +``` + +This generates two `ScheduleAnyway` (soft) constraints — one per availability zone, one per node — ensuring +pods are distributed evenly without blocking scheduling when perfect spread is not possible. + +To enforce strict spreading (pods won't schedule if spread can't be satisfied), use `DoNotSchedule`: + +```yaml +topologySpreadConstraintsPreset: + enabled: true + whenUnsatisfiable: DoNotSchedule +``` + +For full control over the constraints, use `topologySpreadConstraints` directly — it takes precedence over +the preset when set: + +```yaml +topologySpreadConstraints: + - topologyKey: topology.kubernetes.io/zone + maxSkew: 1 + whenUnsatisfiable: ScheduleAnyway + labelSelector: + matchLabels: + app.kubernetes.io/name: graphdb +``` + ##### Microsoft Azure We recommend not to use the Microsoft Azure storage of type `azurefile`. The write speeds of this storage type when used in a Kubernetes cluster is @@ -637,6 +676,9 @@ IMPORTANT: This is generated by helm-docs, do not attempt modifying it on hand a | proxy.terminationGracePeriodSeconds | int | `30` | | | proxy.tolerations | list | `[]` | | | proxy.topologySpreadConstraints | list | `[]` | | +| proxy.topologySpreadConstraintsPreset.enabled | bool | `false` | | +| proxy.topologySpreadConstraintsPreset.maxSkew | int | `1` | | +| proxy.topologySpreadConstraintsPreset.whenUnsatisfiable | string | `"ScheduleAnyway"` | | | proxy.updateStrategy.type | string | `"RollingUpdate"` | | | readinessProbe.httpGet.path | string | `"/protocol"` | | | readinessProbe.httpGet.port | string | `"http"` | | @@ -690,6 +732,9 @@ IMPORTANT: This is generated by helm-docs, do not attempt modifying it on hand a | terminationGracePeriodSeconds | int | `120` | | | tolerations | list | `[]` | | | topologySpreadConstraints | list | `[]` | | +| topologySpreadConstraintsPreset.enabled | bool | `false` | | +| topologySpreadConstraintsPreset.maxSkew | int | `1` | | +| topologySpreadConstraintsPreset.whenUnsatisfiable | string | `"ScheduleAnyway"` | | | updateStrategy.type | string | `"RollingUpdate"` | | ## Troubleshooting diff --git a/templates/graphdb/statefulset.yaml b/templates/graphdb/statefulset.yaml index 14aa810..4c8635b 100644 --- a/templates/graphdb/statefulset.yaml +++ b/templates/graphdb/statefulset.yaml @@ -264,8 +264,28 @@ spec: {{- with .Values.tolerations }} tolerations: {{- tpl (toYaml .) $ | nindent 8 }} {{- end }} - {{- with .Values.topologySpreadConstraints }} - topologySpreadConstraints: {{- tpl (toYaml .) $ | nindent 8 }} + {{- if or .Values.topologySpreadConstraints .Values.topologySpreadConstraintsPreset.enabled }} + topologySpreadConstraints: + {{- if .Values.topologySpreadConstraints }} + {{- tpl (toYaml .Values.topologySpreadConstraints) $ | nindent 8 }} + {{- else }} + - labelSelector: + matchLabels: + {{- include "graphdb.selectorLabels" . | nindent 14 }} + matchLabelKeys: + - pod-template-hash + topologyKey: topology.kubernetes.io/zone + maxSkew: {{ .Values.topologySpreadConstraintsPreset.maxSkew }} + whenUnsatisfiable: {{ .Values.topologySpreadConstraintsPreset.whenUnsatisfiable }} + - labelSelector: + matchLabels: + {{- include "graphdb.selectorLabels" . | nindent 14 }} + matchLabelKeys: + - pod-template-hash + topologyKey: kubernetes.io/hostname + maxSkew: {{ .Values.topologySpreadConstraintsPreset.maxSkew }} + whenUnsatisfiable: {{ .Values.topologySpreadConstraintsPreset.whenUnsatisfiable }} + {{- end }} {{- end }} {{- with .Values.podSecurityContext }} securityContext: {{- toYaml . | nindent 8 }} diff --git a/templates/proxy/statefulset.yaml b/templates/proxy/statefulset.yaml index 09458ea..2c6b732 100644 --- a/templates/proxy/statefulset.yaml +++ b/templates/proxy/statefulset.yaml @@ -227,8 +227,28 @@ spec: {{- with .Values.proxy.tolerations }} tolerations: {{- tpl (toYaml .) $ | nindent 8 }} {{- end }} - {{- with .Values.proxy.topologySpreadConstraints }} - topologySpreadConstraints: {{- tpl (toYaml .) $ | nindent 8 }} + {{- if or .Values.proxy.topologySpreadConstraints .Values.proxy.topologySpreadConstraintsPreset.enabled }} + topologySpreadConstraints: + {{- if .Values.proxy.topologySpreadConstraints }} + {{- tpl (toYaml .Values.proxy.topologySpreadConstraints) $ | nindent 8 }} + {{- else }} + - labelSelector: + matchLabels: + {{- include "graphdb-proxy.selectorLabels" . | nindent 14 }} + matchLabelKeys: + - pod-template-hash + topologyKey: topology.kubernetes.io/zone + maxSkew: {{ .Values.proxy.topologySpreadConstraintsPreset.maxSkew }} + whenUnsatisfiable: {{ .Values.proxy.topologySpreadConstraintsPreset.whenUnsatisfiable }} + - labelSelector: + matchLabels: + {{- include "graphdb-proxy.selectorLabels" . | nindent 14 }} + matchLabelKeys: + - pod-template-hash + topologyKey: kubernetes.io/hostname + maxSkew: {{ .Values.proxy.topologySpreadConstraintsPreset.maxSkew }} + whenUnsatisfiable: {{ .Values.proxy.topologySpreadConstraintsPreset.whenUnsatisfiable }} + {{- end }} {{- end }} {{- with .Values.proxy.podSecurityContext }} securityContext: {{- toYaml . | nindent 8 }} diff --git a/values.yaml b/values.yaml index e87a720..b207f24 100644 --- a/values.yaml +++ b/values.yaml @@ -1023,6 +1023,18 @@ tolerations: [] # Ref: https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/ topologySpreadConstraints: [] +# Default topology spread constraints preset ensuring GraphDB pods are spread across availability zones and nodes. +# When enabled and topologySpreadConstraints is empty, two constraints are generated: +# - Spread across availability zones (topology.kubernetes.io/zone) +# - Spread across nodes (kubernetes.io/hostname) +# Useful for cloud deployments on AWS/Azure/GCP with multiple availability zones. +# Note: topologySpreadConstraints takes precedence over this preset when set. +# Ref: https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/ +topologySpreadConstraintsPreset: + enabled: false + maxSkew: 1 + whenUnsatisfiable: ScheduleAnyway + ########################## # Resource Configuration # ########################## @@ -1641,6 +1653,18 @@ proxy: # Ref: https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/ topologySpreadConstraints: [] + # Default topology spread constraints preset ensuring GraphDB proxy pods are spread across availability zones and nodes. + # When enabled and topologySpreadConstraints is empty, two constraints are generated: + # - Spread across availability zones (topology.kubernetes.io/zone) + # - Spread across nodes (kubernetes.io/hostname) + # Useful for cloud deployments on AWS/Azure/GCP with multiple availability zones. + # Note: topologySpreadConstraints takes precedence over this preset when set. + # Ref: https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/ + topologySpreadConstraintsPreset: + enabled: false + maxSkew: 1 + whenUnsatisfiable: ScheduleAnyway + ########################## # Resource Configuration # ########################## From dc07de3a742651d8fca811081886f1f2c17e05a5 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 29 Jun 2026 10:31:37 +0000 Subject: [PATCH 2/2] Updated the README --- README.md | 39 --------------------------------------- 1 file changed, 39 deletions(-) diff --git a/README.md b/README.md index 258becb..a6076c7 100644 --- a/README.md +++ b/README.md @@ -250,45 +250,6 @@ The Ingress can be disabled by switching `ingress.enabled` to false. Some cloud Kubernetes clusters have some specifics that should be noted. Here are some useful tips on some cloud K8s clusters: -#### Topology Spread Constraints - -For cloud deployments on AWS (EKS), Azure (AKS), or GCP (GKE) with multiple availability zones, enable the -topology spread constraints preset to automatically spread GraphDB pods across zones and nodes: - -```yaml -topologySpreadConstraintsPreset: - enabled: true - -# For the proxy StatefulSet (when using GraphDB cluster): -proxy: - topologySpreadConstraintsPreset: - enabled: true -``` - -This generates two `ScheduleAnyway` (soft) constraints — one per availability zone, one per node — ensuring -pods are distributed evenly without blocking scheduling when perfect spread is not possible. - -To enforce strict spreading (pods won't schedule if spread can't be satisfied), use `DoNotSchedule`: - -```yaml -topologySpreadConstraintsPreset: - enabled: true - whenUnsatisfiable: DoNotSchedule -``` - -For full control over the constraints, use `topologySpreadConstraints` directly — it takes precedence over -the preset when set: - -```yaml -topologySpreadConstraints: - - topologyKey: topology.kubernetes.io/zone - maxSkew: 1 - whenUnsatisfiable: ScheduleAnyway - labelSelector: - matchLabels: - app.kubernetes.io/name: graphdb -``` - ##### Microsoft Azure We recommend not to use the Microsoft Azure storage of type `azurefile`. The write speeds of this storage type when used in a Kubernetes cluster is