Upgrade of the PostgreSQL Dogu
When developing the PostgreSQL Dogu further, it must be ensured that existing instances can be upgraded to newer versions.
The upgrade path consists of pre-upgrade.sh before the image switch and post-upgrade.sh after the image switch.
General process
During a Dogu upgrade, pre-upgrade.sh is executed first in the old container.
After that, the new image is started and post-upgrade.sh is executed.
At the same time, startup.sh starts the official PostgreSQL entrypoint.
Pre-upgrade (resources/pre-upgrade.sh)
pre-upgrade.sh decides whether a full backup is required.
A backup is created, among other things, for major upgrades or layout migrations.
Important points:
- A full backup using
pg_dumpallis stored under/var/lib/postgresql/backup. - The backup path is stored in config under
migration_backup_path. local_state=upgradingis set so thatstartup.shcan wait for a running upgrade.
Post-upgrade (resources/post-upgrade.sh)
post-upgrade.sh distinguishes between restore cases and regular migrations.
Restore case:
- If
migration_backup_pathis set, the target directory is prepared for restore. post-upgrade.shinitializes a new database with the functions of the official entrypoint and starts it temporarily.restore.shrestores the backup, then password rotation and migrations run as in the regular case.local_stateis removed only at the very end, until thenstartup.shwaits.
The restore must run completely within post-upgrade.sh and not during the regular startup:
The Dogu operator restarts the pod as soon as post-upgrade.sh has finished.
A restore during startup would be aborted and leave a partially restored database behind.
If a run is aborted, migration_backup_path stays set and the next call starts over with an empty PGDATA.
A flock prevents a repeated call by the operator from interfering with a restore that is still running.
Regular migration case:
- If no restore is needed and a DB is already initialized,
post-upgrade.shstarts PostgreSQL temporarily. - The superuser password is rotated once (see below).
- Then migration scripts from
/docker-entrypoint-initdb.d(fromresources/migrations) are executed manually. - PostgreSQL is stopped again and
local_stateis removed.
Rotation of the superuser password (rotateSuperuserPassword)
Before doguctl v0.12.2, doguctl random used Go's math/rand instead of crypto/rand. Affected values cannot be told apart from safe ones, so every instance without the marker rotates.
- Marker
password_rotatedin the Dogu config, no version comparison. - Order: config, then
ALTER USER, then the marker — an aborted rotation is retried. - Runs after
startPostgresql, becauseALTER USERneeds a running DB. On the Unix sockettrustapplies, so the old password is not needed. - Also runs in the restore case, after the backup has been restored.
Startup (resources/startup.sh)
startup.sh waits as long as local_state=upgrading is set.
If PGDATA is empty, initAdmin additionally sets password_rotated=true, because a freshly generated password is safe.
After that, it starts /usr/local/bin/docker-entrypoint.sh with Dogu-specific parameters.
Important:
The official entrypoint executes scripts in /docker-entrypoint-initdb.d automatically only for a fresh initialization.
Therefore, for existing data, scripts are called manually in post-upgrade.sh.
Where should new migration scripts be added?
New migration scripts go into resources/migrations/ and are copied in the Dockerfile to /docker-entrypoint-initdb.d/.
Current scripts:
resources/migrations/02-restrictStatVisibility.shresources/migrations/03-migrateConstraintsOnPartitionedTables.sh
The restore (resources/restore.sh) is deliberately not a migration script, it is only called by post-upgrade.sh.
Order and conventions
- Name scripts as
NN-description.sh(01-...,02-..., ...). - Keep scripts idempotent (running them multiple times must not cause problems).
- Set completion markers in Dogu config (for example
restricted_stat_visibility=true) so steps only run once. - Always use
set -o errexit -o nounset -o pipefail.