Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
89ec787
PMM-7 Upgrade internal PostgreSQL from 14 to 18.
talhabinrizwan Apr 17, 2026
31745a5
PMM-7 Upgrade internal PostgreSQL from 14 to 18.
talhabinrizwan Apr 17, 2026
db280b1
Grant CREATE ON SCHEMA public to grafana and pmm-managed users
talhabinrizwan Apr 17, 2026
01a7a31
Fix permission denied on public schema for PostgreSQL 15+
talhabinrizwan Apr 17, 2026
439689a
Grant CREATE ON SCHEMA public before running migrations
talhabinrizwan Apr 18, 2026
17bf090
Restore scram-sha-256 pg_hba entry for dev container
talhabinrizwan Apr 27, 2026
a4374dd
PMM-15014 Remove max_connections from pmm_config.go template
talhabinrizwan Apr 27, 2026
803a9e4
Merge branch 'main' into PMM-15014-upgrade-to-pg18
ademidoff Jul 30, 2026
e712e3e
PMM-15014 Document the PostgreSQL 14 to 18 migration
ademidoff Jul 30, 2026
f3dfe58
PMM-15014 Grant schema access through database ownership
ademidoff Jul 30, 2026
9061044
PMM-15014 Move embedded cluster creation into postgres-migration
ademidoff Jul 30, 2026
eb125aa
PMM-15014 Drop the pg_hba trust rewrite
ademidoff Jul 30, 2026
b1dff33
PMM-15014 Temporarily lower minPGVersion to 14
ademidoff Jul 30, 2026
7cdda0c
PMM-15014 Temporarily expect postgresql14.log in TestFiles
ademidoff Jul 30, 2026
9a4748a
PMM-15014 Name the PostgreSQL log file without the major version
ademidoff Jul 30, 2026
a0d070f
PMM-15014 Shorten the counter variable names in initWithRoot
ademidoff Jul 30, 2026
6326518
PMM-15014 Quote identifiers and the password in initWithRoot
ademidoff Jul 30, 2026
7e21ec6
PMM-15014 Fix the pg14 upgrade on data directories from PMM 2
ademidoff Jul 30, 2026
d82c74c
PMM-15014 Remove the upgrade dumps once the migration completes
ademidoff Jul 30, 2026
ce54fef
PMM-15014 Build the new cluster in a staging directory
ademidoff Jul 30, 2026
d4e5517
Merge branch 'main' into PMM-15014-upgrade-to-pg18
ademidoff Aug 5, 2026
d462e79
Merge branch 'main' into PMM-15014-upgrade-to-pg18
ademidoff Aug 31, 2026
617af31
PMM-15014 Keep minPGVersion at 14
ademidoff Aug 31, 2026
87ae436
PMM-15014 Expect postgresql.log in TestFiles
ademidoff Aug 31, 2026
1bb05db
PMM-15014 Restore the v11 to v14 dumps with psql
ademidoff Aug 31, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions .devcontainer/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,14 +73,14 @@ def setup():
"""Runs various setup commands."""
run_commands([
# allow connecting from any host, needed to connect from host to PG running in docker
"sed -i -e \"s/#listen_addresses = 'localhost'/listen_addresses = '*'/\" /srv/postgres14/postgresql.conf",
"sed -i -e \"s/#listen_addresses = 'localhost'/listen_addresses = '*'/\" /srv/postgres18/postgresql.conf",
# Turns fsync off. Create database operations with fsync on are very slow on Ubuntu.
# Having fsync off in dev environment is fine.
"sed -i -e \"s/#fsync = on/fsync = off/\" /srv/postgres14/postgresql.conf",
"sed -i -e \"s/#fsync = on/fsync = off/\" /srv/postgres18/postgresql.conf",
# Configure pg_hba.conf for password authentication from all hosts (dev environment only)
# Note: In dev, we allow both trust and scram-sha-256 for convenience
"echo 'host all all 0.0.0.0/0 trust' >> /srv/postgres14/pg_hba.conf",
"echo 'host all all 0.0.0.0/0 scram-sha-256' >> /srv/postgres14/pg_hba.conf",
# Note: In dev, we allow both trust and scram-sha-256 for convenience
"echo 'host all all 0.0.0.0/0 trust' >> /srv/postgres18/pg_hba.conf",
"echo 'host all all 0.0.0.0/0 scram-sha-256' >> /srv/postgres18/pg_hba.conf",
# "supervisorctl restart postgresql",
])

