Skip to content

Commit

Permalink
Make StatefulSet updateStrategy configurable (#845)
Browse files Browse the repository at this point in the history
* Make updateStrategy configurable

* Update docs

---------

Co-authored-by: Yevhen Ivantsov <[email protected]>
  • Loading branch information
bianchi2 and Yevhen Ivantsov authored Jul 31, 2024
1 parent d7aa523 commit e01bfce
Show file tree
Hide file tree
Showing 24 changed files with 185 additions and 16 deletions.
1 change: 1 addition & 0 deletions src/main/charts/bamboo/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ Kubernetes: `>=1.21.x-0`
| serviceAccount.create | bool | `true` | Set to 'true' if a ServiceAccount should be created, or 'false' if it already exists. |
| serviceAccount.imagePullSecrets | list | `[]` | For Docker images hosted in private registries, define the list of image pull secrets that should be utilized by the created ServiceAccount https://kubernetes.io/docs/concepts/containers/images/#specifying-imagepullsecrets-on-a-pod |
| serviceAccount.name | string | `nil` | The name of the ServiceAccount to be used by the pods. If not specified, but the "serviceAccount.create" flag is set to 'true', then the ServiceAccount name will be auto-generated, otherwise the 'default' ServiceAccount will be used. https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#use-the-default-service-account-to-access-the-api-server |
| statefulSet | object | `{"updateStrategy":{}}` | StatefulSet update strategy. When unset defaults to Rolling update. See: https://kubernetes.io/docs/tutorials/stateful-application/basic-stateful-set/#updating-statefulsets |
| testPods | object | `{"affinity":{},"annotations":{},"image":{"permissionsTestContainer":"debian:stable-slim","statusTestContainer":"alpine:latest"},"labels":{},"nodeSelector":{},"resources":{},"schedulerName":null,"tolerations":[]}` | Metadata and pod spec for pods started in Helm tests |
| tolerations | list | `[]` | Standard K8s tolerations that will be applied to all Bamboo pods |
| volumes.additional | list | `[]` | Defines additional volumes that should be applied to all Bamboo pods. Note that this will not create any corresponding volume mounts; those needs to be defined in bamboo.additionalVolumeMounts |
Expand Down
6 changes: 6 additions & 0 deletions src/main/charts/bamboo/templates/statefulset.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ metadata:
labels:
{{- include "common.labels.commonLabels" . | nindent 4 }}
spec:
{{- if .Values.statefulSet.updateStrategy }}
{{- with .Values.statefulSet.updateStrategy }}
updateStrategy:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}
{{ if .Values.ordinals.enabled }}
ordinals:
start: {{ .Values.ordinals.start }}
Expand Down
6 changes: 6 additions & 0 deletions src/main/charts/bamboo/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1301,3 +1301,9 @@ openshift:
# configuration files as ConfigMaps.
#
runWithRestrictedSCC: false

