Skip to content
Merged
Show file tree
Hide file tree
Changes from 36 commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
4e71d1b
Update PostgreSQL mount paths to /var/lib/pg with 16/main subdirectory
marceloneppel Dec 18, 2025
a6c7d52
fix(charm): robustly patch OCI health-check script on pebble-ready/_f…
marceloneppel Dec 19, 2025
aaa3e61
Merge remote-tracking branch 'origin/16/edge' into change-storage-mounts
marceloneppel Dec 19, 2025
0d47327
chore: fix linter warnings and apply ruff formatting
marceloneppel Dec 19, 2025
a1246d5
chore(tests): apply ruff formatting to integration tests
marceloneppel Dec 19, 2025
5660ce5
test(spread): disable upgrade integration tests
marceloneppel Dec 19, 2025
cdeebe7
tests: add PGDATA_PATH and use in integration tests
marceloneppel Dec 19, 2025
6e14e88
Merge remote-tracking branch 'origin/16/edge' into change-storage-mounts
marceloneppel Jan 19, 2026
f7ab91f
Merge remote-tracking branch 'origin/16/edge' into change-storage-mounts
marceloneppel Jan 20, 2026
370a799
Create data directory symlink (#1217)
marceloneppel Jan 22, 2026
d793491
Merge branch 'change-storage-mounts' of github.com:canonical/postgres…
marceloneppel Jan 23, 2026
2c4890b
Merge remote-tracking branch 'origin/16/edge' into change-storage-mounts
marceloneppel Jan 23, 2026
4fa7c7d
fix: use consistent symlink path for PostgreSQL data directory
marceloneppel Jan 26, 2026
56cd2c6
Merge remote-tracking branch 'origin/16/edge' into change-storage-mounts
marceloneppel Jan 26, 2026
a68366f
fix(async-replication): prevent system ID mismatch for standby replicas
marceloneppel Jan 28, 2026
13c9f57
style: improve code formatting in patroni and async_replication modules
marceloneppel Jan 28, 2026
5581a0f
fix(backups): use actual pgdata path instead of symlink for backup op…
marceloneppel Jan 28, 2026
15ffa03
Merge remote-tracking branch 'origin/16/edge' into change-storage-mounts
marceloneppel Jan 28, 2026
1827478
fix(tests): update clean-data-dir.sh paths and use safer deletion
marceloneppel Jan 28, 2026
4611869
fix(backup): clear all storage directories during restore for replica…
marceloneppel Jan 29, 2026
5e32c4b
refactor(charm): remove stale storage cleanup for replica initialization
marceloneppel Feb 2, 2026
7555a88
fix(charm): clear stale storage dirs before replica initialization
marceloneppel Feb 4, 2026
bd81195
fix(async-replication): check member_started before clearing pgdata o…
marceloneppel Feb 5, 2026
fa1588b
Merge remote-tracking branch 'origin/16/edge' into change-storage-mounts
marceloneppel Feb 6, 2026
acad692
fix: remove health check script patching workaround
marceloneppel Feb 9, 2026
f9c0cb5
fix(storage): ensure pgdata symlink is always recreated and stale dir…
marceloneppel Feb 10, 2026
735eca3
Merge remote-tracking branch 'origin/16/edge' into change-storage-mounts
marceloneppel Feb 10, 2026
ab1588b
fix: prevent pg_wal symlink breakage on replica startup
marceloneppel Feb 11, 2026
43124ba
refactor: replace hardcoded storage paths with named constants
marceloneppel Feb 11, 2026
536e85d
Merge remote-tracking branch 'origin/16/edge' into change-storage-mounts
marceloneppel Feb 11, 2026
0473417
docs: fix broken Juju 3.0 release notes URLs
marceloneppel Feb 11, 2026
24ccb4f
fix(metadata): update postgresql-image upstream source to canonical GHCR
marceloneppel Feb 12, 2026
12a116d
Merge remote-tracking branch 'origin/16/edge' into change-storage-mounts
marceloneppel Feb 12, 2026
6689a53
ci: restore renovate hint for postgresql oci-image resource
marceloneppel Feb 13, 2026
6d2a7ef
Update OCI image hash
marceloneppel Feb 17, 2026
aad1f80
Merge branch '16/edge' into change-storage-mounts
marceloneppel Feb 17, 2026
7f50e73
Merge branch '16/edge' into change-storage-mounts
marceloneppel Mar 3, 2026
5c36df8
Merge branch '16/edge' into change-storage-mounts
marceloneppel Mar 4, 2026
16b0af6
test: update integration tests to use CHARM_BASE_NOBLE
marceloneppel Mar 4, 2026
26f96b4
test: update HA tests to use CHARM_BASE_NOBLE and latest/edge channel
marceloneppel Mar 4, 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
2 changes: 1 addition & 1 deletion docs/explanation/juju.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ In the context of this documentation, the pertinent changes are as follows:
|`run`|`exec`|
|`run-action --wait`|`run`|

See the [Juju 3.0 release notes](https://documentation.ubuntu.com/juju/3.6/reference/juju/juju-roadmap-and-releases/#juju-3-0-0-22-oct-2022) for the comprehensive list of changes.
See the [Juju 3.0 release notes](https://documentation.ubuntu.com/juju/3.6/releasenotes/unsupported/juju_3.x.x/#juju-3-0) for the comprehensive list of changes.

Example substitutions:

Expand Down
2 changes: 1 addition & 1 deletion docs/explanation/logs.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ The naming convention of the Pgbackrest logs is `<model name>.patroni-<postgresq
2023-10-11 13:07:45.146 P00 INFO: expire command end: completed successfully (353ms)
root@pg-0:/# cat /var/log/pgbackrest/discourse.patroni-pg-backup.log
-------------------PROCESS START-------------------
2023-10-11 13:06:29.857 P00 INFO: backup command begin 2.47: --no-backup-standby --exec-id=843-b0d896e1 --log-level-console=debug --pg1-path=/var/lib/postgresql/data/pgdata --pg1-user=backup --repo1-path=/postgresql-test --repo1-retention-full=9999999 --repo1-s3-bucket=dragop-test-bucket --repo1-s3-endpoint=https://s3.eu-central-1.amazonaws.com --repo1-s3-key=<redacted> --repo1-s3-key-secret=<redacted> --repo1-s3-region=eu-central-1 --repo1-s3-uri-style=host --repo1-type=s3 --stanza=discourse.patroni-pg --start-fast --type=full
2023-10-11 13:06:29.857 P00 INFO: backup command begin 2.47: --no-backup-standby --exec-id=843-b0d896e1 --log-level-console=debug --pg1-path=/var/lib/pg/data/16/main --pg1-user=backup --repo1-path=/postgresql-test --repo1-retention-full=9999999 --repo1-s3-bucket=dragop-test-bucket --repo1-s3-endpoint=https://s3.eu-central-1.amazonaws.com --repo1-s3-key=<redacted> --repo1-s3-key-secret=<redacted> --repo1-s3-region=eu-central-1 --repo1-s3-uri-style=host --repo1-type=s3 --stanza=discourse.patroni-pg --start-fast --type=full
2023-10-11 13:06:30.869 P00 INFO: execute non-exclusive backup start: backup begins after the requested immediate checkpoint completes
2023-10-11 13:06:31.671 P00 INFO: backup start archive = 000000010000000000000004, lsn = 0/4000060
2023-10-11 13:06:31.671 P00 INFO: check archive for prior segment 000000010000000000000003
Expand Down
2 changes: 1 addition & 1 deletion docs/how-to/data-migration/migrate-data-via-pg-dump.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ Always test migration in a safe environment before performing it in production!

- **[Your application is compatible](/explanation/legacy-charm) with Charmed PostgreSQL K8s**
- A client machine with access to the deployed legacy charm
- `juju v.2.9` or later (check [Juju 3.0 Release Notes](https://documentation.ubuntu.com/juju/3.6/reference/juju/juju-roadmap-and-releases/#juju-3-0-0-22-oct-2022) for more information about key differences)
- `juju v.2.9` or later (check [Juju 3.0 Release Notes](https://documentation.ubuntu.com/juju/3.6/releasenotes/unsupported/juju_3.x.x/#juju-3-0) for more information about key differences)
- Enough storage in the cluster to support backup/restore of the databases.

## Obtain existing database credentials
Expand Down
4 changes: 2 additions & 2 deletions docs/reference/troubleshooting.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,9 @@ postgresql enabled active today at 12:29 UTC
root@postgresql-k8s-0:/# ps auxww
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.0 718264 10916 ? Ssl 12:29 0:00 /charm/bin/pebble run --create-dirs --hold --http :38813 --verbose
postgres 14 0.1 0.1 565020 39412 ? Sl 12:29 0:01 python3 /usr/bin/patroni /var/lib/postgresql/data/patroni.yml
postgres 14 0.1 0.1 565020 39412 ? Sl 12:29 0:01 python3 /usr/bin/patroni /var/lib/pg/data/patroni.yml
postgres 30 0.0 0.0 1082704 9076 ? Sl 12:30 0:00 /usr/bin/prometheus-postgres-exporter
postgres 48 0.0 0.0 215488 28912 ? S 12:30 0:00 /usr/lib/postgresql/14/bin/postgres -D /var/lib/postgresql/data/pgdata --config-file=/var/lib/postgresql/data/pgdata/postgresql.conf --listen_addresses=0.0.0.0 --port=5432 --cluster_name=patroni-postgresql-k8s --wal_level=logical --hot_standby=on --max_connections=100 --max_wal_senders=10 --max_prepared_transactions=0 --max_locks_per_transaction=64 --track_commit_timestamp=off --max_replication_slots=10 --max_worker_processes=8 --wal_log_hints=on
postgres 48 0.0 0.0 215488 28912 ? S 12:30 0:00 /usr/lib/postgresql/16/bin/postgres -D /var/lib/pg/data/16/main --config-file=/var/lib/pg/data/16/main/postgresql.conf --listen_addresses=0.0.0.0 --port=5432 --cluster_name=patroni-postgresql-k8s --wal_level=logical --hot_standby=on --max_connections=100 --max_wal_senders=10 --max_prepared_transactions=0 --max_locks_per_transaction=64 --track_commit_timestamp=off --max_replication_slots=10 --max_worker_processes=8 --wal_log_hints=on
postgres 50 0.0 0.0 70080 7488 ? Ss 12:30 0:00 postgres: patroni-postgresql-k8s: logger
postgres 52 0.0 0.0 215592 9136 ? Ss 12:30 0:00 postgres: patroni-postgresql-k8s: checkpointer
postgres 53 0.0 0.0 215604 9632 ? Ss 12:30 0:00 postgres: patroni-postgresql-k8s: background writer
Expand Down
18 changes: 9 additions & 9 deletions metadata.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,19 @@ containers:
resource: postgresql-image
mounts:
- storage: archive
location: /var/lib/postgresql/archive
location: /var/lib/pg/archive
- storage: data
location: /var/lib/postgresql/data
location: /var/lib/pg/data
- storage: logs
location: /var/lib/postgresql/logs
location: /var/lib/pg/logs
- storage: temp
location: /var/lib/postgresql/temp
location: /var/lib/pg/temp

resources:
postgresql-image:
type: oci-image
description: OCI image for PostgreSQL
upstream-source: ghcr.io/canonical/charmed-postgresql@sha256:fcb648db2c418403fbf5f58f04892c4677f113526097ca7314cbd9f527bb1baf # renovate: oci-image tag: 16.11-24.04_edge
upstream-source: ghcr.io/canonical/charmed-postgresql@sha256:840100acce8597fe94f1ba5a4d8599a50d4acc9b351d9ec146d9ebb6099e5aa9 # renovate: oci-image tag: 16.11-24.04_edge

peers:
database-peers:
Expand Down Expand Up @@ -109,19 +109,19 @@ storage:
archive:
type: filesystem
description: Storage mount used for holding local backups (before typically sending them to remote object storage) when relevant/needed.
location: /var/lib/postgresql/archive
location: /var/lib/pg/archive
data:
type: filesystem
description: Storage mount used for storing all tables, indexes, and so on (except those from temporary tablespaces).
location: /var/lib/postgresql/data
location: /var/lib/pg/data
logs:
type: filesystem
description: Storage mount used for storing all the logs that are part of the transactional commit path (WAL files).
location: /var/lib/postgresql/logs
location: /var/lib/pg/logs
temp:
type: filesystem
description: Storage mount used for storing temporary tablespaces (where typically sort operations happen).
location: /var/lib/postgresql/temp
location: /var/lib/pg/temp

assumes:
- k8s-api
Expand Down
2 changes: 1 addition & 1 deletion scripts/authorisation_rules_observer.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
PATRONI_CLUSTER_STATUS_ENDPOINT = "cluster"
PATRONI_CONFIG_STATUS_ENDPOINT = "config"
TLS_CA_BUNDLE_FILE = "peer_ca_bundle.pem"
PATRONI_CONF_FILE_PATH = "/var/lib/postgresql/data/patroni.yml"
PATRONI_CONF_FILE_PATH = "/var/lib/pg/data/patroni.yml"

# File path for the spawned cluster topology observer process to write logs.
LOG_FILE_PATH = "/var/log/authorisation_rules_observer.log"
Expand Down
38 changes: 27 additions & 11 deletions src/backups.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,13 @@
from tenacity import RetryError, Retrying, stop_after_attempt, wait_fixed

from constants import (
ARCHIVE_PATH,
BACKUP_TYPE_OVERRIDES,
BACKUP_USER,
LOGS_STORAGE_PATH,
PGBACKREST_LOGROTATE_FILE,
POSTGRESQL_DATA_PATH,
TEMP_STORAGE_PATH,
WORKLOAD_OS_GROUP,
WORKLOAD_OS_USER,
)
Expand Down Expand Up @@ -195,7 +199,7 @@ def can_use_s3_repository(self) -> tuple[bool, str]:

system_identifier_from_instance, error = self._execute_command([
f"/usr/lib/postgresql/{self.charm._patroni.rock_postgresql_version.split('.')[0]}/bin/pg_controldata",
"/var/lib/postgresql/data/pgdata",
POSTGRESQL_DATA_PATH,
])
if error != "":
raise Exception(error)
Expand Down Expand Up @@ -272,15 +276,24 @@ def _create_bucket_if_not_exists(self) -> None:

def _empty_data_files(self) -> None:
"""Empty the PostgreSQL data directory in preparation of backup restore."""
try:
self.container.exec(["rm", "-r", "/var/lib/postgresql/data/pgdata"]).wait_output()
except ExecError as e:
# If previous PITR restore was unsuccessful, there is no such directory.
if "No such file or directory" not in str(e.stderr):
logger.exception(
"Failed to empty data directory in prep for backup restore", exc_info=e
)
raise
# Clear all storage directories, not just data. The logs directory must be cleared
# so that when new replicas join after restore, pg_basebackup can use the --waldir
# option (which requires an empty directory).
for path in [
ARCHIVE_PATH,
self.charm._actual_pgdata_path,
LOGS_STORAGE_PATH,
TEMP_STORAGE_PATH,
]:
try:
self.container.exec(["find", path, "-mindepth", "1", "-delete"]).wait_output()
except ExecError as e:
# If previous PITR restore was unsuccessful, there may be no such directory.
if "No such file or directory" not in str(e.stderr):
logger.exception(
f"Failed to empty {path} in prep for backup restore", exc_info=e
)
raise

def _change_connectivity_to_database(self, connectivity: bool) -> None:
"""Enable or disable the connectivity to the database."""
Expand Down Expand Up @@ -1212,6 +1225,7 @@ def _render_pgbackrest_conf_file(self) -> bool:
secret_key=s3_parameters["secret-key"],
stanza=self.stanza_name,
storage_path=self.charm._storage_path,
pgdata_path=POSTGRESQL_DATA_PATH,
user=BACKUP_USER,
retention_full=s3_parameters["delete-older-than-days"],
process_max=max(cpu_count - 2, 1),
Expand All @@ -1234,7 +1248,9 @@ def _render_pgbackrest_conf_file(self) -> bool:
"/home/postgres/rotate_logs.py",
f.read(),
)
self.container.start(self.charm.rotate_logs_service)
services = self.container.pebble.get_services(names=[self.charm.rotate_logs_service])
if services:
self.container.start(self.charm.rotate_logs_service)

return True

Expand Down
Loading
Loading