Upgrades
An upgrade is one command. This page is about the handful of things that make that command safe to run against an install with real data in it.Upgrade checklist
The whole procedure, in order. Each step links to the detail below.- Read the release notes for every version between yours and the target, and prepare your values file from the new version’s preset (Before you run it, step 1).
- Check the chart file is the version you expect:
helm show chart $SWARMD_CHART. - Back up both databases and the
swarmd-generated-credentialsSecret, and note the current Helm revision — it is the one you would roll back to. - Preview the upgrade with
--dry-run=server(orhelm diff). - Upgrade in a quiet window, with
--wait --timeout 15m. - Verify straight away: pods Running with zero restarts,
helm testpasses, and one real message reaches an agent (Verifying afterwards). - Do any after-upgrade steps the release notes list.
Getting the new version
We send you a newswarmd-<version>.tgz for each release, with notes covering
what changed and anything that needs care on the way to it. There is no
registry to poll and no --version flag: the file is the version.
That has a couple of practical consequences.
- Keep old tarballs.
helm rollbackrestores the previous revision from what Helm already has, so it works without the file. Reinstalling an older release from scratch does not — that needs the tarball again, and asking us for it is a slower path than keeping a copy. - Name your releases after the file.
helm -n swarmd listshows the chart version, so a cluster can always tell you what it is running; keeping the tarballs in one directory makes it just as easy in the other direction.
Read the release notes for every version between where you are and where you
are going — not just the target. Helm applies one jump; the notes are written
per version.
What survives an upgrade
The one that bricks installs
The chart generatesswarmd-generated-credentials on first install and, on
every upgrade, reads the existing Secret back so nothing rotates. That read is
a Helm lookup, and lookup only works when Helm has a live connection to
the cluster.
When it doesn’t, every credential falls through to a freshly generated random
value. Applying that render rotates the Postgres password, the Keycloak admin
password and encryption-key in a single step. The first two stop the
platform; the third is worse, because registry, relay and teams encrypt rows
at rest with that key and a rotated key makes existing rows permanently
unreadable. No backup of the database helps — you need the old key.
The chart now refuses rather than letting that happen:
helm upgrade --dry-run
helm upgrade --dry-run
Plain
--dry-run is client-side and disables lookup. Use
--dry-run=server when you want to preview an upgrade — it keeps the
cluster connection, so the Secret is read and the render matches what a
real upgrade would apply.GitOps that renders with helm template
GitOps that renders with helm template
Argo CD renders charts with Then pre-create a Secret of that name with the keys listed in
Configuration → Secrets, sourced
from your secret manager (Vault, OpenBao, External Secrets). This is the
right shape for GitOps anyway — the credentials stop being a side effect
of a render.
helm template by default and applies the
output. lookup returns nothing in that mode, and because the render
reports itself as an install the guard cannot tell it apart from a
genuine first install — so it does not fire, and the rotation happens
silently.If you deploy through a template-and-apply GitOps tool, do not let the
chart own its credentials. Turn generation off and manage the Secret
yourself:Before you run it
1
Prepare your values file
Start from the preset that ships with the version you are moving to, then
re-apply your own changes, rather than reusing your old file as it is: new
versions add settings that an old file silently leaves out. Compare the two:The release notes list anything a version needs from you, such as a new
setting to fill in or extra node capacity.
2
Take a database backup
Migrations run forwards only. There is no Note the current revision too — it is the one to
roll back to:Other layouts (a separate or managed database): see Databases › Backups, and Restoring for the rules a restore must follow.
down script, so a rollback of
the chart does not roll back the schema — see Rolling back.
For the single in-cluster Postgres (schema-per-service with
sharedDatabase: swarmd):3
Back up the keys
encryption-key / encryption-keys.4
Confirm you can read the credentials Secret
5
Preview the change
--dry-run=server, never plain --dry-run (see
The one that bricks installs).For a line-by-line view of what will change, helm diff upgrade with the
same arguments is better still; it is a plugin
(helm plugin install https://github.com/databus23/helm-diff).6
Check you have headroom for the ECR pull
The licence bootstrap Job refreshes the image-pull Secret as a
pre-upgrade hook, so an expired registry token is not a problem. A
licence that has expired is — the Job fails and the upgrade stops before
touching any workload. Check the expiry on your licence first.What happens during the rollout
Services are replaced in place rather than surged:maxSurge: 0,
maxUnavailable: 1.
That means a single-replica service is briefly unavailable while its pod
is replaced — roughly 40–70 seconds for a JVM service. It is deliberate. The
Kubernetes default starts a second pod before retiring the first, which
doubles the memory every service wants at the same moment; on a node sized for
the steady state the kubelet starts OOMKilling, and it kills the old pods
too. A routine upgrade takes down a working install.
If you need a genuinely zero-downtime rollout, run more than one replica and
put the surge back on that service — and size the node for the surge:
- Migration Jobs run to completion (
pre-upgradehooks, Flyway, forwards only). A service withworker.enabled: false— every service invalues-prismforce-local.yaml— has no Job and migrates as its pod starts instead. - Pods replaced one service at a time, each held at
Init:0/1until Keycloak’s realm answers. - The realm bootstrap Job for the new revision runs and exits early, because the realm already exists.
kubectl -n swarmd describe pod for
exit code 137 (OOMKilled) and see JVM sizing.
Rolling back
First find the revision you are going back to. Always name it. Without a revision,helm rollback goes to the previous revision, and that is only the
version you came from if nothing has been applied since. After a first
rollback attempt, or a second helm upgrade to change a value, “previous” is
the new version again.
Rolling back with a restore
Run this from the directory holding the dumps you took before upgrading, straight after thehelm rollback
above. It is self-contained: it reads the Postgres credentials itself, and it
puts every workload back at the replica count it had.
swarmd-generated-credentials. The rollback puts the Secret back as the older release wrote it, so keys the newer version added are removed. That is safe:encryption-keysis derived fromencryption-key, and the per-service Keycloak client secrets are regenerated and re-applied to Keycloak by each service at start, so upgrading again rebuilds both. The keys the older version uses are never changed.- ClickHouse. Its volume is kept when a rollback removes ClickHouse, so its data is still there when you upgrade again.
Skipping versions
Upgrading across several versions in one jump works — migrations are cumulative and run in order. What it costs you is the ability to tell which version broke something. On an install carrying data you care about, step through one minor version at a time and let each one settle. On a rebuildable environment, jump.Verifying afterwards
Running only tells you the JVMs started.
Next
Configuration
Secrets, JVM sizing, and the core/worker split.
Databases
Layouts, external Postgres and backups.
