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.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
Take a database backup
Migrations run forwards only. There is no
down script, so a rollback of
the chart does not roll back the schema — see Rolling back.2
Confirm you can read the credentials Secret
3
Preview the change
helm diff is a plugin (helm plugin install https://github.com/databus23/helm-diff)
and is the single most useful thing you can install for this. Failing
that, --dry-run=server and read the output.4
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). - 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
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.
