Upgrade
When this page is done you are running the new release, with the same data.
Read Roll back before you start. The rollback boundary changes what a safe upgrade looks like.
Before you start
- Read the release notes for every version between yours and the target
- A current backup. See Back up and restore
- The new release's install kit, verified
- A maintenance window. The application is briefly unavailable while pods roll
Rules that are not negotiable
| Rule | Why |
|---|---|
| One minor at a time | Skipping a minor is not supported. Each train's migrations assume the previous train ran |
| Patches in place | Within a train, upgrade directly |
| Same order as install: infra, then data, then platform | Each chart depends on the previous one |
| Apply CRDs by hand first | Helm never upgrades CRDs. See step 1 |
| Back up first | The migration hook changes your schema, and helm rollback does not undo that |
1. Apply the new CRDs
Do this before anything else. Helm installs a chart's CRDs on first install and ignores them from then on. An upgrade that ships a new CRD schema fails with a server-side-apply error, or worse, silently rejects fields it does not know.
cd $B/charts
tar xzf gen0sec-infra-*.tgz
kubectl apply --server-side --force-conflicts \
-f gen0sec-infra/charts/postgres-operator/crds/
kubectl apply --server-side --force-conflicts \
-f gen0sec-infra/charts/strimzi-kafka-operator/crds/
The output is similar to this:
customresourcedefinition.apiextensions.k8s.io/postgresqls.acid.zalan.do serverside-applied
The Postgres operator 1.15 to 2.0 change adds PostgreSQL 18 to the postgresqls schema. Without the
CRD apply, the postgresql/core resource is rejected outright and the database never starts.
2. Get the new artifacts
Follow Prepare the artifacts for the new release. Both methods work the same as on a first install, with one addition for the offline bundle.
Offline bundle only. Mirroring is additive: the new tags land beside the old ones. Your running install keeps working until you upgrade, and a rollback still has its images.
Do not reuse the previous bundle's directory. The bundler refuses to write into an existing one, and each bundle's values files are targeted at the version they shipped with.
3. Upgrade infra
Run every command from the new bundle directory, so charts/ and values/ are the new release's.
helm upgrade g0s-infra $B/charts/gen0sec-infra-*.tgz \
-n gen0sec-system \
-f $B/values/gen0sec-infra-values-onprem.yaml
If you installed the platform under a release name or namespace other than g0s in gen0sec,
add --set components.ui.serviceAccountName=<release>-ui,components.ui.namespace=<namespace> here.
The infra chart binds the dashboard's service account by name, and a wrong name fails silently: the
Components tab then cannot show infrastructure versions.
Wait for the operators to finish rolling before continuing.
kubectl -n gen0sec-system rollout status deploy/g0s-infra-postgres-operator
kubectl -n gen0sec-system rollout status deploy/strimzi-cluster-operator
kubectl -n gen0sec-system rollout status deploy/g0s-infra-synapse-operator
kubectl -n gen0sec-system rollout status deploy/dragonfly
kubectl -n gen0sec-system rollout status \
"$(kubectl -n gen0sec-system get sts,deploy -o name | grep -m1 rustfs)"
4. Upgrade data
helm upgrade g0s-data $B/charts/gen0sec-data-*.tgz \
-n gen0sec-system \
-f $B/values/gen0sec-data-values-onprem.yaml
kubectl -n gen0sec-system wait --for=condition=Ready kafka/core --timeout=15m
kubectl -n gen0sec-system wait \
--for=jsonpath='{.status.PostgresClusterStatus}'=Running postgresql/core --timeout=15m
5. Upgrade the platform
The schema migration runs first, as a pre-upgrade hook, before any new pod rolls.
helm upgrade g0s $B/charts/gen0sec-platform-*.tgz \
-n gen0sec \
-f $B/values/gen0sec-platform-values-onprem.yaml \
-f $KIT/examples/single-entrypoint/ingress-values.yaml \
--set entrypointHost=$ENTRYPOINT_HOST \
--set global.imageTag=$VERSION \
--timeout 20m
Upgrading from v0.1.x, entrypointHost is required even if you never published the endpoints: the
dashboard now builds its sign-in URL from it, and the render fails without it.
$KIT is the new release's kit. Pass every file you layered at install time, in the same order:
helm upgrade applies only what you give it. Leaving out the ingress overlay removes every Ingress,
and leaving out single-node/platform-values.yaml on a quickstart install scales every service back
to its production replica count. See Publish the endpoints.
If the migration fails, Helm aborts and the old application keeps running. That is the designed behavior and it is why the hook runs before the rollout.
kubectl -n gen0sec logs job/g0s-db-migrate
Fix the cause, then re-run the same command. See Migration failures.
20261004150000 changes a constraint on the block events table and waits at most 10 seconds for its
lock. On a busy install the job fails with canceling statement due to lock timeout and leaves the
schema dirty. Nothing was changed. Pause the block events pipeline, mark the previous version and
re-run this step:
kubectl -n gen0sec-system scale deploy/g0s-data-kafka2pg-block-events --replicas=0
kubectl -n gen0sec run db-migrate-force --rm -it --restart=Never \
--image=$REGISTRY/gen0sec/db-migrate:$VERSION \
--env DATABASE_URL="$OWNER_DSN" -- force 20261004120000
Scale the pipeline back to 1 once the upgrade completes. Events wait in Kafka meanwhile.
6. Verify
kubectl -n gen0sec wait --for=condition=Ready pod --all --timeout=10m
$KIT/scripts/verify-deployment.sh
Run the smoke test after every upgrade, not just after installs. It is the only check that proves the platform still serves an agent rather than merely starting.
Full checklist: Verify the install.
If you changed values along the way
helm upgrade uses the values files you pass, not the ones from last time. Anything you set with
--set on the previous install must be set again, or it reverts to the chart default.
Check what the running release actually has:
helm get values g0s -n gen0sec
Keep your overrides in a file rather than in shell history. See Reference configurations.
If it fails
| Symptom | Start here |
|---|---|
CRD schema error on helm upgrade | You skipped step 1 |
Unsupported value from the Postgres operator | You skipped step 1 |
| Migration job fails | Migration failures |
Migration job fails with lock timeout | A busy block events table. See the note in step 5 |
| Pods roll but the smoke test fails | Roll back |
ImagePullBackOff on new tags | The new images were not mirrored. Offline bundle method, step 2 |