Expand Down
2 changes: 1 addition & 1 deletion api-tests/server/logs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ func TestDownloadLogs(t *testing.T) {
"pmm-version.txt",
"pmm.conf",
"pmm.ini",
"postgresql14.log",
"postgresql18.log",
"prometheus.base.yml",
"qan-api2.ini",
"qan-api2.log",
Expand Down
2 changes: 1 addition & 1 deletion build/ansible/roles/grafana/files/datasources.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ datasources:
sslRootCertFile: ${PMM_POSTGRES_SSL_CA_PATH}
sslKeyFile: ${PMM_POSTGRES_SSL_KEY_PATH}
sslCertFile: ${PMM_POSTGRES_SSL_CERT_PATH}
postgresVersion: "1100"
postgresVersion: "1800"
sslmode: ${PMM_POSTGRES_SSL_MODE}
secureJsonData:
password: ${PMM_POSTGRES_DBPASSWORD}
Expand Down
11 changes: 11 additions & 0 deletions build/ansible/roles/initialization/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,17 @@
when: not ansible_check_mode
environment:
PGPASSWORD: "{{ lookup('file', '/srv/.postgres_password') }}"

- name: Grant CREATE on public schema to grafana user
postgresql_privs:
database: grafana
privs: CREATE
type: schema
objs: public
roles: grafana
login_user: postgres
environment:
PGPASSWORD: "{{ lookup('file', '/srv/.postgres_password') }}"
when:
- lookup('env','GF_DATABASE_URL') == ''
- lookup('env','GF_DATABASE_HOST') == ''
Expand Down
2 changes: 1 addition & 1 deletion build/ansible/roles/pmm-images/tasks/main.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
# We use percona-release package to install the gpg keys and ppg-14
# We use percona-release package to install the gpg keys and ppg-18
# To workaround the package's incompatibility with RHEL9, we have to disable the gpg verification :(
- name: Add percona-release package
dnf:
Expand Down
111 changes: 104 additions & 7 deletions build/ansible/roles/postgres/files/postgres-migration
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,105 @@
set -o errexit
set -o pipefail

declare POSTGRES_DATA_DIR="${POSTGRES_DATA_DIR:-/srv/postgres14}"
declare POSTGRES_DATA_DIR="${POSTGRES_DATA_DIR:-/srv/postgres18}"
declare POSTGRES_PASSWORD_FILE="${POSTGRES_PASSWORD_FILE:-/srv/.postgres_password}"

# ── pg14 → pg18 upgrade ───────────────────────────────────────────────────────
# Runs once when /srv/postgres14 exists and /srv/postgres18 does not.
# Requires both pg14 and pg18 binaries in the image (shipped through PMM 3.12.x).
upgrade_pg14_to_pg18() {
local PG14_DATA="/srv/postgres14"
local PG14_BIN="/usr/pgsql-14/bin"
local PG18_BIN="/usr/pgsql-18/bin"
local BACKUP_DIR="/srv/backup"

if [ ! -d "$PG14_DATA" ] || [ -d "$POSTGRES_DATA_DIR" ]; then
return
fi

echo "PostgreSQL 14 data found at $PG14_DATA. Migrating to PostgreSQL 18..."

local PGPASSWORD
PGPASSWORD=$(cat "$POSTGRES_PASSWORD_FILE")
export PGPASSWORD
Comment thread
coderabbitai[bot] marked this conversation as resolved.

# Start pg14 and dump databases
echo "Starting PostgreSQL 14 for dump..."
"$PG14_BIN/pg_ctl" start -D "$PG14_DATA" -o "-c logging_collector=off" -w

mkdir -p "$BACKUP_DIR"

echo "Dumping pmm-managed database..."
"$PG14_BIN/pg_dump" -h /run/postgresql -U postgres -F p \
-f "${BACKUP_DIR}/pg18-upgrade-pmm-managed.sql" pmm-managed

# Skip grafana dump when an external database is configured (HA mode).
if [ -z "${GF_DATABASE_URL}" ] && [ -z "${GF_DATABASE_HOST}" ]; then
echo "Dumping grafana database..."
"$PG14_BIN/pg_dump" -h /run/postgresql -U postgres -F p \
-f "${BACKUP_DIR}/pg18-upgrade-grafana.sql" grafana
fi

echo "Stopping PostgreSQL 14..."
"$PG14_BIN/pg_ctl" stop -D "$PG14_DATA" -w

unset PGPASSWORD

# Initialise pg18
echo "Initialising PostgreSQL 18 at $POSTGRES_DATA_DIR..."
install -d -m 750 "$POSTGRES_DATA_DIR"
"$PG18_BIN/initdb" -D "$POSTGRES_DATA_DIR" \
--auth-host=scram-sha-256 \
--auth-local=trust \
--username=postgres \
--pwfile="$POSTGRES_PASSWORD_FILE"

# Start pg18 and restore
echo "Starting PostgreSQL 18..."
"$PG18_BIN/pg_ctl" start -D "$POSTGRES_DATA_DIR" -o "-c logging_collector=off" -w

PGPASSWORD=$(cat "$POSTGRES_PASSWORD_FILE")
export PGPASSWORD

echo "Creating pmm-managed role and database..."
"$PG18_BIN/psql" -h /run/postgresql -U postgres -d postgres \
-c "CREATE ROLE \"pmm-managed\" LOGIN PASSWORD 'pmm-managed'"
"$PG18_BIN/psql" -h /run/postgresql -U postgres -d postgres \
-c "CREATE DATABASE \"pmm-managed\" OWNER \"pmm-managed\""
"$PG18_BIN/psql" -h /run/postgresql -U postgres -d pmm-managed \
-c "GRANT CREATE ON SCHEMA public TO \"pmm-managed\""
echo "Restoring pmm-managed database..."
"$PG18_BIN/psql" -h /run/postgresql -U postgres -d pmm-managed \
-f "${BACKUP_DIR}/pg18-upgrade-pmm-managed.sql"

if [ -f "${BACKUP_DIR}/pg18-upgrade-grafana.sql" ]; then
echo "Creating grafana role and database..."
"$PG18_BIN/psql" -h /run/postgresql -U postgres -d postgres \
-c "CREATE ROLE grafana LOGIN PASSWORD 'grafana'"
"$PG18_BIN/psql" -h /run/postgresql -U postgres -d postgres \
-c "CREATE DATABASE grafana OWNER grafana"
"$PG18_BIN/psql" -h /run/postgresql -U postgres -d grafana \
-c "GRANT CREATE ON SCHEMA public TO grafana"
echo "Restoring grafana database..."
"$PG18_BIN/psql" -h /run/postgresql -U postgres -d grafana \
-f "${BACKUP_DIR}/pg18-upgrade-grafana.sql"
fi

echo "Ensuring pg_stat_statements extension..."
"$PG18_BIN/psql" -h /run/postgresql -U postgres -d postgres \
-c "CREATE EXTENSION IF NOT EXISTS pg_stat_statements SCHEMA public"

echo "Stopping PostgreSQL 18..."
"$PG18_BIN/pg_ctl" stop -D "$POSTGRES_DATA_DIR" -w

unset PGPASSWORD

echo "Renaming $PG14_DATA to ${PG14_DATA}.old for rollback safety..."
mv "$PG14_DATA" "${PG14_DATA}.old"

echo "PostgreSQL 14 to 18 migration completed successfully."
}

ensure_postgres_password() {
# This check is to verify if the data directory is empty.
if [ ! -f "$POSTGRES_DATA_DIR/PG_VERSION" ]; then
Expand All @@ -20,8 +116,8 @@ ensure_postgres_password() {
echo "Generating postgres superuser password..."
POSTGRES_PASSWORD=$(openssl rand -hex 16)

if ! /usr/pgsql-14/bin/pg_ctl status -D "$POSTGRES_DATA_DIR" > /dev/null 2>&1; then
/usr/pgsql-14/bin/pg_ctl start -D "$POSTGRES_DATA_DIR" -o "-c logging_collector=off"
if ! /usr/pgsql-18/bin/pg_ctl status -D "$POSTGRES_DATA_DIR" > /dev/null 2>&1; then
Comment thread
ademidoff marked this conversation as resolved.
Outdated
/usr/pgsql-18/bin/pg_ctl start -D "$POSTGRES_DATA_DIR" -o "-c logging_collector=off"
STARTED=1
fi

Expand All @@ -32,13 +128,13 @@ ensure_postgres_password() {
chmod 600 "$POSTGRES_PASSWORD_FILE"

if [ "$STARTED" -eq 1 ]; then
/usr/pgsql-14/bin/pg_ctl stop -D "$POSTGRES_DATA_DIR"
/usr/pgsql-18/bin/pg_ctl stop -D "$POSTGRES_DATA_DIR"
fi
}

update_pg_hba_auth() {
local hba="$POSTGRES_DATA_DIR/pg_hba.conf"

if [ ! -f "$hba" ]; then
return 1
fi
Expand All @@ -53,10 +149,11 @@ update_pg_hba_auth() {
sed -E 's/^([[:space:]]*host[[:space:]].*[[:space:]])trust([[:space:]]*)$/\1scram-sha-256\2/' "$hba" > "$tmp"
mv "$tmp" "$hba"

if /usr/pgsql-14/bin/pg_ctl status -D "$POSTGRES_DATA_DIR" > /dev/null 2>&1; then
/usr/pgsql-14/bin/pg_ctl reload -D "$POSTGRES_DATA_DIR"
if /usr/pgsql-18/bin/pg_ctl status -D "$POSTGRES_DATA_DIR" > /dev/null 2>&1; then
/usr/pgsql-18/bin/pg_ctl reload -D "$POSTGRES_DATA_DIR"
fi
}

upgrade_pg14_to_pg18

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this func uses /srv/.pgpassword file but is called before ensure_postgres_password that creates this file in case it is absent

ensure_postgres_password
update_pg_hba_auth || true
4 changes: 2 additions & 2 deletions build/ansible/roles/postgres/tasks/backup.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
become_method: su

- name: Run Postgres database without supervisor
command: /usr/pgsql-14/bin/pg_ctl start -D /srv/postgres14 -o "-c logging_collector=off"
command: /usr/pgsql-18/bin/pg_ctl start -D /srv/postgres18 -o "-c logging_collector=off"
become: true
become_user: pmm
become_method: su
Expand All @@ -55,7 +55,7 @@
PGPASSWORD: "{{ lookup('file', '/srv/.postgres_password') }}"

- name: Stop Postgres database without supervisor
command: /usr/pgsql-14/bin/pg_ctl stop -D /srv/postgres14
command: /usr/pgsql-18/bin/pg_ctl stop -D /srv/postgres18
become: true
become_user: pmm
become_method: su
Expand Down
48 changes: 41 additions & 7 deletions build/ansible/roles/postgres/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,29 @@
- name: Add PostgreSQL 14 YUM repository
yum_repository:
name: percona-ppg-14
description: PostgreSQL YUM repository
description: PostgreSQL 14 YUM repository
baseurl: http://repo.percona.com/ppg-14/yum/release/$releasever/RPMS/$basearch/
gpgcheck: yes
enabled: yes
gpgkey: file:///etc/pki/rpm-gpg/PERCONA-PACKAGING-KEY

- name: Add PostgreSQL 18 YUM repository
yum_repository:
name: percona-ppg-18
description: PostgreSQL 18 YUM repository
baseurl: http://repo.percona.com/ppg-18/yum/release/$releasever/RPMS/$basearch/
gpgcheck: yes
enabled: yes
gpgkey: file:///etc/pki/rpm-gpg/PERCONA-PACKAGING-KEY

- name: Install Postgres
when:
- not ansible_check_mode
dnf:
name:
- percona-postgresql18-server
- percona-postgresql18-contrib
- percona-postgresql18
- percona-postgresql14-server
- percona-postgresql14-contrib
- percona-postgresql14
Expand All @@ -29,7 +41,7 @@

- name: Create Postgres log file
file:
path: /srv/logs/postgresql14.log
path: /srv/logs/postgresql18.log
state: touch
force: yes
group: root
Expand All @@ -38,7 +50,7 @@

- name: Create Postgres data dir
file:
path: /srv/postgres14
path: /srv/postgres18
state: directory
owner: pmm
group: root
Expand All @@ -58,13 +70,13 @@
mode: 0600

- name: Initialize Postgres database with password authentication
command: /usr/pgsql-14/bin/initdb -D /srv/postgres14 --auth-host=scram-sha-256 --auth-local=trust --username=postgres --pwfile=/srv/.postgres_password
command: /usr/pgsql-18/bin/initdb -D /srv/postgres18 --auth-host=scram-sha-256 --auth-local=trust --username=postgres --pwfile=/srv/.postgres_password
become: true
become_user: pmm
become_method: su

- name: Start Postgres database without supervisor
command: /usr/pgsql-14/bin/pg_ctl start -D /srv/postgres14 -o "-c logging_collector=off"
command: /usr/pgsql-18/bin/pg_ctl start -D /srv/postgres18 -o "-c logging_collector=off"
become: true
become_user: pmm
become_method: su
Expand All @@ -89,6 +101,17 @@
environment:
PGPASSWORD: "{{ lookup('file', '/srv/.postgres_password') }}"

- name: Grant CREATE on public schema to pmm-managed user
postgresql_privs:
database: pmm-managed
privs: CREATE
type: schema
objs: public
roles: pmm-managed
login_user: postgres
environment:
PGPASSWORD: "{{ lookup('file', '/srv/.postgres_password') }}"

- name: Create pg_stat_statements extension
postgresql_ext:
db: postgres
Expand Down Expand Up @@ -116,12 +139,23 @@
environment:
PGPASSWORD: "{{ lookup('file', '/srv/.postgres_password') }}"

- name: Grant CREATE on public schema to grafana user
postgresql_privs:
database: grafana
privs: CREATE
type: schema
objs: public
roles: grafana
login_user: postgres
environment:
PGPASSWORD: "{{ lookup('file', '/srv/.postgres_password') }}"

- name: Upgrade grafana database to the latest schema
command: grafana cli --homepath=/usr/share/grafana --config=/etc/grafana/grafana.ini admin data-migration encrypt-datasource-passwords
changed_when: true

- name: Stop Postgres 14 database
command: /usr/pgsql-14/bin/pg_ctl stop -D /srv/postgres14
- name: Stop Postgres 18 database
command: /usr/pgsql-18/bin/pg_ctl stop -D /srv/postgres18
become: true
become_user: pmm
become_method: su
8 changes: 4 additions & 4 deletions build/ansible/roles/postgres/tasks/restore.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
become_method: su

- name: Run Postgres database without supervisor
command: /usr/pgsql-14/bin/pg_ctl start -D /srv/postgres14 -o "-c logging_collector=off"
command: /usr/pgsql-18/bin/pg_ctl start -D /srv/postgres18 -o "-c logging_collector=off"
become: true
become_user: pmm
become_method: su
Expand All @@ -41,15 +41,15 @@
postgresql_db:
name: pmm-managed
state: restore
target: /srv/postgres14/pmm-managed.sql
target: /srv/backup/pmm-managed.sql
environment:
PGPASSWORD: "{{ lookup('file', '/srv/.postgres_password') }}"

- name: Restore grafana database
postgresql_db:
name: grafana
state: restore
target: /srv/postgres14/grafana.sql
target: /srv/backup/grafana.sql
when: not is_ha
environment:
PGPASSWORD: "{{ lookup('file', '/srv/.postgres_password') }}"
Expand All @@ -63,7 +63,7 @@
PGPASSWORD: "{{ lookup('file', '/srv/.postgres_password') }}"

- name: Stop Postgres database without supervisor
command: /usr/pgsql-14/bin/pg_ctl stop -D /srv/postgres14
command: /usr/pgsql-18/bin/pg_ctl stop -D /srv/postgres18
become: true
become_user: pmm
become_method: su
Expand Down
6 changes: 3 additions & 3 deletions build/ansible/roles/supervisord/files/pmm.ini
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ environment = ANSIBLE_CONFIG="/opt/ansible/ansible.cfg"
[program:postgresql]
priority = 1
command =
/usr/pgsql-14/bin/postgres
-D /srv/postgres14
/usr/pgsql-18/bin/postgres
-D /srv/postgres18
-c shared_preload_libraries=pg_stat_statements
-c pg_stat_statements.max=10000
-c pg_stat_statements.track=all
Expand All @@ -44,7 +44,7 @@ stopsignal = INT ; Fast Shutdown mode
stopwaitsecs = 300
; postgresql.conf contains settings to log to stdout,
; so we delegate logfile management to supervisord
stdout_logfile = /srv/logs/postgresql14.log
stdout_logfile = /srv/logs/postgresql18.log
stdout_logfile_maxbytes = 30MB
stdout_logfile_backups = 2
redirect_stderr = true
Expand Down
Loading
Loading