PostgreSQL Major Version Upgrade Steps¶
The following steps will guide you through a major version upgrade of PostgreSQL (e.g., 13 to 15). A shutdown of all Pulp pods is required, so a maintenance window is recommended.
ℹ️ NOTE
The steps were tested only with postgres deployed by the operator. For steps to upgrade external databases follow your vendor documentation.
Prerequisites¶
- make sure you have enough storage space on the machine running
kubectl(we will copy the dump locally) - make sure to have a backup of the environment
To get an approximate size of the database:
kubectl -n $PULP_NAMESPACE exec ${PULP_CR}-database-0 -- psql -U pulp -c "SELECT pg_size_pretty(pg_database_size('pulp'));"
Step 1 — Set env vars¶
- these environment variables will be used several times in the next steps
PULP_CR=pulp PULP_NAMESPACE=pulp
Step 2 — Scale Down Pulp Components¶
Scale down all Pulp pods to avoid any writes to the database:
kubectl -n $PULP_NAMESPACE patch pulp $PULP_CR --type merge -p '{"spec":{"api":{"replicas":0},"content":{"replicas":0},"worker":{"replicas":0}}}'
- if you have pulp web running:
kubectl -n $PULP_NAMESPACE patch pulp $PULP_CR --type merge -p '{"spec":{"web":{"replicas":0}}}'
Wait for all API, content, and worker pods to terminate:
kubectl -n $PULP_NAMESPACE get pods -w
Step 3 — Dump the Database¶
Run pg_dump inside the running database pod and store it in /tmp/pulp.db on the local machine:
kubectl -n $PULP_NAMESPACE exec ${PULP_CR}-database-0 -- pg_dump --clean -Ft -U pulp -d pulp > /tmp/pulp.db
Step 4 — Delete the Old Database StatefulSet and PVC¶
Put the operator in unmanaged state to avoid the StatefulSet redeploy:
kubectl -n $PULP_NAMESPACE patch pulp $PULP_CR --type merge -p '{"spec":{"unmanaged":true}}'
Delete the postgres StatefulSet and PVC:
kubectl -n $PULP_NAMESPACE delete statefulset ${PULP_CR}-database
kubectl -n $PULP_NAMESPACE delete pvc ${PULP_CR}-postgres-${PULP_CR}-database-0
Step 5 — Update the Pulp CR to Use the New PostgreSQL Version¶
Update the postgres_image to the desired version (e.g., PostgreSQL 15):
kubectl -n $PULP_NAMESPACE patch pulp $PULP_CR --type merge -p '{"spec":{"database":{"postgres_image":"docker.io/library/postgres:15"}}}'
Put the operator back to a managed state:
kubectl -n $PULP_NAMESPACE patch pulp $PULP_CR --type merge -p '{"spec":{"unmanaged":false}}'
Wait for the operator to reconcile and the new database pod to be running:
kubectl -n $PULP_NAMESPACE wait --for condition=Pulp-Operator-Finished-Execution pulp/$PULP_CR --timeout=900s
kubectl -n $PULP_NAMESPACE get pods -w
Step 6 — Restore the Dump into the New PostgreSQL¶
Copy the dump to the new database pod:
kubectl -n $PULP_NAMESPACE cp /tmp/pulp.db ${PULP_CR}-database-0:/tmp/pulp.db
Run the pg_restore:
kubectl -n $PULP_NAMESPACE exec ${PULP_CR}-database-0 -- bash -c 'pg_restore --clean --if-exists -U pulp -d pulp /tmp/pulp.db'
If pg_restore reports errors about objects already existing (e.g., the pulp role), that is
expected since --clean drops before creating but some default objects may already exist.
Verify the exit code (echo $?) — a non-zero exit due to pre-existing objects is harmless,
but data-related errors should be investigated.
Clean up the dump file from the database pod:
kubectl -n $PULP_NAMESPACE exec ${PULP_CR}-database-0 -- rm /tmp/pulp.db
Step 7 — Scale Pulp Back Up¶
Make sure to set the number of replicas according to your environment needs:
kubectl -n $PULP_NAMESPACE patch pulp $PULP_CR --type merge -p '{"spec":{"api":{"replicas":1},"content":{"replicas":1},"worker":{"replicas":1}}}'
- if you have pulp web running:
kubectl -n $PULP_NAMESPACE patch pulp $PULP_CR --type merge -p '{"spec":{"web":{"replicas":1}}}'
Wait for the pods to get into a running state:
kubectl -n $PULP_NAMESPACE wait --for condition=Pulp-Operator-Finished-Execution pulp/$PULP_CR --timeout=900s
Step 8 — Verify¶
Confirm PostgreSQL version
kubectl -n $PULP_NAMESPACE exec ${PULP_CR}-database-0 -- psql -U pulp -c "SELECT version();"
Check pods are healthy
kubectl -n $PULP_NAMESPACE get pods
Check pulp status (requires Pulp CLI installed and configured):
pulp status
You can also clean up the local dump file once you have confirmed the upgrade is successful:
rm /tmp/pulp.db
Rollback¶
If the restore fails, the local dump file (/tmp/pulp.db) can be used to retry.
Repeat from Step 4 to re-create the database pod and restore again.