# -- StatefulSet update strategy. When unset defaults to Rolling update. See: https://kubernetes.io/docs/tutorials/stateful-application/basic-stateful-set/#updating-statefulsets
#
statefulSet:
updateStrategy: {}
# type: OnDelete
1 change: 1 addition & 0 deletions src/main/charts/bitbucket/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,7 @@ Kubernetes: `>=1.21.x-0`
| serviceAccount.name | string | `nil` | The name of the ServiceAccount to be used by the pods. If not specified, but the "serviceAccount.create" flag is set to 'true', then the ServiceAccount name will be auto-generated, otherwise the 'default' ServiceAccount will be used. https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#use-the-default-service-account-to-access-the-api-server |
| serviceAccount.role.create | bool | `true` | Create a role for Hazelcast client with privileges to get and list pods and endpoints in the namespace. Set to false if you need to create a Role and RoleBinding manually |
| serviceAccount.roleBinding | object | `{"create":true}` | Grant permissions defined in Role (list and get pods and endpoints) to a service account. |
| statefulSet | object | `{"updateStrategy":{}}` | StatefulSet update strategy. When unset defaults to Rolling update. See: https://kubernetes.io/docs/tutorials/stateful-application/basic-stateful-set/#updating-statefulsets |
| testPods | object | `{"affinity":{},"annotations":{},"image":{"permissionsTestContainer":"debian:stable-slim","statusTestContainer":"alpine:latest"},"labels":{},"nodeSelector":{},"resources":{},"schedulerName":null,"tolerations":[]}` | Metadata and pod spec for pods started in Helm tests |
| tolerations | list | `[]` | Standard K8s tolerations that will be applied to all Bitbucket pods |
| volumes.additional | list | `[]` | Defines additional volumes that should be applied to all Bitbucket pods. Note that this will not create any corresponding volume mounts; those need to be defined in bitbucket.additionalVolumeMounts |
Expand Down
10 changes: 6 additions & 4 deletions src/main/charts/bitbucket/templates/statefulset-mesh.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,17 @@ metadata:
labels:
{{- include "common.labels.commonLabels" . | nindent 4 }}
spec:
{{- if .Values.statefulSet.updateStrategy }}
{{- with .Values.statefulSet.updateStrategy }}
updateStrategy:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}
{{ if .Values.ordinals.enabled }}
ordinals:
start: {{ .Values.ordinals.start }}
{{ end }}
replicas: {{ .Values.bitbucket.mesh.replicaCount }}
updateStrategy:
type: RollingUpdate
rollingUpdate:
partition: 0
podManagementPolicy: {{ default "OrderedReady" .Values.bitbucket.mesh.podManagementPolicy }}
serviceName: {{ include "common.names.fullname" . }}-mesh
selector:
Expand Down
10 changes: 6 additions & 4 deletions src/main/charts/bitbucket/templates/statefulset.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,17 @@ metadata:
labels:
{{- include "common.labels.commonLabels" . | nindent 4 }}
spec:
{{- if .Values.statefulSet.updateStrategy }}
{{- with .Values.statefulSet.updateStrategy }}
updateStrategy:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}
{{ if .Values.ordinals.enabled }}
ordinals:
start: {{ .Values.ordinals.start }}
{{ end }}
replicas: {{ .Values.replicaCount }}
updateStrategy:
type: RollingUpdate
rollingUpdate:
partition: 0
podManagementPolicy: {{ default "OrderedReady" .Values.bitbucket.podManagementStrategy }}
serviceName: {{ include "common.names.fullname" . }}
selector:
Expand Down
6 changes: 6 additions & 0 deletions src/main/charts/bitbucket/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1610,3 +1610,9 @@ opensearch:
# -- Secret with pre-defined internal_users.yml. When undefined, Bitbucket will use initial admin user credentials
# to create indexes in OpenSearch. See: https://atlassian.github.io/data-center-helm-charts/examples/bitbucket/BITBUCKET_OPENSEARCH/
internalUsersSecret: # opensearch-internal-users

# -- StatefulSet update strategy. When unset defaults to Rolling update. See: https://kubernetes.io/docs/tutorials/stateful-application/basic-stateful-set/#updating-statefulsets
#
statefulSet:
updateStrategy: {}
# type: OnDelete
1 change: 1 addition & 0 deletions src/main/charts/confluence/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ Kubernetes: `>=1.21.x-0`
| serviceAccount.name | string | `nil` | The name of the ServiceAccount to be used by the pods. If not specified, but the "serviceAccount.create" flag is set to 'true', then the ServiceAccount name will be auto-generated, otherwise the 'default' ServiceAccount will be used. https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#use-the-default-service-account-to-access-the-api-server |
| serviceAccount.role.create | bool | `true` | Create a role for Hazelcast client with privileges to get and list pods and endpoints in the namespace. Set to false if you need to create a Role and RoleBinding manually |
| serviceAccount.roleBinding | object | `{"create":true}` | Grant permissions defined in Role (list and get pods and endpoints) to a service account. |
| statefulSet | object | `{"updateStrategy":{}}` | StatefulSet update strategy. When unset defaults to Rolling update. See: https://kubernetes.io/docs/tutorials/stateful-application/basic-stateful-set/#updating-statefulsets |
| synchrony.additionalCertificates | object | `{"customCmd":null,"secretName":null}` | Certificates to be added to Java truststore. Provide reference to a secret that contains the certificates |
| synchrony.additionalJvmArgs | list | `[]` | Specifies a list of additional arguments that can be passed to the Synchrony JVM, e.g. system properties. |
| synchrony.additionalLibraries | list | `[]` | Specifies a list of additional Java libraries that should be added to the Synchrony container. Each item in the list should specify the name of the volume that contains the library, as well as the name of the library file within that volume's root directory. Optionally, a subDirectory field can be included to specify which directory in the volume contains the library file. Additional details: https://atlassian.github.io/data-center-helm-charts/examples/external_libraries/EXTERNAL_LIBS/ |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ metadata:
labels:
{{- include "synchrony.labels" . | nindent 4 }}
spec:
{{- if .Values.statefulSet.updateStrategy }}
{{- with .Values.statefulSet.updateStrategy }}
updateStrategy:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}
{{ if .Values.ordinals.enabled }}
ordinals:
start: {{ .Values.ordinals.start }}
Expand Down
6 changes: 6 additions & 0 deletions src/main/charts/confluence/templates/statefulset.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ metadata:
labels:
{{- include "common.labels.commonLabels" . | nindent 4 }}
spec:
{{- if .Values.statefulSet.updateStrategy }}
{{- with .Values.statefulSet.updateStrategy }}
updateStrategy:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}
{{ if .Values.ordinals.enabled }}
ordinals:
start: {{ .Values.ordinals.start }}
Expand Down
5 changes: 5 additions & 0 deletions src/main/charts/confluence/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1616,3 +1616,8 @@ opensearch:
#
name: opensearch-initial-password

