- Home
- Operations Guide
- Upgrade Guide
- Upgrade PostgreSQL in HA Deployments
Upgrade PostgreSQL in HA Deployments#
This section is intended for MSR administrators who manage the PostgreSQL cluster of an MSR deployment with High Availability (HA). It applies to the PostgreSQL cluster deployed with the Zalando Postgres Operator as described in Install highly available PostgreSQL. The procedure explains how to upgrade the Postgres Operator, the Spilo image, and the PostgreSQL major version.
Upgrading PostgreSQL is an on-demand task that you can perform independently of MSR upgrades. Typical reasons to upgrade include:
- Compatibility with the MSR and Kubernetes versions that you run or plan to run.
- Features that are available only in a newer PostgreSQL version.
Note
In single-host deployments, MSR manages its internal PostgreSQL database and upgrades it together with MSR.
Before You Upgrade#
-
Verify that the Compatibility Matrix lists the target combination of MSR, Kubernetes, and Postgres Operator.
If the matrix does not list your Kubernetes version for your MSR version, upgrade MSR first.
-
Back up the MSR database:
kubectl -n <namespace> exec <cluster-name>-0 -- \ pg_dumpall -U postgres > msr-postgres-backup.sql -
Verify that the PostgreSQL cluster is healthy. All members must be
running, and one member must be theLeader:kubectl -n <namespace> exec <cluster-name>-0 -- patronictl list -
Plan a maintenance window. MSR loses its database connection during parts of the upgrade.
Expected Service Interruption#
| Upgrade | What happens | Impact on MSR |
|---|---|---|
| Postgres Operator, 2.x to 2.x | The operator pod restarts. If the pod specification changes, the operator rolls the PostgreSQL pods. | None, or a brief disconnect if the PostgreSQL pods roll. |
| Postgres Operator, 1.x to 2.x | The Patroni leader state moves from Endpoints to ConfigMaps, and the PostgreSQL pods restart. | MSR loses its database connection while the primary pod restarts. |
| Spilo image | The operator rolls the PostgreSQL pods one by one. With replicas, the primary switches over to an updated replica, usually in less than 5 seconds. | A brief disconnect with replicas. With a single instance, MSR is unavailable while the pod restarts. |
| PostgreSQL major version, 17 to 18 | The operator runs pg_upgrade on the primary and re-creates the replicas. |
MSR loses its database connection during the upgrade, and users must log in again. |
Upgrade the Postgres Operator and the Spilo Image#
-
Verify the Zalando Postgres Operator image:
kubectl -n <operator-namespace> get operatorconfiguration.acid.zalan.do \ -o=jsonpath='{.items[0].configuration.docker_image}' -
Identify the installed Postgres Operator version:
helm list -A --filter postgres-operator -
Perform the upgrade for the installed Postgres Operator version. The
helm upgradecommand upgrades the Postgres Operator and sets the Spilo image in theconfigGeneral.docker_imageparameter. The operator then replaces the PostgreSQL pods one by one to run the new image:Warning
The
helm upgradecommands below do not use--reuse-values. Therefore, each command resets the operator values that it does not set to the chart defaults, including any custom values that you set during installation.For example, the upgrade from 1.x to 2.x scales the cluster back by resetting
min_instancesandmax_instancesto the chart default-1.helm upgrade postgres-operator postgres-operator \ -n <operator-namespace> \ --repo https://opensource.zalando.com/postgres-operator/charts/postgres-operator \ --version 2.0.2 \ --set configGeneral.docker_image=registry.mirantis.com/msr/spilo:18-4.1-p2-20260907083821Warning
Postgres Operator 2.x changes the default of
kubernetes_use_configmapstotrue, so Patroni keeps the leader state in ConfigMaps instead of Endpoints, which Kubernetes deprecates starting from version 1.33. To avoid a split-brain while a leader Endpoint and a leader ConfigMap exist at the same time, scale the cluster to a single instance before you switch to ConfigMaps. The primary pod restarts during the switch, and MSR is unavailable until it is back.For details, see Zalando Postgres Operator documentation: Migrate from v1 to v2.
-
Upgrade the operator, keep Endpoints, and scale the cluster to one instance:
helm upgrade postgres-operator postgres-operator \ -n <operator-namespace> \ --repo https://opensource.zalando.com/postgres-operator/charts/postgres-operator \ --version 2.0.2 \ --set configGeneral.docker_image=registry.mirantis.com/msr/spilo:17-4.0-p3-20260907083821 \ --set configGeneral.kubernetes_use_configmaps=false \ --set configGeneral.min_instances=1 \ --set configGeneral.max_instances=1 -
Wait until the cluster has a single healthy
Leader:kubectl -n <namespace> exec <cluster-name>-0 -- patronictl list -
Switch to ConfigMaps:
helm upgrade postgres-operator postgres-operator \ -n <operator-namespace> \ --repo https://opensource.zalando.com/postgres-operator/charts/postgres-operator \ --version 2.0.2 \ --set configGeneral.docker_image=registry.mirantis.com/msr/spilo:17-4.0-p3-20260907083821 \ --set configGeneral.kubernetes_use_configmaps=true \ --set configGeneral.min_instances=1 \ --set configGeneral.max_instances=1 -
Verify that the Patroni ConfigMaps exist:
kubectl -n <namespace> get configmap \ <cluster-name>-leader <cluster-name>-config <cluster-name>-failover -
Scale the cluster back to
numberOfInstances:helm upgrade postgres-operator postgres-operator \ -n <operator-namespace> \ --repo https://opensource.zalando.com/postgres-operator/charts/postgres-operator \ --version 2.0.2 \ --set configGeneral.docker_image=registry.mirantis.com/msr/spilo:17-4.0-p3-20260907083821 -
Upgrade PostgreSQL to version 18 as described in Upgrade PostgreSQL from Version 17 to 18.
-
-
Verify the upgrade as described in Perform the Post-Upgrade Checks.
Upgrade PostgreSQL from Version 17 to 18#
Note
If the manifest defines maintenanceWindows, the operator runs the upgrade only within those windows.
For details, see Zalando Postgres Operator documentation: In-place major version upgrade.
-
You cannot revert the upgrade after
pg_upgraderuns. Therefore, back up the MSR database:kubectl -n <namespace> exec <cluster-name>-0 -- \ pg_dumpall -U postgres > msr-postgres-backup.sql -
Switch the operator to the Spilo 18 image. The PostgreSQL pods restart one by one and continue to run PostgreSQL 17:
helm upgrade postgres-operator postgres-operator \ -n <operator-namespace> \ --repo https://opensource.zalando.com/postgres-operator/charts/postgres-operator \ --version 2.0.2 \ --set configGeneral.docker_image=registry.mirantis.com/msr/spilo:18-4.1-p2-20260907083821 -
Wait until all PostgreSQL pods are
RunningandReady:kubectl -n <namespace> get pods \ -l application=spilo,cluster-name=<cluster-name> -
In
msr-postgres-manifest.yaml, change the PostgreSQL version from"17"to"18":spec: postgresql: version: "18" -
Apply the manifest. The operator runs an in-place major version upgrade (
pg_upgrade) on the primary and then re-creates the replicas:kubectl -n <namespace> apply -f msr-postgres-manifest.yaml -
Verify the upgrade as described in Perform the Post-Upgrade Checks.
Perform the Post-Upgrade Checks#
-
Verify that all PostgreSQL pods are
RunningandReady:kubectl -n <namespace> get pods \ -l application=spilo,cluster-name=<cluster-name> -
Verify that the Patroni cluster has one
Leaderand that all replicas arestreaming:kubectl -n <namespace> exec <cluster-name>-0 -- patronictl list -
Verify that the operator uses the expected pod image:
kubectl -n <operator-namespace> get operatorconfiguration.acid.zalan.do \ -o=jsonpath='{.items[0].configuration.docker_image}' -
After an upgrade from Postgres Operator 1.x to 2.x, verify that the Patroni ConfigMaps exist:
kubectl -n <namespace> get configmap \ <cluster-name>-leader <cluster-name>-config <cluster-name>-failover -
After a PostgreSQL major version upgrade, verify that the
postgresqlresource has thelast-major-upgrade-successannotation and that the server reports the new version. Alast-major-upgrade-failureannotation means that the upgrade failed:kubectl -n <namespace> get postgresql <cluster-name> \ -o jsonpath='{.metadata.annotations}' kubectl -n <namespace> exec <cluster-name>-0 -- \ psql -U postgres -tc 'SHOW server_version;' -
Verify that MSR reports all components, including the database, as healthy:
curl -u admin:<password> https://<msr-host>/api/v2.0/health -
Log in to MSR, push an image, and pull it back.
Now, you have successfully upgraded PostgreSQL, and MSR is ready to use with the upgraded database.