JHipster Helm Chart Configuration for Pre‑Run Liquibase Migration Job
0 reputation · 21 Oct 2021, 05:11 UTC
0 reputation · 21 Oct 2021, 05:11 UTC
The goal is to guarantee that database schema updates are applied exactly once and before any new version of the application starts, while preserving the ability to run destructive change‑sets safely in a Kubernetes RollingUpdate.
Currently the generated Helm chart relies on pod‑startup Liquibase execution, which can cause overlapping schema versions when old and new replicas run concurrently, and it does not automatically add the required preConditions for column drops, leaving the decision to manually edit changelogs.
How can the chart be extended to invoke the standalone liquibase:migrate task as a pre‑upgrade hook? What mechanism ensures the migration job finishes before the Deployment creates new pods? Should the chart provide a way to inject or validate preConditions for destructive changes without requiring developers to edit each change‑set?
35275 reputation · 21 Oct 2021, 15:40 UTC
Yes: add a dedicated Kubernetes Job to the chart, annotate it as a Helm pre-upgrade hook, and upgrade with --wait. Helm executes hook resources before touching the Deployment, and with --wait it blocks until the Job completes — so no new application pod is created until the schema is current. For destructive change‑sets, the chart can inject a standard preConditions block through a templated ConfigMap/changelog, but that only covers generic guards; developers must still review genuinely destructive changes.
Add a manifest such as templates/liquibase-migrate-job.yaml:
apiVersion: batch/v1
kind: Job
metadata:
name: {{ include "myapp.fullname" . }}-liquibase
annotations:
"helm.sh/hook": pre-upgrade
"helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded
spec:
backoffLimit: 1
activeDeadlineSeconds: 600
template:
spec:
restartPolicy: Never
containers:
- name: liquibase
image: {{ .Values.image.repository }}:{{ .Values.image.tag }}
command: ["./mvnw", "liquibase:migrate"]
envFrom:
- secretRef:
name: {{ include "myapp.fullname" . }}-dbUse the same application image (it already contains the JDBC driver and changelogs) or a purpose‑built Liquibase image. Keep backoffLimit low and set activeDeadlineSeconds so a stuck migration fails visibly instead of retrying forever. The DB credentials Secret must exist before the hook runs — hooks do not wait for other chart resources.
The guarantee comes from two mechanisms together:
pre-upgrade hook resources before applying any change to the Deployment. The Deployment update simply does not start while the hook is pending.--wait (or CI equivalent): Helm watches the hook Job until it reaches Complete. Only then does the RollingUpdate proceed. If the Job fails, the upgrade fails and the old ReplicaSet keeps serving.Also disable Liquibase at pod startup (e.g. set spring.liquibase.enabled=false via an env var in the Deployment) so the migration runs exactly once, in the Job, rather than racing across replicas.
A pragmatic middle ground: expose a value like liquibase.preConditions and render a small "guard" changelog through a ConfigMap that runs first, containing checks such as columnExists for columns scheduled for removal, with onFail: MARK_RAN or HALT as appropriate. Optionally add a second hook Job running liquibase:validate gated behind --set liquibase.validate=true. Be explicit in the chart docs that templated guards cannot understand every custom change‑set — column drops still warrant human review; the chart's job is to fail fast, not to decide.
helm upgrade --dry-run --debug myapp ./chart # hook Job rendered before Deployment
helm upgrade --wait myapp ./chart
kubectl get jobs -w # migration completes first
kubectl logs job/myapp-liquibase # Liquibase outputOne caveat worth testing on staging: if the database is unreachable when the hook starts, the upgrade stalls until the deadline. A small initContainer checking DB connectivity makes that failure mode faster and clearer.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.