# -- StatefulSet update strategy. When unset defaults to Rolling update. See: https://kubernetes.io/docs/tutorials/stateful-application/basic-stateful-set/#updating-statefulsets
#
statefulSet:
updateStrategy: {}
# type: OnDelete
1 change: 1 addition & 0 deletions src/main/charts/crowd/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ Kubernetes: `>=1.21.x-0`
| serviceAccount.create | bool | `true` | Set to 'true' if a ServiceAccount should be created, or 'false' if it already exists. |
| serviceAccount.imagePullSecrets | list | `[]` | For Docker images hosted in private registries, define the list of image pull secrets that should be utilized by the created ServiceAccount https://kubernetes.io/docs/concepts/containers/images/#specifying-imagepullsecrets-on-a-pod |
| serviceAccount.name | string | `nil` | The name of the ServiceAccount to be used by the pods. If not specified, but the "serviceAccount.create" flag is set to 'true', then the ServiceAccount name will be auto-generated, otherwise the 'default' ServiceAccount will be used. https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#use-the-default-service-account-to-access-the-api-server |
| statefulSet | object | `{"updateStrategy":{}}` | StatefulSet update strategy. When unset defaults to Rolling update. See: https://kubernetes.io/docs/tutorials/stateful-application/basic-stateful-set/#updating-statefulsets |
| terminationGracePeriodSeconds | int | `30` | Kubernetes default, but can be overridden here. |
| testPods | object | `{"affinity":{},"annotations":{},"image":{"permissionsTestContainer":"debian:stable-slim","statusTestContainer":"alpine:latest"},"labels":{},"nodeSelector":{},"resources":{},"schedulerName":null,"tolerations":[]}` | Metadata and pod spec for pods started in Helm tests |
| tolerations | list | `[]` | Standard K8s tolerations that will be applied to all Crowd pods |
Expand Down
6 changes: 6 additions & 0 deletions src/main/charts/crowd/templates/statefulset.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ metadata:
labels:
{{- include "common.labels.commonLabels" . | nindent 4 }}
spec:
{{- if .Values.statefulSet.updateStrategy }}
{{- with .Values.statefulSet.updateStrategy }}
updateStrategy:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}
{{ if .Values.ordinals.enabled }}
ordinals:
start: {{ .Values.ordinals.start }}
Expand Down
6 changes: 6 additions & 0 deletions src/main/charts/crowd/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1060,3 +1060,9 @@ openshift:
# configuration files as ConfigMaps.
#
runWithRestrictedSCC: false

