Add support for pg18 and remove pg13

This commit is contained in:
inovindasari 2026-01-20 15:51:29 +01:00
parent b97de5d7f1
commit f7780d692a
32 changed files with 105 additions and 107 deletions

View File

@ -29,13 +29,13 @@ pipelines with no access to Kubernetes API directly, promoting infrastructure as
### PostgreSQL features
* Supports PostgreSQL 17, starting from 13+
* Supports PostgreSQL 18, starting from 14+
* Streaming replication cluster via Patroni
* Point-In-Time-Recovery with
[pg_basebackup](https://www.postgresql.org/docs/17/app-pgbasebackup.html) /
[pg_basebackup](https://www.postgresql.org/docs/18/app-pgbasebackup.html) /
[WAL-G](https://github.com/wal-g/wal-g) or [WAL-E](https://github.com/wal-e/wal-e) via [Spilo](https://github.com/zalando/spilo)
* Preload libraries: [bg_mon](https://github.com/CyberDem0n/bg_mon),
[pg_stat_statements](https://www.postgresql.org/docs/17/pgstatstatements.html),
[pg_stat_statements](https://www.postgresql.org/docs/18/pgstatstatements.html),
[pgextwlist](https://github.com/dimitri/pgextwlist),
[pg_auth_mon](https://github.com/RafiaSabih/pg_auth_mon)
* Incl. popular Postgres extensions such as

View File

@ -84,11 +84,11 @@ spec:
"limit_iops": 16000,
"limit_throughput": 1000,
"postgresql_versions": [
"18",
"17",
"16",
"15",
"14",
"13"
]
}
{{- if .Values.extraEnvs }}

View File

@ -68,7 +68,7 @@ spec:
type: string
docker_image:
type: string
default: "ghcr.io/zalando/spilo-17:4.0-p3"
default: "container-registry-test.zalando.net/acid/spilo-cdp-pr1156-18:4.1-p18"
enable_crd_registration:
type: boolean
default: true
@ -169,10 +169,10 @@ spec:
type: string
minimal_major_version:
type: string
default: "13"
default: "14"
target_major_version:
type: string
default: "17"
default: "18"
kubernetes:
type: object
properties:

View File

@ -374,11 +374,11 @@ spec:
version:
type: string
enum:
- "13"
- "14"
- "15"
- "16"
- "17"
- "18"
parameters:
type: object
additionalProperties:

View File

@ -31,14 +31,12 @@ configGeneral:
enable_pgversion_env_var: true
# start any new database pod without limitations on shm memory
enable_shm_volume: true
# enables backwards compatible path between Spilo 12 and Spilo 13+ images
enable_spilo_wal_path_compat: false
# operator will sync only clusters where name starts with teamId prefix
enable_team_id_clustername_prefix: false
# etcd connection string for Patroni. Empty uses K8s-native DCS.
etcd_host: ""
# Spilo docker image
docker_image: ghcr.io/zalando/spilo-17:4.0-p3
docker_image: container-registry-test.zalando.net/acid/spilo-cdp-pr1156-18:4.1-p18
# key name for annotation to ignore globally configured instance limits
# ignore_instance_limits_annotation_key: ""
@ -92,9 +90,9 @@ configMajorVersionUpgrade:
# - acid
# minimal Postgres major version that will not automatically be upgraded
minimal_major_version: "13"
minimal_major_version: "14"
# target Postgres major version when upgrading clusters automatically
target_major_version: "17"
target_major_version: "18"
configKubernetes:
# list of additional capabilities for postgres container

View File

@ -1312,7 +1312,7 @@ aws_or_gcp:
If cluster members have to be (re)initialized restoring physical backups
happens automatically either from the backup location or by running
[pg_basebackup](https://www.postgresql.org/docs/17/app-pgbasebackup.html)
[pg_basebackup](https://www.postgresql.org/docs/18/app-pgbasebackup.html)
on one of the other running instances (preferably replicas if they do not lag
behind). You can test restoring backups by [cloning](user.md#how-to-clone-an-existing-postgresql-cluster)
clusters.

View File

@ -647,7 +647,7 @@ the global configuration before adding the `tls` section'.
## Change data capture streams
This sections enables change data capture (CDC) streams via Postgres'
[logical decoding](https://www.postgresql.org/docs/17/logicaldecoding.html)
[logical decoding](https://www.postgresql.org/docs/18/logicaldecoding.html)
feature and `pgoutput` plugin. While the Postgres operator takes responsibility
for providing the setup to publish change events, it relies on external tools
to consume them. At Zalando, we are using a workflow based on
@ -680,7 +680,7 @@ can have the following properties:
The CDC operator is following the [outbox pattern](https://debezium.io/blog/2019/02/19/reliable-microservices-data-exchange-with-the-outbox-pattern/).
The application is responsible for putting events into a (JSON/B or VARCHAR)
payload column of the outbox table in the structure of the specified target
event type. The operator will create a [PUBLICATION](https://www.postgresql.org/docs/17/logical-replication-publication.html)
event type. The operator will create a [PUBLICATION](https://www.postgresql.org/docs/18/logical-replication-publication.html)
in Postgres for all tables specified for one `database` and `applicationId`.
The CDC operator will consume from it shortly after transactions are
committed to the outbox table. The `idColumn` will be used in telemetry for

View File

@ -260,12 +260,12 @@ CRD-configuration, they are grouped under the `major_version_upgrade` key.
* **minimal_major_version**
The minimal Postgres major version that will not automatically be upgraded
when `major_version_upgrade_mode` is set to `"full"`. The default is `"13"`.
when `major_version_upgrade_mode` is set to `"full"`. The default is `"14"`.
* **target_major_version**
The target Postgres major version when upgrading clusters automatically
which violate the configured allowed `minimal_major_version` when
`major_version_upgrade_mode` is set to `"full"`. The default is `"17"`.
`major_version_upgrade_mode` is set to `"full"`. The default is `"18"`.
## Kubernetes resources

View File

@ -30,7 +30,7 @@ spec:
databases:
foo: zalando
postgresql:
version: "17"
version: "18"
```
Once you cloned the Postgres Operator [repository](https://github.com/zalando/postgres-operator)
@ -109,7 +109,7 @@ metadata:
spec:
[...]
postgresql:
version: "17"
version: "18"
parameters:
password_encryption: scram-sha-256
```
@ -517,7 +517,7 @@ Postgres Operator will create the following NOLOGIN roles:
The `<dbname>_owner` role is the database owner and should be used when creating
new database objects. All members of the `admin` role, e.g. teams API roles, can
become the owner with the `SET ROLE` command. [Default privileges](https://www.postgresql.org/docs/17/sql-alterdefaultprivileges.html)
become the owner with the `SET ROLE` command. [Default privileges](https://www.postgresql.org/docs/18/sql-alterdefaultprivileges.html)
are configured for the owner role so that the `<dbname>_reader` role
automatically gets read-access (SELECT) to new tables and sequences and the
`<dbname>_writer` receives write-access (INSERT, UPDATE, DELETE on tables,
@ -594,7 +594,7 @@ spec:
### Schema `search_path` for default roles
The schema [`search_path`](https://www.postgresql.org/docs/17/ddl-schemas.html#DDL-SCHEMAS-PATH)
The schema [`search_path`](https://www.postgresql.org/docs/18/ddl-schemas.html#DDL-SCHEMAS-PATH)
for each role will include the role name and the schemas, this role should have
access to. So `foo_bar_writer` does not have to schema-qualify tables from
schemas `foo_bar_writer, bar`, while `foo_writer` can look up `foo_writer` and
@ -695,7 +695,7 @@ handle it.
### HugePages support
The operator supports [HugePages](https://www.postgresql.org/docs/17/kernel-resources.html#LINUX-HUGEPAGES).
The operator supports [HugePages](https://www.postgresql.org/docs/18/kernel-resources.html#LINUX-HUGEPAGES).
To enable HugePages, set the matching resource requests and/or limits in the manifest:
```yaml
@ -757,7 +757,7 @@ If you need to define a `nodeAffinity` for all your Postgres clusters use the
## In-place major version upgrade
Starting with Spilo 13, operator supports in-place major version upgrade to a
Starting with Spilo 14, operator supports in-place major version upgrade to a
higher major version (e.g. from PG 14 to PG 16). To trigger the upgrade,
simply increase the version in the manifest. It is your responsibility to test
your applications against the new version before the upgrade; downgrading is
@ -792,7 +792,7 @@ spec:
clone:
uid: "efd12e58-5786-11e8-b5a7-06148230260c"
cluster: "acid-minimal-cluster"
timestamp: "2017-12-19T12:40:33+01:00"
timestamp: "2025-12-19T12:40:33+01:00"
```
Here `cluster` is a name of a source cluster that is going to be cloned. A new
@ -827,7 +827,7 @@ spec:
clone:
uid: "efd12e58-5786-11e8-b5a7-06148230260c"
cluster: "acid-minimal-cluster"
timestamp: "2017-12-19T12:40:33+01:00"
timestamp: "2025-12-19T12:40:33+01:00"
s3_wal_path: "s3://custom/path/to/bucket"
s3_endpoint: https://s3.acme.org
s3_access_key_id: 0123456789abcdef0123456789abcdef
@ -838,7 +838,7 @@ spec:
### Clone directly
Another way to get a fresh copy of your source DB cluster is via
[pg_basebackup](https://www.postgresql.org/docs/17/app-pgbasebackup.html). To
[pg_basebackup](https://www.postgresql.org/docs/18/app-pgbasebackup.html). To
use this feature simply leave out the timestamp field from the clone section.
The operator will connect to the service of the source cluster by name. If the
cluster is called test, then the connection string will look like host=test

View File

@ -46,7 +46,7 @@ tools:
# install pinned version of 'kind'
# go install must run outside of a dir with a (module-based) Go project !
# otherwise go install updates project's dependencies and/or behaves differently
cd "/tmp" && GO111MODULE=on go install sigs.k8s.io/kind@v0.27.0
cd "/tmp" && GO111MODULE=on go install sigs.k8s.io/kind@v0.31.0
e2etest: tools copy clean
./run.sh main

View File

@ -8,7 +8,7 @@ IFS=$'\n\t'
readonly cluster_name="postgres-operator-e2e-tests"
readonly kubeconfig_path="/tmp/kind-config-${cluster_name}"
readonly spilo_image="registry.opensource.zalan.do/acid/spilo-17-e2e:0.3"
readonly spilo_image="container-registry-test.zalando.net/acid/spilo-cdp-pr1156-18:4.1-p18"
readonly e2e_test_runner_image="ghcr.io/zalando/postgres-operator-e2e-tests-runner:latest"
export GOPATH=${GOPATH-~/go}

View File

@ -12,9 +12,9 @@ from kubernetes import client
from tests.k8s_api import K8s
from kubernetes.client.rest import ApiException
SPILO_CURRENT = "registry.opensource.zalan.do/acid/spilo-17-e2e:0.3"
SPILO_LAZY = "registry.opensource.zalan.do/acid/spilo-17-e2e:0.4"
SPILO_FULL_IMAGE = "ghcr.io/zalando/spilo-17:4.0-p3"
SPILO_CURRENT = "container-registry-test.zalando.net/acid/spilo-cdp-pr1156-18:4.1-p18"
SPILO_LAZY = "container-registry-test.zalando.net/acid/spilo-cdp-pr1156-18:4.1-p19"
SPILO_FULL_IMAGE = "container-registry-test.zalando.net/acid/spilo-cdp-pr1156-18:4.1-p18"
def to_selector(labels):
return ",".join(["=".join(lbl) for lbl in labels.items()])
@ -1211,25 +1211,25 @@ class EndToEndTestCase(unittest.TestCase):
k8s.create_with_kubectl("manifests/minimal-postgres-lowest-version-manifest.yaml")
self.eventuallyEqual(lambda: k8s.count_running_pods(labels=cluster_label), 2, "No 2 pods running")
self.eventuallyEqual(lambda: k8s.get_operator_state(), {"0": "idle"}, "Operator does not get in sync")
self.eventuallyEqual(check_version, 13, "Version is not correct")
self.eventuallyEqual(check_version, 14, "Version is not correct")
master_nodes, _ = k8s.get_cluster_nodes(cluster_labels=cluster_label)
# should upgrade immediately
pg_patch_version_14 = {
pg_patch_version_higher_version = {
"spec": {
"postgresql": {
"version": "14"
"version": "15"
}
}
}
k8s.api.custom_objects_api.patch_namespaced_custom_object(
"acid.zalan.do", "v1", "default", "postgresqls", "acid-upgrade-test", pg_patch_version_14)
"acid.zalan.do", "v1", "default", "postgresqls", "acid-upgrade-test", pg_patch_version_higher_version)
self.eventuallyEqual(lambda: k8s.get_operator_state(), {"0": "idle"}, "Operator does not get in sync")
k8s.wait_for_pod_failover(master_nodes, 'spilo-role=replica,' + cluster_label)
k8s.wait_for_pod_start('spilo-role=master,' + cluster_label)
k8s.wait_for_pod_start('spilo-role=replica,' + cluster_label)
self.eventuallyEqual(check_version, 14, "Version should be upgraded from 13 to 14")
self.eventuallyEqual(check_version, 15, "Version should be upgraded from 14 to 15")
# check if annotation for last upgrade's success is set
annotations = get_annotations()
@ -1238,10 +1238,10 @@ class EndToEndTestCase(unittest.TestCase):
# should not upgrade because current time is not in maintenanceWindow
current_time = datetime.now()
maintenance_window_future = f"{(current_time+timedelta(minutes=60)).strftime('%H:%M')}-{(current_time+timedelta(minutes=120)).strftime('%H:%M')}"
pg_patch_version_15_outside_mw = {
pg_patch_version_higher_version_outside_mw = {
"spec": {
"postgresql": {
"version": "15"
"version": "16"
},
"maintenanceWindows": [
maintenance_window_future
@ -1249,23 +1249,23 @@ class EndToEndTestCase(unittest.TestCase):
}
}
k8s.api.custom_objects_api.patch_namespaced_custom_object(
"acid.zalan.do", "v1", "default", "postgresqls", "acid-upgrade-test", pg_patch_version_15_outside_mw)
"acid.zalan.do", "v1", "default", "postgresqls", "acid-upgrade-test", pg_patch_version_higher_version_outside_mw)
self.eventuallyEqual(lambda: k8s.get_operator_state(), {"0": "idle"}, "Operator does not get in sync")
# no pod replacement outside of the maintenance window
k8s.wait_for_pod_start('spilo-role=master,' + cluster_label)
k8s.wait_for_pod_start('spilo-role=replica,' + cluster_label)
self.eventuallyEqual(check_version, 14, "Version should not be upgraded")
self.eventuallyEqual(check_version, 15, "Version should not be upgraded")
second_annotations = get_annotations()
self.assertIsNone(second_annotations.get("last-major-upgrade-failure"), "Annotation for last upgrade's failure should not be set")
# change maintenanceWindows to current
maintenance_window_current = f"{(current_time-timedelta(minutes=30)).strftime('%H:%M')}-{(current_time+timedelta(minutes=30)).strftime('%H:%M')}"
pg_patch_version_15_in_mw = {
pg_patch_version_higher_version_in_mw = {
"spec": {
"postgresql": {
"version": "15"
"version": "16"
},
"maintenanceWindows": [
maintenance_window_current
@ -1274,13 +1274,13 @@ class EndToEndTestCase(unittest.TestCase):
}
k8s.api.custom_objects_api.patch_namespaced_custom_object(
"acid.zalan.do", "v1", "default", "postgresqls", "acid-upgrade-test", pg_patch_version_15_in_mw)
"acid.zalan.do", "v1", "default", "postgresqls", "acid-upgrade-test", pg_patch_version_higher_version_in_mw)
self.eventuallyEqual(lambda: k8s.get_operator_state(), {"0": "idle"}, "Operator does not get in sync")
k8s.wait_for_pod_failover(master_nodes, 'spilo-role=master,' + cluster_label)
k8s.wait_for_pod_start('spilo-role=master,' + cluster_label)
k8s.wait_for_pod_start('spilo-role=replica,' + cluster_label)
self.eventuallyEqual(check_version, 15, "Version should be upgraded from 14 to 15")
self.eventuallyEqual(check_version, 16, "Version should be upgraded from 15 to 16")
# check if annotation for last upgrade's success is updated after second upgrade
third_annotations = get_annotations()
@ -1288,7 +1288,7 @@ class EndToEndTestCase(unittest.TestCase):
self.assertNotEqual(annotations.get("last-major-upgrade-success"), third_annotations.get("last-major-upgrade-success"), "Annotation for last upgrade's success is not updated")
# test upgrade with failed upgrade annotation
pg_patch_version_17 = {
pg_patch_version_highest_version = {
"metadata": {
"annotations": {
"last-major-upgrade-failure": "2024-01-02T15:04:05Z"
@ -1296,28 +1296,28 @@ class EndToEndTestCase(unittest.TestCase):
},
"spec": {
"postgresql": {
"version": "17"
"version": "18"
},
},
}
k8s.api.custom_objects_api.patch_namespaced_custom_object(
"acid.zalan.do", "v1", "default", "postgresqls", "acid-upgrade-test", pg_patch_version_17)
"acid.zalan.do", "v1", "default", "postgresqls", "acid-upgrade-test", pg_patch_version_highest_version)
self.eventuallyEqual(lambda: k8s.get_operator_state(), {"0": "idle"}, "Operator does not get in sync")
k8s.wait_for_pod_failover(master_nodes, 'spilo-role=replica,' + cluster_label)
k8s.wait_for_pod_start('spilo-role=master,' + cluster_label)
k8s.wait_for_pod_start('spilo-role=replica,' + cluster_label)
self.eventuallyEqual(check_version, 15, "Version should not be upgraded because annotation for last upgrade's failure is set")
self.eventuallyEqual(check_version, 16, "Version should not be upgraded because annotation for last upgrade's failure is set")
# change the version back to 15 and should remove failure annotation
# change the version back to 16 and should remove failure annotation
k8s.api.custom_objects_api.patch_namespaced_custom_object(
"acid.zalan.do", "v1", "default", "postgresqls", "acid-upgrade-test", pg_patch_version_15_in_mw)
"acid.zalan.do", "v1", "default", "postgresqls", "acid-upgrade-test", pg_patch_version_higher_version_in_mw)
self.eventuallyEqual(lambda: k8s.get_operator_state(), {"0": "idle"}, "Operator does not get in sync")
k8s.wait_for_pod_start('spilo-role=master,' + cluster_label)
k8s.wait_for_pod_start('spilo-role=replica,' + cluster_label)
self.eventuallyEqual(check_version, 15, "Version should not be upgraded from 15")
self.eventuallyEqual(check_version, 16, "Version should not be upgraded from 16")
fourth_annotations = get_annotations()
self.assertIsNone(fourth_annotations.get("last-major-upgrade-failure"), "Annotation for last upgrade's failure is not removed")

View File

@ -25,11 +25,11 @@ RUN apt-get update \
&& curl --silent https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - \
&& apt-get update \
&& apt-get install --no-install-recommends -y \
postgresql-client-18 \
postgresql-client-17 \
postgresql-client-16 \
postgresql-client-15 \
postgresql-client-14 \
postgresql-client-13 \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*

View File

@ -10,7 +10,7 @@ metadata:
# "delete-date": "2020-08-31" # can only be deleted on that day if "delete-date "key is configured
# "delete-clustername": "acid-test-cluster" # can only be deleted when name matches if "delete-clustername" key is configured
spec:
dockerImage: ghcr.io/zalando/spilo-17:4.0-p3
dockerImage: container-registry-test.zalando.net/acid/spilo-cdp-pr1156-18:4.1-p18
teamId: "acid"
numberOfInstances: 2
users: # Application/Robot users
@ -48,7 +48,7 @@ spec:
defaultRoles: true
defaultUsers: false
postgresql:
version: "17"
version: "18"
parameters: # Expert section
shared_buffers: "32MB"
max_connections: "10"

View File

@ -34,7 +34,7 @@ data:
default_memory_request: 100Mi
# delete_annotation_date_key: delete-date
# delete_annotation_name_key: delete-clustername
docker_image: ghcr.io/zalando/spilo-17:4.0-p3
docker_image: container-registry-test.zalando.net/acid/spilo-cdp-pr1156-18:4.1-p18
# downscaler_annotations: "deployment-time,downscaler/*"
enable_admin_role_for_users: "true"
enable_crd_registration: "true"
@ -113,7 +113,7 @@ data:
min_cpu_limit: 250m
min_instances: "-1"
min_memory_limit: 250Mi
minimal_major_version: "13"
minimal_major_version: "14"
# node_readiness_label: "status:ready"
# node_readiness_label_merge: "OR"
oauth_token_secret_name: postgresql-operator
@ -163,7 +163,7 @@ data:
spilo_privileged: "false"
storage_resize_mode: "pvc"
super_username: postgres
target_major_version: "17"
target_major_version: "18"
team_admin_role: "admin"
team_api_role_configuration: "log_statement:all"
teams_api_url: http://fake-teams-api.default.svc.cluster.local

View File

@ -28,7 +28,7 @@ spec:
preparedDatabases:
bar: {}
postgresql:
version: "13"
version: "18"
sidecars:
- name: "exporter"
image: "quay.io/prometheuscommunity/postgres-exporter:v0.15.0"

View File

@ -17,4 +17,4 @@ spec:
preparedDatabases:
bar: {}
postgresql:
version: "13"
version: "14"

View File

@ -17,4 +17,4 @@ spec:
preparedDatabases:
bar: {}
postgresql:
version: "17"
version: "18"

View File

@ -66,7 +66,7 @@ spec:
type: string
docker_image:
type: string
default: "ghcr.io/zalando/spilo-17:4.0-p3"
default: "container-registry-test.zalando.net/acid/spilo-cdp-pr1156-18:4.1-p18"
enable_crd_registration:
type: boolean
default: true
@ -167,10 +167,10 @@ spec:
type: string
minimal_major_version:
type: string
default: "13"
default: "14"
target_major_version:
type: string
default: "17"
default: "18"
kubernetes:
type: object
properties:

View File

@ -3,7 +3,7 @@ kind: OperatorConfiguration
metadata:
name: postgresql-operator-default-configuration
configuration:
docker_image: ghcr.io/zalando/spilo-17:4.0-p3
docker_image: container-registry-test.zalando.net/acid/spilo-cdp-pr1156-18:4.1-p18
# enable_crd_registration: true
# crd_categories:
# - all
@ -40,8 +40,8 @@ configuration:
major_version_upgrade_mode: "manual"
# major_version_upgrade_team_allow_list:
# - acid
minimal_major_version: "13"
target_major_version: "17"
minimal_major_version: "14"
target_major_version: "18"
kubernetes:
# additional_pod_capabilities:
# - "SYS_NICE"

View File

@ -3523,11 +3523,11 @@ spec:
type: object
version:
enum:
- "13"
- "14"
- "15"
- "16"
- "17"
- "18"
type: string
required:
- version

View File

@ -8,7 +8,7 @@ spec:
size: 1Gi
numberOfInstances: 1
postgresql:
version: "17"
version: "18"
# Make this a standby cluster. You can specify s3_wal_path or gs_wal_path for WAL archive,
# standby_host for remote primary streaming, or combine standby_host with either WAL path.
# Note: s3_wal_path and gs_wal_path are mutually exclusive.

View File

@ -49,8 +49,8 @@ type PostgresUsersConfiguration struct {
type MajorVersionUpgradeConfiguration struct {
MajorVersionUpgradeMode string `json:"major_version_upgrade_mode" default:"manual"` // off - no actions, manual - manifest triggers action, full - manifest and minimal version violation trigger upgrade
MajorVersionUpgradeTeamAllowList []string `json:"major_version_upgrade_team_allow_list,omitempty"`
MinimalMajorVersion string `json:"minimal_major_version" default:"13"`
TargetMajorVersion string `json:"target_major_version" default:"17"`
MinimalMajorVersion string `json:"minimal_major_version" default:"14"`
TargetMajorVersion string `json:"target_major_version" default:"18"`
}
// KubernetesMetaConfiguration defines k8s conf required for all Postgres clusters and the operator itself

View File

@ -185,7 +185,7 @@ type AdditionalVolume struct {
// PostgresqlParam describes PostgreSQL version and pairs of configuration parameter name - values.
type PostgresqlParam struct {
// +kubebuilder:validation:Enum="13";"14";"15";"16";"17"
// +kubebuilder:validation:Enum="14";"15";"16";"17";"18"
PgVersion string `json:"version"`
Parameters map[string]string `json:"parameters,omitempty"`
}

View File

@ -219,7 +219,7 @@ var unmarshalCluster = []struct {
"127.0.0.1/32"
],
"postgresql": {
"version": "17",
"version": "18",
"parameters": {
"shared_buffers": "32MB",
"max_connections": "10",
@ -279,7 +279,7 @@ var unmarshalCluster = []struct {
},
Spec: PostgresSpec{
PostgresqlParam: PostgresqlParam{
PgVersion: "17",
PgVersion: "18",
Parameters: map[string]string{
"shared_buffers": "32MB",
"max_connections": "10",
@ -339,7 +339,7 @@ var unmarshalCluster = []struct {
},
Error: "",
},
marshal: []byte(`{"kind":"Postgresql","apiVersion":"acid.zalan.do/v1","metadata":{"name":"acid-testcluster1","creationTimestamp":null},"spec":{"postgresql":{"version":"17","parameters":{"log_statement":"all","max_connections":"10","shared_buffers":"32MB"}},"pod_priority_class_name":"spilo-pod-priority","volume":{"size":"5Gi","storageClass":"SSD", "subPath": "subdir"},"enableShmVolume":false,"patroni":{"initdb":{"data-checksums":"true","encoding":"UTF8","locale":"en_US.UTF-8"},"pg_hba":["hostssl all all 0.0.0.0/0 md5","host all all 0.0.0.0/0 md5"],"ttl":30,"loop_wait":10,"retry_timeout":10,"maximum_lag_on_failover":33554432,"slots":{"permanent_logical_1":{"database":"foo","plugin":"pgoutput","type":"logical"}}},"resources":{"requests":{"cpu":"10m","memory":"50Mi"},"limits":{"cpu":"300m","memory":"3000Mi"}},"teamId":"acid","allowedSourceRanges":["127.0.0.1/32"],"numberOfInstances":2,"users":{"zalando":["superuser","createdb"]},"maintenanceWindows":["Mon:01:00-06:00","Sat:00:00-04:00","05:00-05:15"],"clone":{"cluster":"acid-batman"}},"status":{"PostgresClusterStatus":""}}`),
marshal: []byte(`{"kind":"Postgresql","apiVersion":"acid.zalan.do/v1","metadata":{"name":"acid-testcluster1","creationTimestamp":null},"spec":{"postgresql":{"version":"18","parameters":{"log_statement":"all","max_connections":"10","shared_buffers":"32MB"}},"pod_priority_class_name":"spilo-pod-priority","volume":{"size":"5Gi","storageClass":"SSD", "subPath": "subdir"},"enableShmVolume":false,"patroni":{"initdb":{"data-checksums":"true","encoding":"UTF8","locale":"en_US.UTF-8"},"pg_hba":["hostssl all all 0.0.0.0/0 md5","host all all 0.0.0.0/0 md5"],"ttl":30,"loop_wait":10,"retry_timeout":10,"maximum_lag_on_failover":33554432,"slots":{"permanent_logical_1":{"database":"foo","plugin":"pgoutput","type":"logical"}}},"resources":{"requests":{"cpu":"10m","memory":"50Mi"},"limits":{"cpu":"300m","memory":"3000Mi"}},"teamId":"acid","allowedSourceRanges":["127.0.0.1/32"],"numberOfInstances":2,"users":{"zalando":["superuser","createdb"]},"maintenanceWindows":["Mon:01:00-06:00","Sat:00:00-04:00","05:00-05:15"],"clone":{"cluster":"acid-batman"}},"status":{"PostgresClusterStatus":""}}`),
err: nil},
{
about: "example with clone",
@ -404,7 +404,7 @@ var postgresqlList = []struct {
out PostgresqlList
err error
}{
{"expect success", []byte(`{"apiVersion":"v1","items":[{"apiVersion":"acid.zalan.do/v1","kind":"Postgresql","metadata":{"labels":{"team":"acid"},"name":"acid-testcluster42","namespace":"default","resourceVersion":"30446957","selfLink":"/apis/acid.zalan.do/v1/namespaces/default/postgresqls/acid-testcluster42","uid":"857cd208-33dc-11e7-b20a-0699041e4b03"},"spec":{"allowedSourceRanges":["185.85.220.0/22"],"numberOfInstances":1,"postgresql":{"version":"17"},"teamId":"acid","volume":{"size":"10Gi"}},"status":{"PostgresClusterStatus":"Running"}}],"kind":"List","metadata":{},"resourceVersion":"","selfLink":""}`),
{"expect success", []byte(`{"apiVersion":"v1","items":[{"apiVersion":"acid.zalan.do/v1","kind":"Postgresql","metadata":{"labels":{"team":"acid"},"name":"acid-testcluster42","namespace":"default","resourceVersion":"30446957","selfLink":"/apis/acid.zalan.do/v1/namespaces/default/postgresqls/acid-testcluster42","uid":"857cd208-33dc-11e7-b20a-0699041e4b03"},"spec":{"allowedSourceRanges":["185.85.220.0/22"],"numberOfInstances":1,"postgresql":{"version":"18"},"teamId":"acid","volume":{"size":"10Gi"}},"status":{"PostgresClusterStatus":"Running"}}],"kind":"List","metadata":{},"resourceVersion":"","selfLink":""}`),
PostgresqlList{
TypeMeta: metav1.TypeMeta{
Kind: "List",
@ -425,7 +425,7 @@ var postgresqlList = []struct {
},
Spec: PostgresSpec{
ClusterName: "testcluster42",
PostgresqlParam: PostgresqlParam{PgVersion: "17"},
PostgresqlParam: PostgresqlParam{PgVersion: "18"},
Volume: Volume{Size: "10Gi"},
TeamID: "acid",
AllowedSourceRanges: []string{"185.85.220.0/22"},

View File

@ -72,18 +72,18 @@ func TestGenerateSpiloJSONConfiguration(t *testing.T) {
}{
{
subtest: "Patroni default configuration",
pgParam: &acidv1.PostgresqlParam{PgVersion: "17"},
pgParam: &acidv1.PostgresqlParam{PgVersion: "18"},
patroni: &acidv1.Patroni{},
opConfig: &config.Config{
Auth: config.Auth{
PamRoleName: "zalandos",
},
},
result: `{"postgresql":{"bin_dir":"/usr/lib/postgresql/17/bin"},"bootstrap":{"initdb":[{"auth-host":"md5"},{"auth-local":"trust"}],"dcs":{}}}`,
result: `{"postgresql":{"bin_dir":"/usr/lib/postgresql/18/bin"},"bootstrap":{"initdb":[{"auth-host":"md5"},{"auth-local":"trust"}],"dcs":{}}}`,
},
{
subtest: "Patroni configured",
pgParam: &acidv1.PostgresqlParam{PgVersion: "17"},
pgParam: &acidv1.PostgresqlParam{PgVersion: "18"},
patroni: &acidv1.Patroni{
InitDB: map[string]string{
"encoding": "UTF8",
@ -102,38 +102,38 @@ func TestGenerateSpiloJSONConfiguration(t *testing.T) {
FailsafeMode: util.True(),
},
opConfig: &config.Config{},
result: `{"postgresql":{"bin_dir":"/usr/lib/postgresql/17/bin","pg_hba":["hostssl all all 0.0.0.0/0 md5","host all all 0.0.0.0/0 md5"]},"bootstrap":{"initdb":[{"auth-host":"md5"},{"auth-local":"trust"},"data-checksums",{"encoding":"UTF8"},{"locale":"en_US.UTF-8"}],"dcs":{"ttl":30,"loop_wait":10,"retry_timeout":10,"maximum_lag_on_failover":33554432,"synchronous_mode":true,"synchronous_mode_strict":true,"synchronous_node_count":1,"slots":{"permanent_logical_1":{"database":"foo","plugin":"pgoutput","type":"logical"}},"failsafe_mode":true}}}`,
result: `{"postgresql":{"bin_dir":"/usr/lib/postgresql/18/bin","pg_hba":["hostssl all all 0.0.0.0/0 md5","host all all 0.0.0.0/0 md5"]},"bootstrap":{"initdb":[{"auth-host":"md5"},{"auth-local":"trust"},"data-checksums",{"encoding":"UTF8"},{"locale":"en_US.UTF-8"}],"dcs":{"ttl":30,"loop_wait":10,"retry_timeout":10,"maximum_lag_on_failover":33554432,"synchronous_mode":true,"synchronous_mode_strict":true,"synchronous_node_count":1,"slots":{"permanent_logical_1":{"database":"foo","plugin":"pgoutput","type":"logical"}},"failsafe_mode":true}}}`,
},
{
subtest: "Patroni failsafe_mode configured globally",
pgParam: &acidv1.PostgresqlParam{PgVersion: "17"},
pgParam: &acidv1.PostgresqlParam{PgVersion: "18"},
patroni: &acidv1.Patroni{},
opConfig: &config.Config{
EnablePatroniFailsafeMode: util.True(),
},
result: `{"postgresql":{"bin_dir":"/usr/lib/postgresql/17/bin"},"bootstrap":{"initdb":[{"auth-host":"md5"},{"auth-local":"trust"}],"dcs":{"failsafe_mode":true}}}`,
result: `{"postgresql":{"bin_dir":"/usr/lib/postgresql/18/bin"},"bootstrap":{"initdb":[{"auth-host":"md5"},{"auth-local":"trust"}],"dcs":{"failsafe_mode":true}}}`,
},
{
subtest: "Patroni failsafe_mode configured globally, disabled for cluster",
pgParam: &acidv1.PostgresqlParam{PgVersion: "17"},
pgParam: &acidv1.PostgresqlParam{PgVersion: "18"},
patroni: &acidv1.Patroni{
FailsafeMode: util.False(),
},
opConfig: &config.Config{
EnablePatroniFailsafeMode: util.True(),
},
result: `{"postgresql":{"bin_dir":"/usr/lib/postgresql/17/bin"},"bootstrap":{"initdb":[{"auth-host":"md5"},{"auth-local":"trust"}],"dcs":{"failsafe_mode":false}}}`,
result: `{"postgresql":{"bin_dir":"/usr/lib/postgresql/18/bin"},"bootstrap":{"initdb":[{"auth-host":"md5"},{"auth-local":"trust"}],"dcs":{"failsafe_mode":false}}}`,
},
{
subtest: "Patroni failsafe_mode disabled globally, configured for cluster",
pgParam: &acidv1.PostgresqlParam{PgVersion: "17"},
pgParam: &acidv1.PostgresqlParam{PgVersion: "18"},
patroni: &acidv1.Patroni{
FailsafeMode: util.True(),
},
opConfig: &config.Config{
EnablePatroniFailsafeMode: util.False(),
},
result: `{"postgresql":{"bin_dir":"/usr/lib/postgresql/17/bin"},"bootstrap":{"initdb":[{"auth-host":"md5"},{"auth-local":"trust"}],"dcs":{"failsafe_mode":true}}}`,
result: `{"postgresql":{"bin_dir":"/usr/lib/postgresql/18/bin"},"bootstrap":{"initdb":[{"auth-host":"md5"},{"auth-local":"trust"}],"dcs":{"failsafe_mode":true}}}`,
},
}
for _, tt := range tests {
@ -164,15 +164,15 @@ func TestExtractPgVersionFromBinPath(t *testing.T) {
},
{
subTest: "test current bin path against hard coded template",
binPath: "/usr/lib/postgresql/17/bin",
binPath: "/usr/lib/postgresql/18/bin",
template: pgBinariesLocationTemplate,
expected: "17",
expected: "18",
},
{
subTest: "test alternative bin path against a matching template",
binPath: "/usr/pgsql-17/bin",
binPath: "/usr/pgsql-18/bin",
template: "/usr/pgsql-%v/bin",
expected: "17",
expected: "18",
},
}
@ -2188,7 +2188,7 @@ func TestSidecars(t *testing.T) {
spec = acidv1.PostgresSpec{
PostgresqlParam: acidv1.PostgresqlParam{
PgVersion: "17",
PgVersion: "18",
Parameters: map[string]string{
"max_connections": "100",
},
@ -2381,7 +2381,7 @@ func TestContainerValidation(t *testing.T) {
name: "init container without image",
spec: acidv1.PostgresSpec{
PostgresqlParam: acidv1.PostgresqlParam{
PgVersion: "17",
PgVersion: "18",
},
TeamID: "myapp",
NumberOfInstances: 1,
@ -2410,7 +2410,7 @@ func TestContainerValidation(t *testing.T) {
name: "sidecar without name",
spec: acidv1.PostgresSpec{
PostgresqlParam: acidv1.PostgresqlParam{
PgVersion: "17",
PgVersion: "18",
},
TeamID: "myapp",
NumberOfInstances: 1,
@ -2439,7 +2439,7 @@ func TestContainerValidation(t *testing.T) {
name: "sidecar without image",
spec: acidv1.PostgresSpec{
PostgresqlParam: acidv1.PostgresqlParam{
PgVersion: "17",
PgVersion: "18",
},
TeamID: "myapp",
NumberOfInstances: 1,
@ -2468,7 +2468,7 @@ func TestContainerValidation(t *testing.T) {
name: "valid containers pass validation",
spec: acidv1.PostgresSpec{
PostgresqlParam: acidv1.PostgresqlParam{
PgVersion: "17",
PgVersion: "18",
},
TeamID: "myapp",
NumberOfInstances: 1,

View File

@ -16,11 +16,11 @@ import (
// VersionMap Map of version numbers
var VersionMap = map[string]int{
"13": 130000,
"14": 140000,
"15": 150000,
"16": 160000,
"17": 170000,
"18": 180000,
}
const (
@ -44,7 +44,7 @@ func (c *Cluster) GetDesiredMajorVersionAsInt() int {
func (c *Cluster) GetDesiredMajorVersion() string {
if c.Config.OpConfig.MajorVersionUpgradeMode == "full" {
// e.g. current is 13, minimal is 13 allowing 13 to 17 clusters, everything below is upgraded
// e.g. current is 18, minimal is 18 allowing 18 to 18 clusters, everything below is upgraded
if IsBiggerPostgresVersion(c.Spec.PgVersion, c.Config.OpConfig.MinimalMajorVersion) {
c.logger.Infof("overwriting configured major version %s to %s", c.Spec.PgVersion, c.Config.OpConfig.TargetMajorVersion)
return c.Config.OpConfig.TargetMajorVersion

View File

@ -39,7 +39,7 @@ func (c *Controller) importConfigurationFromCRD(fromCRD *acidv1.OperatorConfigur
result.EnableTeamIdClusternamePrefix = fromCRD.EnableTeamIdClusternamePrefix
result.EtcdHost = fromCRD.EtcdHost
result.KubernetesUseConfigMaps = fromCRD.KubernetesUseConfigMaps
result.DockerImage = util.Coalesce(fromCRD.DockerImage, "ghcr.io/zalando/spilo-17:4.0-p3")
result.DockerImage = util.Coalesce(fromCRD.DockerImage, "container-registry-test.zalando.net/acid/spilo-cdp-pr1156-18:4.1-p18")
result.Workers = util.CoalesceUInt32(fromCRD.Workers, 8)
result.MinInstances = fromCRD.MinInstances
result.MaxInstances = fromCRD.MaxInstances
@ -63,8 +63,8 @@ func (c *Controller) importConfigurationFromCRD(fromCRD *acidv1.OperatorConfigur
// major version upgrade config
result.MajorVersionUpgradeMode = util.Coalesce(fromCRD.MajorVersionUpgrade.MajorVersionUpgradeMode, "manual")
result.MajorVersionUpgradeTeamAllowList = fromCRD.MajorVersionUpgrade.MajorVersionUpgradeTeamAllowList
result.MinimalMajorVersion = util.Coalesce(fromCRD.MajorVersionUpgrade.MinimalMajorVersion, "13")
result.TargetMajorVersion = util.Coalesce(fromCRD.MajorVersionUpgrade.TargetMajorVersion, "17")
result.MinimalMajorVersion = util.Coalesce(fromCRD.MajorVersionUpgrade.MinimalMajorVersion, "14")
result.TargetMajorVersion = util.Coalesce(fromCRD.MajorVersionUpgrade.TargetMajorVersion, "18")
// kubernetes config
result.EnableOwnerReferences = util.CoalesceBool(fromCRD.Kubernetes.EnableOwnerReferences, util.False())

View File

@ -177,7 +177,7 @@ type Config struct {
WatchedNamespace string `name:"watched_namespace"` // special values: "*" means 'watch all namespaces', the empty string "" means 'watch a namespace where operator is deployed to'
KubernetesUseConfigMaps bool `name:"kubernetes_use_configmaps" default:"false"`
EtcdHost string `name:"etcd_host" default:""` // special values: the empty string "" means Patroni will use K8s as a DCS
DockerImage string `name:"docker_image" default:"ghcr.io/zalando/spilo-17:4.0-p3"`
DockerImage string `name:"docker_image" default:"container-registry-test.zalando.net/acid/spilo-cdp-pr1156-18:4.1-p18"`
SidecarImages map[string]string `name:"sidecar_docker_images"` // deprecated in favour of SidecarContainers
SidecarContainers []v1.Container `name:"sidecars"`
PodServiceAccountName string `name:"pod_service_account_name" default:"postgres-pod"`
@ -248,8 +248,8 @@ type Config struct {
EnableTeamIdClusternamePrefix bool `name:"enable_team_id_clustername_prefix" default:"false"`
MajorVersionUpgradeMode string `name:"major_version_upgrade_mode" default:"manual"`
MajorVersionUpgradeTeamAllowList []string `name:"major_version_upgrade_team_allow_list" default:""`
MinimalMajorVersion string `name:"minimal_major_version" default:"13"`
TargetMajorVersion string `name:"target_major_version" default:"17"`
MinimalMajorVersion string `name:"minimal_major_version" default:"14"`
TargetMajorVersion string `name:"target_major_version" default:"18"`
PatroniAPICheckInterval time.Duration `name:"patroni_api_check_interval" default:"1s"`
PatroniAPICheckTimeout time.Duration `name:"patroni_api_check_timeout" default:"5s"`
EnablePatroniFailsafeMode *bool `name:"enable_patroni_failsafe_mode" default:"false"`

View File

@ -73,11 +73,11 @@ spec:
"limit_iops": 16000,
"limit_throughput": 1000,
"postgresql_versions": [
"18",
"17",
"16",
"15",
"14",
"13"
]
}
# Exemple of settings to make snapshot view working in the ui when using AWS

View File

@ -259,7 +259,7 @@ DEFAULT_UI_CONFIG = {
'users_visible': True,
'databases_visible': True,
'resources_visible': RESOURCES_VISIBLE,
'postgresql_versions': ['13', '14', '15', '16', '17'],
'postgresql_versions': ['14', '15', '16', '17', '18'],
'dns_format_string': '{0}.{1}',
'pgui_link': '',
'static_network_whitelist': {},

View File

@ -31,11 +31,11 @@ default_operator_ui_config='{
"limit_iops": 16000,
"limit_throughput": 1000,
"postgresql_versions": [
"18",
"17",
"16",
"15",
"14",
"13"
],
"static_network_whitelist": {
"localhost": ["172.0.0.1/32"]