From d3138836720a65e6f83376e9dc38bba2b8fae632 Mon Sep 17 00:00:00 2001 From: antruigon <99184149+antruigon@users.noreply.github.com> Date: Tue, 18 Aug 2026 20:07:18 +0200 Subject: [PATCH] [chart/v1-2x-test] Add terminationGracePeriodSeconds support for PgBouncer in Helm chart (#71237) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The chart ships a default PgBouncer preStop hook that drains client connections for up to 120 seconds, but the Deployment never sets terminationGracePeriodSeconds, so the Kubernetes default of 30s SIGKILLs the pod mid-drain on a node drain or eviction and cuts in-flight client connections. Every other long-running component in the chart already exposes this value; PgBouncer was the only one missing it, despite being the component that holds the database connections of all the others. The default of 120 matches the drain window of the default preStop hook. PgBouncer exits as soon as the last client connection is released, so the value is an upper bound rather than a fixed wait. (cherry picked from commit 0815a27eae7a8c9b6f336255437d8ed344cdaf3a) Co-authored-by: antruigon <99184149+antruigon@users.noreply.github.com> Co-authored-by: Przemysław Mirowski <17602603+Miretpl@users.noreply.github.com> --- .../templates/pgbouncer/pgbouncer-deployment.yaml | 1 + chart/values.schema.json | 7 +++++++ chart/values.yaml | 6 ++++++ .../tests/helm_tests/other/test_pgbouncer.py | 14 ++++++++++++++ 4 files changed, 28 insertions(+) diff --git a/chart/templates/pgbouncer/pgbouncer-deployment.yaml b/chart/templates/pgbouncer/pgbouncer-deployment.yaml index 45c4a7148778c..96f523a6d9ebf 100644 --- a/chart/templates/pgbouncer/pgbouncer-deployment.yaml +++ b/chart/templates/pgbouncer/pgbouncer-deployment.yaml @@ -87,6 +87,7 @@ spec: {{- end }} tolerations: {{- toYaml $tolerations | nindent 8 }} topologySpreadConstraints: {{- toYaml $topologySpreadConstraints | nindent 8 }} + terminationGracePeriodSeconds: {{ .Values.pgbouncer.terminationGracePeriodSeconds }} serviceAccountName: {{ include "pgbouncer.serviceAccountName" . }} {{- include "serviceLinks" . | nindent 6 }} securityContext: {{ $securityContext | nindent 8 }} diff --git a/chart/values.schema.json b/chart/values.schema.json index 092e5abc2d1ce..f04ef036c5818 100644 --- a/chart/values.schema.json +++ b/chart/values.schema.json @@ -10061,6 +10061,13 @@ } ] }, + "terminationGracePeriodSeconds": { + "description": "Grace period for PgBouncer to finish after SIGTERM is sent from Kubernetes.", + "type": "integer", + "default": 120, + "minimum": 0, + "x-docsSection": "Kubernetes" + }, "securityContexts": { "description": "Security context definition for the PgBouncer.", "type": "object", diff --git a/chart/values.yaml b/chart/values.yaml index 274a8d79b4a86..5fcac27903e09 100644 --- a/chart/values.yaml +++ b/chart/values.yaml @@ -3916,6 +3916,12 @@ pgbouncer: # Allow existing queries clients to complete within 120 seconds command: ["/bin/sh", "-c", "killall -INT pgbouncer && sleep 120"] + # Grace period for PgBouncer to finish after SIGTERM is sent from Kubernetes. + # Matches the default preStop hook above, which needs up to 120 seconds to + # drain client connections; with a shorter grace period the pod is killed + # mid-drain and in-flight connections are cut. + terminationGracePeriodSeconds: 120 + metricsExporterSidecar: resources: {} # limits: diff --git a/helm-tests/tests/helm_tests/other/test_pgbouncer.py b/helm-tests/tests/helm_tests/other/test_pgbouncer.py index 27e0f60378aac..8bde2b419e8b7 100644 --- a/helm-tests/tests/helm_tests/other/test_pgbouncer.py +++ b/helm-tests/tests/helm_tests/other/test_pgbouncer.py @@ -431,6 +431,20 @@ def test_should_add_component_specific_labels(self): assert "labels" in jmespath.search("spec.template.metadata", docs[0]) assert jmespath.search("spec.template.metadata.labels", docs[0])["test_label"] == "test_label_value" + @pytest.mark.parametrize( + ("pgbouncer_values", "expected"), + [ + ({"enabled": True}, 120), + ({"enabled": True, "terminationGracePeriodSeconds": 30}, 30), + ], + ) + def test_pgbouncer_termination_grace_period_seconds(self, pgbouncer_values, expected): + docs = render_chart( + values={"pgbouncer": pgbouncer_values}, + show_only=["templates/pgbouncer/pgbouncer-deployment.yaml"], + ) + assert expected == jmespath.search("spec.template.spec.terminationGracePeriodSeconds", docs[0]) + class TestPgbouncerConfig: """Tests PgBouncer config."""