# -- StatefulSet update strategy. When unset defaults to Rolling update. See: https://kubernetes.io/docs/tutorials/stateful-application/basic-stateful-set/#updating-statefulsets
#
statefulSet:
updateStrategy: {}
# type: OnDelete
1 change: 1 addition & 0 deletions src/main/charts/jira/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ Kubernetes: `>=1.21.x-0`
| serviceAccount.eksIrsa.roleArn | string | `nil` | |
| serviceAccount.imagePullSecrets | list | `[]` | For Docker images hosted in private registries, define the list of image pull secrets that should be utilized by the created ServiceAccount https://kubernetes.io/docs/concepts/containers/images/#specifying-imagepullsecrets-on-a-pod |
| serviceAccount.name | string | `nil` | The name of the ServiceAccount to be used by the pods. If not specified, but the "serviceAccount.create" flag is set to 'true', then the ServiceAccount name will be auto-generated, otherwise the 'default' ServiceAccount will be used. https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#use-the-default-service-account-to-access-the-api-server |
| statefulSet | object | `{"updateStrategy":{}}` | StatefulSet update strategy. When unset defaults to Rolling update. See: https://kubernetes.io/docs/tutorials/stateful-application/basic-stateful-set/#updating-statefulsets |
| testPods | object | `{"affinity":{},"annotations":{},"image":{"permissionsTestContainer":"debian:stable-slim","statusTestContainer":"alpine:latest"},"labels":{},"nodeSelector":{},"resources":{},"schedulerName":null,"tolerations":[]}` | Metadata and pod spec for pods started in Helm tests |
| tolerations | list | `[]` | Standard K8s tolerations that will be applied to all Jira pods |
| volumes.additional | list | `[]` | Defines additional volumes that should be applied to all Jira pods. Note that this will not create any corresponding volume mounts; those needs to be defined in jira.additionalVolumeMounts |
Expand Down
6 changes: 6 additions & 0 deletions src/main/charts/jira/templates/statefulset.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ metadata:
labels:
{{- include "common.labels.commonLabels" . | nindent 4 }}
spec:
{{- if .Values.statefulSet.updateStrategy }}
{{- with .Values.statefulSet.updateStrategy }}
updateStrategy:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}
{{ if .Values.ordinals.enabled }}
ordinals:
start: {{ .Values.ordinals.start }}
Expand Down
6 changes: 6 additions & 0 deletions src/main/charts/jira/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1208,3 +1208,9 @@ openshift:
# configuration files as ConfigMaps.
#
runWithRestrictedSCC: false

# -- StatefulSet update strategy. When unset defaults to Rolling update. See: https://kubernetes.io/docs/tutorials/stateful-application/basic-stateful-set/#updating-statefulsets
#
statefulSet:
updateStrategy: {}
# type: OnDelete
91 changes: 91 additions & 0 deletions src/test/java/test/StatefulSetUpdateTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package test;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.TestInfo;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EnumSource;
import test.helm.Helm;
import com.fasterxml.jackson.databind.JsonNode;
import test.model.Product;
import test.model.StatefulSet;

import java.util.Map;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static test.jackson.JsonNodeAssert.assertThat;

