diff --git a/src/main/charts/bamboo/README.md b/src/main/charts/bamboo/README.md
index 72f574846..b4ed9bb9f 100644
--- a/src/main/charts/bamboo/README.md
+++ b/src/main/charts/bamboo/README.md
@@ -142,6 +142,7 @@ Kubernetes: `>=1.21.x-0`
| monitoring.serviceMonitor.scrapeIntervalSeconds | int | `30` | Scrape interval for the JMX service. |
| nodeSelector | object | `{}` | Standard K8s node-selectors that will be applied to all Bamboo pods |
| podAnnotations | object | `{}` | Custom annotations that will be applied to all Bamboo pods |
+| podDisruptionBudget | object | `{"annotations":{},"enabled":false,"labels":{},"maxUnavailable":null,"minAvailable":null}` | PodDisruptionBudget: https://kubernetes.io/docs/tasks/run-application/configure-pdb/ You can specify only one of maxUnavailable and minAvailable in a single PodDisruptionBudget. When both minAvailable and maxUnavailable are set, maxUnavailable takes precedence. |
| podLabels | object | `{}` | Custom labels that will be applied to all Bamboo pods |
| priorityClassName | string | `nil` | Priority class for the application pods. The PriorityClass with this name needs to be available in the cluster. For details see https://kubernetes.io/docs/concepts/scheduling-eviction/pod-priority-preemption/#priorityclass |
| replicaCount | int | `1` | The initial number of Bamboo pods that should be started at deployment time. Note that Bamboo requires manual configuration via the browser post deployment after the first pod is deployed. At present Bamboo Data Center utilizes an `active-passive` clustering model. This architecture is not ideal where K8s deployments are concerned. As such a Bamboo server cluster comprising only `1` pod is the recommended topology for now. For more detail see: https://atlassian.github.io/data-center-helm-charts/troubleshooting/LIMITATIONS#cluster-size |
diff --git a/src/main/charts/bamboo/templates/pdb.yaml b/src/main/charts/bamboo/templates/pdb.yaml
new file mode 100644
index 000000000..bac9d7fdc
--- /dev/null
+++ b/src/main/charts/bamboo/templates/pdb.yaml
@@ -0,0 +1,26 @@
+{{- if .Values.podDisruptionBudget.enabled }}
+apiVersion: policy/v1
+kind: PodDisruptionBudget
+metadata:
+ name: {{ include "common.names.fullname" . }}
+ labels:
+ {{- include "common.labels.commonLabels" . | nindent 4 }}
+ {{- with .Values.podDisruptionBudget.labels }}
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+ {{- with .Values.podDisruptionBudget.annotations }}
+ annotations:
+ {{- range $key, $value := . }}
+ {{ $key }}: {{ $value | quote }}
+ {{- end }}
+ {{- end }}
+spec:
+ {{- with .Values.podDisruptionBudget.maxUnavailable }}
+ maxUnavailable: {{ . }}
+ {{- else }}
+ minAvailable: {{ .Values.podDisruptionBudget.minAvailable | default 0 }}
+ {{- end }}
+ selector:
+ matchLabels:
+ {{- include "common.labels.selectorLabels" . | nindent 6 }}
+{{- end }}
diff --git a/src/main/charts/bamboo/values.yaml b/src/main/charts/bamboo/values.yaml
index aad24d7d6..538fb2cbf 100644
--- a/src/main/charts/bamboo/values.yaml
+++ b/src/main/charts/bamboo/values.yaml
@@ -1045,6 +1045,16 @@ additionalFiles: []
# key: keystore.jks
# mountPath: /var/ssl
+# -- PodDisruptionBudget: https://kubernetes.io/docs/tasks/run-application/configure-pdb/
+# You can specify only one of maxUnavailable and minAvailable in a single PodDisruptionBudget. When both minAvailable and maxUnavailable are set, maxUnavailable takes precedence.
+#
+podDisruptionBudget:
+ enabled: false
+ labels: {}
+ annotations: {}
+ minAvailable:
+ maxUnavailable:
+
# -- Create additional ConfigMaps with given names, keys and content. Ther Helm release name will be used as a prefix
# for a ConfigMap name, fileName is used as subPath
#
@@ -1060,4 +1070,4 @@ additionalConfigMaps: []
# mountPath: /opt/atlassian/jira/atlassian-jira/WEB-INF/classes
# content: |
#
-#
\ No newline at end of file
+#
diff --git a/src/main/charts/bitbucket/README.md b/src/main/charts/bitbucket/README.md
index 8160e3efa..fe263e90b 100644
--- a/src/main/charts/bitbucket/README.md
+++ b/src/main/charts/bitbucket/README.md
@@ -174,6 +174,7 @@ Kubernetes: `>=1.21.x-0`
| monitoring.serviceMonitor.scrapeIntervalSeconds | int | `30` | Scrape interval for the JMX service. |
| nodeSelector | object | `{}` | Standard K8s node-selectors that will be applied to all Bitbucket pods |
| podAnnotations | object | `{}` | Custom annotations that will be applied to all Bitbucket pods |
+| podDisruptionBudget | object | `{"annotations":{},"enabled":false,"labels":{},"maxUnavailable":null,"minAvailable":null}` | PodDisruptionBudget: https://kubernetes.io/docs/tasks/run-application/configure-pdb/ You can specify only one of maxUnavailable and minAvailable in a single PodDisruptionBudget. When both minAvailable and maxUnavailable are set, maxUnavailable takes precedence. |
| podLabels | object | `{}` | Custom labels that will be applied to all Bitbucket pods |
| priorityClassName | string | `nil` | Priority class for the application pods. The PriorityClass with this name needs to be available in the cluster. For details see https://kubernetes.io/docs/concepts/scheduling-eviction/pod-priority-preemption/#priorityclass |
| replicaCount | int | `1` | The initial number of Bitbucket pods that should be started at deployment time. Note that if Bitbucket is fully configured (see above) during initial deployment a 'replicaCount' greater than 1 can be supplied. |
diff --git a/src/main/charts/bitbucket/templates/pdb.yaml b/src/main/charts/bitbucket/templates/pdb.yaml
new file mode 100644
index 000000000..bac9d7fdc
--- /dev/null
+++ b/src/main/charts/bitbucket/templates/pdb.yaml
@@ -0,0 +1,26 @@
+{{- if .Values.podDisruptionBudget.enabled }}
+apiVersion: policy/v1
+kind: PodDisruptionBudget
+metadata:
+ name: {{ include "common.names.fullname" . }}
+ labels:
+ {{- include "common.labels.commonLabels" . | nindent 4 }}
+ {{- with .Values.podDisruptionBudget.labels }}
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+ {{- with .Values.podDisruptionBudget.annotations }}
+ annotations:
+ {{- range $key, $value := . }}
+ {{ $key }}: {{ $value | quote }}
+ {{- end }}
+ {{- end }}
+spec:
+ {{- with .Values.podDisruptionBudget.maxUnavailable }}
+ maxUnavailable: {{ . }}
+ {{- else }}
+ minAvailable: {{ .Values.podDisruptionBudget.minAvailable | default 0 }}
+ {{- end }}
+ selector:
+ matchLabels:
+ {{- include "common.labels.selectorLabels" . | nindent 6 }}
+{{- end }}
diff --git a/src/main/charts/bitbucket/values.yaml b/src/main/charts/bitbucket/values.yaml
index ffce3f66c..d26ffa29c 100644
--- a/src/main/charts/bitbucket/values.yaml
+++ b/src/main/charts/bitbucket/values.yaml
@@ -1334,6 +1334,16 @@ additionalHosts: []
# - "foo.local"
# - "bar.local"
+# -- PodDisruptionBudget: https://kubernetes.io/docs/tasks/run-application/configure-pdb/
+# You can specify only one of maxUnavailable and minAvailable in a single PodDisruptionBudget. When both minAvailable and maxUnavailable are set, maxUnavailable takes precedence.
+#
+podDisruptionBudget:
+ enabled: false
+ labels: {}
+ annotations: {}
+ minAvailable:
+ maxUnavailable:
+
# -- Create additional ConfigMaps with given names, keys and content. Ther Helm release name will be used as a prefix
# for a ConfigMap name, fileName is used as subPath
#
diff --git a/src/main/charts/confluence/README.md b/src/main/charts/confluence/README.md
index e97966fed..dfd640934 100644
--- a/src/main/charts/confluence/README.md
+++ b/src/main/charts/confluence/README.md
@@ -137,6 +137,7 @@ Kubernetes: `>=1.21.x-0`
| monitoring.serviceMonitor.scrapeIntervalSeconds | int | `30` | Scrape interval for the JMX service. |
| nodeSelector | object | `{}` | Standard K8s node-selectors that will be applied to all Confluence pods |
| podAnnotations | object | `{}` | Custom annotations that will be applied to all Confluence pods |
+| podDisruptionBudget | object | `{"annotations":{},"enabled":false,"labels":{},"maxUnavailable":null,"minAvailable":null}` | PodDisruptionBudget: https://kubernetes.io/docs/tasks/run-application/configure-pdb/ You can specify only one of maxUnavailable and minAvailable in a single PodDisruptionBudget. When both minAvailable and maxUnavailable are set, maxUnavailable takes precedence. |
| podLabels | object | `{}` | Custom labels that will be applied to all Confluence pods |
| priorityClassName | string | `nil` | Priority class for the application pods. The PriorityClass with this name needs to be available in the cluster. For details see https://kubernetes.io/docs/concepts/scheduling-eviction/pod-priority-preemption/#priorityclass |
| replicaCount | int | `1` | The initial number of Confluence pods that should be started at deployment time. Note that Confluence requires manual configuration via the browser post deployment after the first pod is deployed. This configuration must be completed before scaling up additional pods. As such this value should always be kept as 1, but can be altered once manual configuration is complete. |
diff --git a/src/main/charts/confluence/templates/pdb.yaml b/src/main/charts/confluence/templates/pdb.yaml
new file mode 100644
index 000000000..bac9d7fdc
--- /dev/null
+++ b/src/main/charts/confluence/templates/pdb.yaml
@@ -0,0 +1,26 @@
+{{- if .Values.podDisruptionBudget.enabled }}
+apiVersion: policy/v1
+kind: PodDisruptionBudget
+metadata:
+ name: {{ include "common.names.fullname" . }}
+ labels:
+ {{- include "common.labels.commonLabels" . | nindent 4 }}
+ {{- with .Values.podDisruptionBudget.labels }}
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+ {{- with .Values.podDisruptionBudget.annotations }}
+ annotations:
+ {{- range $key, $value := . }}
+ {{ $key }}: {{ $value | quote }}
+ {{- end }}
+ {{- end }}
+spec:
+ {{- with .Values.podDisruptionBudget.maxUnavailable }}
+ maxUnavailable: {{ . }}
+ {{- else }}
+ minAvailable: {{ .Values.podDisruptionBudget.minAvailable | default 0 }}
+ {{- end }}
+ selector:
+ matchLabels:
+ {{- include "common.labels.selectorLabels" . | nindent 6 }}
+{{- end }}
diff --git a/src/main/charts/confluence/values.yaml b/src/main/charts/confluence/values.yaml
index 770d4d89c..0f2da4c0c 100644
--- a/src/main/charts/confluence/values.yaml
+++ b/src/main/charts/confluence/values.yaml
@@ -1346,6 +1346,16 @@ additionalHosts: []
# - "foo.local"
# - "bar.local"
+# -- PodDisruptionBudget: https://kubernetes.io/docs/tasks/run-application/configure-pdb/
+# You can specify only one of maxUnavailable and minAvailable in a single PodDisruptionBudget. When both minAvailable and maxUnavailable are set, maxUnavailable takes precedence.
+#
+podDisruptionBudget:
+ enabled: false
+ labels: {}
+ annotations: {}
+ minAvailable:
+ maxUnavailable:
+
# -- Create additional ConfigMaps with given names, keys and content. Ther Helm release name will be used as a prefix
# for a ConfigMap name, fileName is used as subPath
#
@@ -1362,3 +1372,4 @@ additionalConfigMaps: []
# content: |
#
#
+
diff --git a/src/main/charts/crowd/README.md b/src/main/charts/crowd/README.md
index 0d21f2fbd..fca5d9e41 100644
--- a/src/main/charts/crowd/README.md
+++ b/src/main/charts/crowd/README.md
@@ -116,6 +116,7 @@ Kubernetes: `>=1.21.x-0`
| monitoring.serviceMonitor.scrapeIntervalSeconds | int | `30` | Scrape interval for the JMX service. |
| nodeSelector | object | `{}` | Standard K8s node-selectors that will be applied to all Crowd pods |
| podAnnotations | object | `{}` | Custom annotations that will be applied to all Crowd pods |
+| podDisruptionBudget | object | `{"annotations":{},"enabled":false,"labels":{},"maxUnavailable":null,"minAvailable":null}` | PodDisruptionBudget: https://kubernetes.io/docs/tasks/run-application/configure-pdb/ You can specify only one of maxUnavailable and minAvailable in a single PodDisruptionBudget. When both minAvailable and maxUnavailable are set, maxUnavailable takes precedence. |
| podLabels | object | `{}` | Custom labels that will be applied to all Crowd pods |
| priorityClassName | string | `nil` | Priority class for the application pods. The PriorityClass with this name needs to be available in the cluster. For details see https://kubernetes.io/docs/concepts/scheduling-eviction/pod-priority-preemption/#priorityclass |
| replicaCount | int | `1` | The initial number of Crowd pods that should be started at deployment time. Note that Crowd requires manual configuration via the browser post deployment after the first pod is deployed. This configuration must be completed before scaling up additional pods. As such this value should always be kept as 1, but can be altered once manual configuration is complete. |
diff --git a/src/main/charts/crowd/templates/pdb.yaml b/src/main/charts/crowd/templates/pdb.yaml
new file mode 100644
index 000000000..bac9d7fdc
--- /dev/null
+++ b/src/main/charts/crowd/templates/pdb.yaml
@@ -0,0 +1,26 @@
+{{- if .Values.podDisruptionBudget.enabled }}
+apiVersion: policy/v1
+kind: PodDisruptionBudget
+metadata:
+ name: {{ include "common.names.fullname" . }}
+ labels:
+ {{- include "common.labels.commonLabels" . | nindent 4 }}
+ {{- with .Values.podDisruptionBudget.labels }}
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+ {{- with .Values.podDisruptionBudget.annotations }}
+ annotations:
+ {{- range $key, $value := . }}
+ {{ $key }}: {{ $value | quote }}
+ {{- end }}
+ {{- end }}
+spec:
+ {{- with .Values.podDisruptionBudget.maxUnavailable }}
+ maxUnavailable: {{ . }}
+ {{- else }}
+ minAvailable: {{ .Values.podDisruptionBudget.minAvailable | default 0 }}
+ {{- end }}
+ selector:
+ matchLabels:
+ {{- include "common.labels.selectorLabels" . | nindent 6 }}
+{{- end }}
diff --git a/src/main/charts/crowd/values.yaml b/src/main/charts/crowd/values.yaml
index f84c94101..d7effc143 100644
--- a/src/main/charts/crowd/values.yaml
+++ b/src/main/charts/crowd/values.yaml
@@ -857,8 +857,18 @@ monitoring:
#
dashboardLabels: {}
# grafana_dashboard: dc_monitoring
-
+
# -- Annotations added to Grafana dashboards ConfigMaps. See: https://github.com/kiwigrid/k8s-sidecar#usage
#
dashboardAnnotations: {}
# k8s-sidecar-target-directory: /tmp/dashboards/example-folder
+
+# -- PodDisruptionBudget: https://kubernetes.io/docs/tasks/run-application/configure-pdb/
+# You can specify only one of maxUnavailable and minAvailable in a single PodDisruptionBudget. When both minAvailable and maxUnavailable are set, maxUnavailable takes precedence.
+#
+podDisruptionBudget:
+ enabled: false
+ labels: {}
+ annotations: {}
+ minAvailable:
+ maxUnavailable:
diff --git a/src/main/charts/jira/README.md b/src/main/charts/jira/README.md
index 0e5ad7727..2bd7c43a9 100644
--- a/src/main/charts/jira/README.md
+++ b/src/main/charts/jira/README.md
@@ -133,6 +133,7 @@ Kubernetes: `>=1.21.x-0`
| monitoring.serviceMonitor.scrapeIntervalSeconds | int | `30` | Scrape interval for the JMX service. |
| nodeSelector | object | `{}` | Standard K8s node-selectors that will be applied to all Jira pods |
| podAnnotations | object | `{}` | Custom annotations that will be applied to all Jira pods |
+| podDisruptionBudget | object | `{"annotations":{},"enabled":false,"labels":{},"maxUnavailable":null,"minAvailable":null}` | PodDisruptionBudget: https://kubernetes.io/docs/tasks/run-application/configure-pdb/ You can specify only one of maxUnavailable and minAvailable in a single PodDisruptionBudget. When both minAvailable and maxUnavailable are set, maxUnavailable takes precedence. |
| podLabels | object | `{}` | Custom labels that will be applied to all Jira pods |
| priorityClassName | string | `nil` | Priority class for the application pods. The PriorityClass with this name needs to be available in the cluster. For details see https://kubernetes.io/docs/concepts/scheduling-eviction/pod-priority-preemption/#priorityclass |
| replicaCount | int | `1` | The initial number of Jira pods that should be started at deployment time. Note that Jira requires manual configuration via the browser post deployment after the first pod is deployed. This configuration must be completed before scaling up additional pods. As such this value should always be kept as 1, but can be altered once manual configuration is complete. |
diff --git a/src/main/charts/jira/templates/pdb.yaml b/src/main/charts/jira/templates/pdb.yaml
new file mode 100644
index 000000000..bac9d7fdc
--- /dev/null
+++ b/src/main/charts/jira/templates/pdb.yaml
@@ -0,0 +1,26 @@
+{{- if .Values.podDisruptionBudget.enabled }}
+apiVersion: policy/v1
+kind: PodDisruptionBudget
+metadata:
+ name: {{ include "common.names.fullname" . }}
+ labels:
+ {{- include "common.labels.commonLabels" . | nindent 4 }}
+ {{- with .Values.podDisruptionBudget.labels }}
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+ {{- with .Values.podDisruptionBudget.annotations }}
+ annotations:
+ {{- range $key, $value := . }}
+ {{ $key }}: {{ $value | quote }}
+ {{- end }}
+ {{- end }}
+spec:
+ {{- with .Values.podDisruptionBudget.maxUnavailable }}
+ maxUnavailable: {{ . }}
+ {{- else }}
+ minAvailable: {{ .Values.podDisruptionBudget.minAvailable | default 0 }}
+ {{- end }}
+ selector:
+ matchLabels:
+ {{- include "common.labels.selectorLabels" . | nindent 6 }}
+{{- end }}
diff --git a/src/main/charts/jira/values.yaml b/src/main/charts/jira/values.yaml
index c823dd0fb..d2e604669 100644
--- a/src/main/charts/jira/values.yaml
+++ b/src/main/charts/jira/values.yaml
@@ -1019,6 +1019,16 @@ additionalHosts: []
# - "foo.local"
# - "bar.local"
+# -- PodDisruptionBudget: https://kubernetes.io/docs/tasks/run-application/configure-pdb/
+# You can specify only one of maxUnavailable and minAvailable in a single PodDisruptionBudget. When both minAvailable and maxUnavailable are set, maxUnavailable takes precedence.
+#
+podDisruptionBudget:
+ enabled: false
+ labels: {}
+ annotations: {}
+ minAvailable:
+ maxUnavailable:
+
# -- Create additional ConfigMaps with given names, keys and content. Ther Helm release name will be used as a prefix
# for a ConfigMap name, fileName is used as subPath
#
diff --git a/src/test/java/test/PodDisruptionBudgetTest.java b/src/test/java/test/PodDisruptionBudgetTest.java
new file mode 100644
index 000000000..e2d88741e
--- /dev/null
+++ b/src/test/java/test/PodDisruptionBudgetTest.java
@@ -0,0 +1,75 @@
+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 test.model.*;
+
+import java.util.Map;
+
+import static test.jackson.JsonNodeAssert.assertThat;
+
+public class PodDisruptionBudgetTest {
+
+ 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 pod_disruption_budget_enabled_min_available(Product product) throws Exception {
+ final var resources = helm.captureKubeResourcesFromHelmChart(product, Map.of(
+ "podDisruptionBudget.enabled", "true",
+ "podDisruptionBudget.minAvailable", "1"
+ ));
+
+ KubeResource pdb = resources.get(Kind.PodDisruptionBudget, product.getHelmReleaseName());
+ assertThat(pdb.getSpec().get("minAvailable")).hasValueEqualTo(1);
+ }
+
+ @ParameterizedTest
+ @EnumSource(value = Product.class, names = {"bamboo_agent"}, mode = EnumSource.Mode.EXCLUDE)
+ void pod_disruption_budget_min_available_max_unavailable(Product product) throws Exception {
+ final var resources = helm.captureKubeResourcesFromHelmChart(product, Map.of(
+ "podDisruptionBudget.enabled", "true",
+ "podDisruptionBudget.minAvailable", "1",
+ "podDisruptionBudget.maxUnavailable", "2"
+ ));
+
+ // assert that when both mixAvailable and maxUnavailable are defined, only maxUnavailable is set in pdb
+ KubeResource pdb = resources.get(Kind.PodDisruptionBudget, product.getHelmReleaseName());
+ assertThat(pdb.getSpec().get("maxUnavailable")).hasValueEqualTo(2);
+ assertThat(pdb.getSpec().path("minAvailable")).isEmpty();
+ }
+
+ @ParameterizedTest
+ @EnumSource(value = Product.class, names = {"bamboo_agent"}, mode = EnumSource.Mode.EXCLUDE)
+ void pod_disruption_budget_annotations(Product product) throws Exception {
+ final var resources = helm.captureKubeResourcesFromHelmChart(product, Map.of(
+ "podDisruptionBudget.enabled", "true",
+ "podDisruptionBudget.minAvailable", "1",
+ "podDisruptionBudget.annotations.foo", "bar"
+ ));
+
+ KubeResource pdb = resources.get(Kind.PodDisruptionBudget, product.getHelmReleaseName());
+ assertThat(pdb.getAnnotations().path("foo")).hasTextEqualTo("bar");
+ }
+
+ @ParameterizedTest
+ @EnumSource(value = Product.class, names = {"bamboo_agent"}, mode = EnumSource.Mode.EXCLUDE)
+ void pod_disruption_budget_labels(Product product) throws Exception {
+ final var resources = helm.captureKubeResourcesFromHelmChart(product, Map.of(
+ "podDisruptionBudget.enabled", "true",
+ "podDisruptionBudget.minAvailable", "1",
+ "podDisruptionBudget.labels.foo", "bar"
+ ));
+
+ KubeResource pdb = resources.get(Kind.PodDisruptionBudget, product.getHelmReleaseName());
+ assertThat(pdb.getMetadata().path("labels").path("foo")).hasTextEqualTo("bar");
+ }
+}
diff --git a/src/test/java/test/model/Kind.java b/src/test/java/test/model/Kind.java
index b872864af..1adbafe91 100644
--- a/src/test/java/test/model/Kind.java
+++ b/src/test/java/test/model/Kind.java
@@ -4,5 +4,5 @@
* The different types of Kubernetes resource we use.
*/
public enum Kind {
- StatefulSet, Deployment, ServiceAccount, ConfigMap, Secret, Service, Pod, Job, ClusterRole, Role, ClusterRoleBinding, RoleBinding, PersistentVolume, PersistentVolumeClaim, Ingress, ServiceMonitor
+ StatefulSet, Deployment, ServiceAccount, ConfigMap, Secret, Service, Pod, Job, ClusterRole, Role, ClusterRoleBinding, RoleBinding, PersistentVolume, PersistentVolumeClaim, Ingress, ServiceMonitor, PodDisruptionBudget
}