From 7ab448cc4d4103456842bedd3e321679a8847a13 Mon Sep 17 00:00:00 2001 From: "David A. Symons" Date: Thu, 23 Apr 2026 11:43:14 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=9A=80=20feat:=20add=20wait-for-db=20init?= =?UTF-8?q?=20container=20for=20bundled=20PostgreSQL?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When deploying with the bundled PostgreSQL subchart, Sequin starts before PostgreSQL accepts connections, causing crash-loop restarts on every fresh install. The startup script (start_commands.sh) runs Ecto migrations immediately with no retry logic. Adds a built-in init container that polls pg_isready until the database is reachable. Uses the PostgreSQL subchart image which provides pg_isready. Gated on postgresql.enabled so it does not run when using an external database. New value: waitForDB.enabled (default: true) Co-Authored-By: Claude Opus 4.6 (1M context) --- templates/_helpers.tpl | 8 ++++++++ templates/deployment.yaml | 24 +++++++++++++++++++++++- values.yaml | 12 ++++++++++++ 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/templates/_helpers.tpl b/templates/_helpers.tpl index 279cf7b..d49df1d 100644 --- a/templates/_helpers.tpl +++ b/templates/_helpers.tpl @@ -124,6 +124,14 @@ Return the Database Secret Name {{- end -}} {{- end -}} +{{/* +Return the image for the wait-for-db init container. +Defaults to the PostgreSQL subchart image. +*/}} +{{- define "sequin.waitForDB.image" -}} +{{- include "common.images.image" (dict "imageRoot" .Values.postgresql.image "global" .Values.global) -}} +{{- end -}} + {{/* Get the Redis® fullname */}} diff --git a/templates/deployment.yaml b/templates/deployment.yaml index a0b9da1..84b812e 100644 --- a/templates/deployment.yaml +++ b/templates/deployment.yaml @@ -55,9 +55,31 @@ spec: {{- if .Values.podSecurityContext.enabled }} securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.podSecurityContext "context" $) | nindent 8 }} {{- end }} - {{- if .Values.initContainers }} + {{- if or (and .Values.waitForDB.enabled .Values.postgresql.enabled) .Values.initContainers }} initContainers: + {{- if and .Values.waitForDB.enabled .Values.postgresql.enabled }} + - name: wait-for-db + image: {{ include "sequin.waitForDB.image" . }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + {{- if .Values.containerSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.containerSecurityContext "context" $) | nindent 12 }} + {{- end }} + command: + - /bin/bash + - -ec + - | + host={{ include "sequin.database.host" . | quote }} + port={{ include "sequin.database.port" . | quote }} + user={{ include "sequin.database.username" . | quote }} + echo "Waiting for PostgreSQL at ${host}:${port}..." + until pg_isready -h "$host" -p "$port" -U "$user" -q; do + sleep 2 + done + echo "PostgreSQL is accepting connections" + {{- end }} + {{- if .Values.initContainers }} {{- include "common.tplvalues.render" (dict "value" .Values.initContainers "context" $) | nindent 8 }} + {{- end }} {{- end }} containers: - name: sequin diff --git a/values.yaml b/values.yaml index 56abaef..a30c0a9 100644 --- a/values.yaml +++ b/values.yaml @@ -378,6 +378,18 @@ sidecars: [] ## command: ['sh', '-c', 'echo "hello world"'] ## initContainers: [] +## @section Database readiness parameters +## + +## Wait for database init container +## Adds an init container that waits for PostgreSQL to accept connections +## before starting Sequin. Prevents crash-loops on fresh installs when +## deploying with the bundled PostgreSQL subchart. +## Only takes effect when postgresql.enabled=true. +## @param waitForDB.enabled Enable the wait-for-db init container +## +waitForDB: + enabled: true ## @section Traffic Exposure Parameters ##