public class StatefulSetUpdateTest {

private Helm helm;

@BeforeEach
void initHelm(TestInfo testInfo) {
helm = new Helm(testInfo);
}

@ParameterizedTest
@EnumSource(value = Product.class, names = {"bamboo_agent"}, mode = EnumSource.Mode.EXCLUDE)
void sts_on_delete_update(Product product) throws Exception {
final var resources = helm.captureKubeResourcesFromHelmChart(product, Map.of(
"statefulSet.updateStrategy.type", "OnDelete"
));
StatefulSet sts = resources.getStatefulSet(product.getHelmReleaseName());
JsonNode updateStrategy = sts.getSpec().path("updateStrategy").path("type");
assertEquals("OnDelete", updateStrategy.asText());
}

@ParameterizedTest
@EnumSource(value = Product.class, names = {"bamboo_agent"}, mode = EnumSource.Mode.EXCLUDE)
void sts_on_not_set(Product product) throws Exception {
final var resources = helm.captureKubeResourcesFromHelmChart(product, Map.of());
StatefulSet sts = resources.getStatefulSet(product.getHelmReleaseName());
JsonNode updateStrategy = sts.getSpec().path("updateStrategy").path("type");
assertThat(updateStrategy).isEmpty();
}

@ParameterizedTest
@EnumSource(value = Product.class, names = {"confluence"}, mode = EnumSource.Mode.INCLUDE)
void sts_on_delete_update_synchrony(Product product) throws Exception {
final var resources = helm.captureKubeResourcesFromHelmChart(product, Map.of(
"statefulSet.updateStrategy.type", "OnDelete",
"synchrony.enabled", "true"
));
StatefulSet sts = resources.getStatefulSet(product.getHelmReleaseName() + "-synchrony");
JsonNode updateStrategy = sts.getSpec().path("updateStrategy").path("type");
assertEquals("OnDelete", updateStrategy.asText());
}

@ParameterizedTest
@EnumSource(value = Product.class, names = {"confluence"}, mode = EnumSource.Mode.INCLUDE)
void sts_on_not_set_synchrony(Product product) throws Exception {
final var resources = helm.captureKubeResourcesFromHelmChart(product, Map.of(
"synchrony.enabled", "true"
));
StatefulSet sts = resources.getStatefulSet(product.getHelmReleaseName() + "-synchrony");
JsonNode updateStrategy = sts.getSpec().path("updateStrategy").path("type");
assertThat(updateStrategy).isEmpty();
}

@ParameterizedTest
@EnumSource(value = Product.class, names = {"bitbucket"}, mode = EnumSource.Mode.INCLUDE)
void sts_on_delete_update_mesh(Product product) throws Exception {
final var resources = helm.captureKubeResourcesFromHelmChart(product, Map.of(
"statefulSet.updateStrategy.type", "OnDelete",
"bitbucket.mesh.enabled", "true"
));
StatefulSet sts = resources.getStatefulSet(product.getHelmReleaseName() + "-mesh");
JsonNode updateStrategy = sts.getSpec().path("updateStrategy").path("type");
assertEquals("OnDelete", updateStrategy.asText());
}

@ParameterizedTest
@EnumSource(value = Product.class, names = {"bitbucket"}, mode = EnumSource.Mode.INCLUDE)
void sts_on_not_set_mesh(Product product) throws Exception {
final var resources = helm.captureKubeResourcesFromHelmChart(product, Map.of(
"bitbucket.mesh.enabled", "true"
));
StatefulSet sts = resources.getStatefulSet(product.getHelmReleaseName() + "-mesh");
JsonNode updateStrategy = sts.getSpec().path("updateStrategy").path("type");
assertThat(updateStrategy).isEmpty();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ spec:
template:
metadata:
annotations:
checksum/config-jvm: 6b6be5f51edc885f5b5ea92a5b42dc9a150011dc6faf6d1337c142c367369eb0
labels:
app.kubernetes.io/name: bamboo-agent
app.kubernetes.io/instance: unittest-bamboo-agent
Expand Down
3 changes: 3 additions & 0 deletions src/test/resources/expected_helm_output/bamboo/output.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,8 @@ data:
create: true
imagePullSecrets: []
name: null
statefulSet:
updateStrategy: {}
testPods:
affinity: {}
annotations: {}
Expand Down Expand Up @@ -438,6 +440,7 @@ spec:
template:
metadata:
annotations:
checksum/config-jvm: e742d2253278aa23591596b959247bb63f0b8c32a3bb9a411cd0f5d2946fe5ab
labels:
app.kubernetes.io/name: bamboo
app.kubernetes.io/instance: unittest-bamboo
Expand Down
12 changes: 4 additions & 8 deletions src/test/resources/expected_helm_output/bitbucket/output.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,8 @@ data:
create: true
roleBinding:
create: true
statefulSet:
updateStrategy: {}
testPods:
affinity: {}
annotations: {}
Expand Down Expand Up @@ -566,10 +568,6 @@ metadata:
app.kubernetes.io/managed-by: Helm
spec:
replicas: 3
updateStrategy:
type: RollingUpdate
rollingUpdate:
partition: 0
podManagementPolicy: OrderedReady
serviceName: unittest-bitbucket-mesh
selector:
Expand All @@ -579,6 +577,7 @@ spec:
template:
metadata:
annotations:
checksum/config-jvm: 181b3e6cefd7ac8f0db885749fc9ff0807fac4112d79b112676977cdac8a8970
labels:
app.kubernetes.io/name: bitbucket-mesh
app.kubernetes.io/instance: unittest-bitbucket
Expand Down Expand Up @@ -688,10 +687,6 @@ metadata:
app.kubernetes.io/managed-by: Helm
spec:
replicas: 1
updateStrategy:
type: RollingUpdate
rollingUpdate:
partition: 0
podManagementPolicy: OrderedReady
serviceName: unittest-bitbucket
selector:
Expand All @@ -701,6 +696,7 @@ spec:
template:
metadata:
annotations:
checksum/config-jvm: 5afa854bf2e6923ea0fdd790b78f94f108f6bd8352de4bd53bae0ef176b4f6ec
labels:
app.kubernetes.io/name: bitbucket
app.kubernetes.io/instance: unittest-bitbucket
Expand Down
Loading

0 comments on commit e01bfce

Please sign in to comment.