diff --git a/product_docs/docs/postgres_for_kubernetes/1/backup.mdx b/product_docs/docs/postgres_for_kubernetes/1/backup.mdx index e2841a02e1..d9e9914fb0 100644 --- a/product_docs/docs/postgres_for_kubernetes/1/backup.mdx +++ b/product_docs/docs/postgres_for_kubernetes/1/backup.mdx @@ -241,6 +241,13 @@ The schedule `"0 0 0 * * *"` triggers a backup every day at midnight (00:00:00). In Kubernetes CronJobs, the equivalent expression would be `0 0 * * *`, since seconds are not supported. +!!!warning + +The `spec.cluster` field is immutable after creation. To schedule backups +for a different `Cluster`, create a new `ScheduledBackup` resource instead +of updating an existing one. +!!! + ### Backup Frequency and RTO !!!tip Hint diff --git a/product_docs/docs/postgres_for_kubernetes/1/bootstrap.mdx b/product_docs/docs/postgres_for_kubernetes/1/bootstrap.mdx index dd7335e222..8112f82c19 100644 --- a/product_docs/docs/postgres_for_kubernetes/1/bootstrap.mdx +++ b/product_docs/docs/postgres_for_kubernetes/1/bootstrap.mdx @@ -388,6 +388,17 @@ cluster. An error in any of those queries will interrupt the bootstrap phase, leaving the cluster incomplete and requiring manual intervention. !!! +!!!note + +These queries run with the standard `"$user", public` `search_path`, even +though operator-issued connections otherwise pin a fixed `search_path` for +security reasons. +See [Schema resolution and `search_path` hardening](security.md#schema-resolution-and-search_path-hardening) +for details. +Schema-qualify object references if you need them to be independent of the +`search_path`. +!!! + !!!info Important Ensure the existence of entries inside the ConfigMaps or Secrets specified in `postInitSQLRefs`, `postInitTemplateSQLRefs`, and @@ -647,7 +658,7 @@ file on the source PostgreSQL instance: host replication streaming_replica all md5 ``` -The following manifest creates a new PostgreSQL 18.3 cluster, +The following manifest creates a new PostgreSQL 18.4 cluster, called `target-db`, using the `pg_basebackup` bootstrap method to clone an external PostgreSQL cluster defined as `source-db` (in the `externalClusters` array). As you can see, the `source-db` @@ -662,7 +673,7 @@ metadata: name: target-db spec: instances: 3 - imageName: docker.enterprisedb.com/k8s/postgresql:18.3-standard-ubi9 + imageName: docker.enterprisedb.com/k8s/postgresql:18.4-standard-ubi9 bootstrap: pg_basebackup: @@ -682,7 +693,7 @@ spec: ``` All the requirements must be met for the clone operation to work, including -the same PostgreSQL version (in our case 18.3). +the same PostgreSQL version (in our case 18.4). #### TLS certificate authentication @@ -698,7 +709,7 @@ This example can be easily adapted to cover an instance that resides outside the Kubernetes cluster. !!! -The manifest defines a new PostgreSQL 18.3 cluster called `cluster-clone-tls`, +The manifest defines a new PostgreSQL 18.4 cluster called `cluster-clone-tls`, which is bootstrapped using the `pg_basebackup` method from the `cluster-example` external cluster. The host is identified by the read/write service in the same cluster, while the `streaming_replica` user is authenticated @@ -713,7 +724,7 @@ metadata: name: cluster-clone-tls spec: instances: 3 - imageName: docker.enterprisedb.com/k8s/postgresql:18.3-standard-ubi9 + imageName: docker.enterprisedb.com/k8s/postgresql:18.4-standard-ubi9 bootstrap: pg_basebackup: diff --git a/product_docs/docs/postgres_for_kubernetes/1/certificates.mdx b/product_docs/docs/postgres_for_kubernetes/1/certificates.mdx index eaa65afcfc..aaad7b4ec9 100644 --- a/product_docs/docs/postgres_for_kubernetes/1/certificates.mdx +++ b/product_docs/docs/postgres_for_kubernetes/1/certificates.mdx @@ -39,6 +39,15 @@ names in user-provided certificates for the `-rw` service used for communication within the cluster. !!! +!!!note + +Beyond the CA-managed certificates listed above, the operator also uses a +self-signed client certificate, generated in memory, to authenticate to the +instance manager's status port. This certificate is not signed by the client +CA: the instance manager trusts it by pinning its public-key fingerprint. See +[Operator-to-instance authentication](security.md#operator-to-instance-authentication). +!!! + ## Operator-Managed Mode By default, the operator automatically generates a single Certificate Authority diff --git a/product_docs/docs/postgres_for_kubernetes/1/cnpg_i.mdx b/product_docs/docs/postgres_for_kubernetes/1/cnpg_i.mdx index f90cca9350..b4b717f458 100644 --- a/product_docs/docs/postgres_for_kubernetes/1/cnpg_i.mdx +++ b/product_docs/docs/postgres_for_kubernetes/1/cnpg_i.mdx @@ -92,6 +92,12 @@ TCP gRPC endpoint behind a Service, with **mTLS** for secure communication. Standalone plugins are discovered dynamically by watching for Services with the required labels and annotations — no operator restart is needed. +When a standalone plugin's pods are rolled (for example, after upgrading its +image), the operator detects the change through the EndpointSlices backing the +plugin Service and reconciles every cluster using that plugin, so they start +interacting with the new pods promptly instead of waiting for the periodic +resync. + Example Deployment: ```yaml diff --git a/product_docs/docs/postgres_for_kubernetes/1/connection_pooling.mdx b/product_docs/docs/postgres_for_kubernetes/1/connection_pooling.mdx index 6c9cdd3d46..5f34f7a8db 100644 --- a/product_docs/docs/postgres_for_kubernetes/1/connection_pooling.mdx +++ b/product_docs/docs/postgres_for_kubernetes/1/connection_pooling.mdx @@ -57,6 +57,13 @@ spec: The pooler name can't be the same as any cluster name in the same namespace. !!! +!!!warning + +The `spec.cluster` field is immutable after creation. To point a pooler at +a different `Cluster`, create a new `Pooler` resource instead of updating +an existing one. +!!! + This example creates a `Pooler` resource called `pooler-example-rw` that's strictly associated with the Postgres `Cluster` resource called `cluster-example`. It points to the primary, identified by the read/write @@ -190,15 +197,27 @@ GRANT CONNECT ON DATABASE postgres TO cnp_pooler_pgbouncer; Create the lookup function for password verification. This function is created in the `postgres` database with `SECURITY DEFINER` privileges and is used by -PgBouncer’s `auth_query` option: +PgBouncer’s `auth_query` option. Because it runs as the function owner, its +`search_path` is pinned to `pg_catalog, pg_temp` so that the function body +cannot resolve operators or objects through a caller- or +tenant-controlled `search_path`: ```sql CREATE OR REPLACE FUNCTION public.user_search(uname TEXT) RETURNS TABLE (usename name, passwd text) - LANGUAGE sql SECURITY DEFINER AS + LANGUAGE sql SECURITY DEFINER + SET search_path = pg_catalog, pg_temp AS 'SELECT usename, passwd FROM pg_catalog.pg_shadow WHERE usename=$1;'; ``` +!!!note + +Clusters created with an earlier version of {{name.ln}} carry a +`user_search` function without the pinned `search_path`. The operator +recreates the function with the `SET search_path` clause automatically +during reconciliation when the cluster is upgraded. +!!! + Restrict and grant permissions on the lookup function: ```sql @@ -280,10 +299,89 @@ spec: topologyKey: "kubernetes.io/hostname" ``` -#### Custom image and resource limits +#### Resource limits + +You can define resource requests and limits by adding a container named +`pgbouncer` to the `template` section: + +```yaml +# ... + template: + metadata: + # ... + spec: + containers: + # This name MUST be "pgbouncer" + - name: pgbouncer + resources: + requests: + cpu: "0.1" + memory: 100Mi + limits: + cpu: "0.5" + memory: 500Mi +``` + +## PgBouncer image + +By default, {{name.ln}} deploys the +[latest stable PgBouncer image](https://docker.enterprisedb.com/k8s/pgbouncer) +the operator was built against. You can override that default in three ways. +When more than one is set, the sources are evaluated top-down — the first +match in the list below is used; if none match, the operator's built-in +default applies: + +1. An explicit image set on the `pgbouncer` container inside + `spec.template.spec.containers` (escape hatch — see + [Pod-template override](#pod-template-override) below). +2. `spec.pgbouncer.image` — an image reference set directly on the `Pooler`. +3. `spec.pgbouncer.imageCatalogRef` — a reference to an entry in an + `ImageCatalog` or `ClusterImageCatalog`. + +`spec.pgbouncer.image` and `spec.pgbouncer.imageCatalogRef` are mutually +exclusive — set at most one. + +!!!warning Policy gating + +If you enforce admission policies that restrict which PgBouncer images +may run, those policies **must gate all three** image sources: +`spec.pgbouncer.image`, `spec.pgbouncer.imageCatalogRef`, and the +`image` field on a `pgbouncer` container inside +`spec.template.spec.containers`. A policy that covers only the first +two leaves the pod-template override as an unguarded escape hatch. +The same consideration applies to `Cluster.spec.imageName` and +`Cluster.spec.imageCatalogRef`. +!!! + +### Setting an explicit image + +Use `spec.pgbouncer.image` to pin a specific PgBouncer version or pull from +a private registry: + +```yaml +apiVersion: postgresql.k8s.enterprisedb.io/v1 +kind: Pooler +metadata: + name: pooler-example-rw +spec: + cluster: + name: cluster-example + instances: 3 + type: rw + pgbouncer: + poolMode: session + image: docker.enterprisedb.com/k8s/pgbouncer:1.25.1-ubi9 +``` + +### Using an image catalog -You can specify a custom image and define resource requests/limits. Note that -the container name is explicitly set to `pgbouncer`. +The `Pooler` resource can manage the PgBouncer container image centrally via +an `ImageCatalog` or `ClusterImageCatalog`, following the same pattern as +`Cluster` resources (see [Image Catalog](image_catalog.md)). The catalog +entry is selected by the `key` defined in the catalog's `componentImages` +list. + +Reference a catalog entry with `spec.pgbouncer.imageCatalogRef`: ```yaml apiVersion: postgresql.k8s.enterprisedb.io/v1 @@ -295,29 +393,68 @@ spec: name: cluster-example instances: 3 type: rw + pgbouncer: + poolMode: session + imageCatalogRef: + apiGroup: postgresql.k8s.enterprisedb.io + kind: ImageCatalog + name: my-catalog + key: pgbouncer +``` + +To use a cluster-wide catalog instead, set `kind: ClusterImageCatalog` and +point `name` at the corresponding resource — the rest of the spec is +identical. + +When a catalog entry is updated, the operator automatically reconciles all +poolers referencing it and rolls out the new image without any change to the +`Pooler` spec. +### Pod-template override + +The pod template can also carry an `image` on the `pgbouncer` container, in +which case it overrides every other source (including `spec.pgbouncer.image` +and `spec.pgbouncer.imageCatalogRef`). Treat this as an **escape hatch** — +use it only when you need to customize other container-level settings +(resources, environment, security context) and happen to want to pin the +image in the same place. For routine image changes, prefer +`spec.pgbouncer.image` or an image catalog: those fields are validated, +mutually exclusive, and visible to admission policies that gate the +PgBouncer image (see [Pod templates](#pod-templates) for the broader +template mechanics): + +```yaml +# ... template: - metadata: - labels: - app: pooler spec: containers: - # This name MUST be "pgbouncer" - name: pgbouncer image: my-pgbouncer:latest - resources: - requests: - cpu: "0.1" - memory: 100Mi - limits: - cpu: "0.5" - memory: 500Mi ``` +### Monitoring the resolved image + +The operator stores the resolved image in `status.image` and reflects the +outcome in `status.phase`, one of `active`, `paused`, `inactive`, or +`failed`. On `failed`, `status.phaseReason` describes the cause (for +example, if the catalog or key does not exist). You can inspect the +current state with: + +```shell +kubectl get pooler pooler-example-rw -o jsonpath='{.status.image}' +``` + +!!!note API reference + +For details, see [`PgBouncerSpec`](pg4k.v1.md#pgbouncerspec) +in the API reference. +!!! + ## Service Template -Sometimes, your pooler will require some different labels, annotations, or even change -the type of the service, you can achieve that by using the `serviceTemplate` field: +Sometimes, your pooler will require some different labels, annotations, or +even a different Service type. You can achieve that by using the +`serviceTemplate` field: ```yaml apiVersion: postgresql.k8s.enterprisedb.io/v1 @@ -668,6 +805,42 @@ spec: - port: metrics ``` +### TLS for the Metrics Endpoint + +Set `.spec.monitoring.tls.enabled: true` to serve the metrics endpoint over +HTTPS. By default, the cluster's server certificate is being used. +The certificate is reloaded on every TLS handshake, so rotations are +picked up without restarting the pod. + +```yaml +spec: + monitoring: + tls: + enabled: true +``` + +When `.spec.pgbouncer.clientTLSSecret` is set, the metrics server presents +that certificate instead. + +```yaml +spec: + pgbouncer: + clientTLSSecret: + name: + monitoring: + tls: + enabled: true +``` + +The generated `PodMonitor` scrapes with `insecureSkipVerify=true` because +Prometheus scrapes pods by IP and the certificate's SANs do not generally +cover the pod IP. + +If you need strict verification, set `.spec.monitoring.enablePodMonitor: false` +and manage the `PodMonitor` yourself: the operator-generated one is hardcoded +to `insecureSkipVerify=true` and overwrites its spec on every reconcile, so a +manual patch on the generated `PodMonitor` would not survive. + ### Deprecation of Automatic `PodMonitor` Creation !!!warning Feature Deprecation Notice @@ -704,7 +877,7 @@ following example: ## Pausing connections The `Pooler` specification allows you to take advantage of PgBouncer's `PAUSE` -and `RESUME` commands, using only declarative configuration. You can ado this +and `RESUME` commands, using only declarative configuration. You can do this using the `paused` option, which by default is set to `false`. When set to `true`, the operator internally invokes the `PAUSE` command in PgBouncer, which: diff --git a/product_docs/docs/postgres_for_kubernetes/1/database_import.mdx b/product_docs/docs/postgres_for_kubernetes/1/database_import.mdx index 9c8c91b064..ff8fa24e84 100644 --- a/product_docs/docs/postgres_for_kubernetes/1/database_import.mdx +++ b/product_docs/docs/postgres_for_kubernetes/1/database_import.mdx @@ -22,8 +22,8 @@ As a result, the instructions in this section are suitable for both: - importing one or more databases from an existing PostgreSQL instance, even outside Kubernetes - importing the database from any PostgreSQL version to one that is either the - same or newer, enabling *major upgrades* of PostgreSQL (e.g. from version 13.x - to version 17.x) + same or newer, enabling *major upgrades* of PostgreSQL (e.g. from version 14.x + to version 18.x) !!!warning When performing major upgrades of PostgreSQL you are responsible for making diff --git a/product_docs/docs/postgres_for_kubernetes/1/declarative_database_management.mdx b/product_docs/docs/postgres_for_kubernetes/1/declarative_database_management.mdx index eef8fc3f08..c9dc0e502f 100644 --- a/product_docs/docs/postgres_for_kubernetes/1/declarative_database_management.mdx +++ b/product_docs/docs/postgres_for_kubernetes/1/declarative_database_management.mdx @@ -69,6 +69,13 @@ The `Database` object must reference a specific `Cluster`, determining where the database will be created. It is managed by the cluster's primary instance, ensuring the database is created or updated as needed. +!!!warning + +The `spec.cluster` field is immutable after creation. To target a +different `Cluster`, create a new `Database` resource instead of updating +an existing one. +!!! + !!!info The distinction between `metadata.name` and `spec.name` allows multiple `Database` resources to reference databases with the same name across different @@ -148,6 +155,11 @@ spec: Deleting this `Database` object will automatically remove the `two` database from the `cluster-example` cluster. +On a replica cluster the database is read-only, so deleting a `Database` object +releases its finalizer and removes the Kubernetes object without dropping the +PostgreSQL database, even with `databaseReclaimPolicy: delete`. Dropping the +database is left to the primary cluster, which owns it. + ### Declaratively Setting `ensure: absent` To remove a database, set the `ensure` field to `absent` like in the following diff --git a/product_docs/docs/postgres_for_kubernetes/1/declarative_hibernation.mdx b/product_docs/docs/postgres_for_kubernetes/1/declarative_hibernation.mdx index 49e9ce75f4..bd8d1e0a0a 100644 --- a/product_docs/docs/postgres_for_kubernetes/1/declarative_hibernation.mdx +++ b/product_docs/docs/postgres_for_kubernetes/1/declarative_hibernation.mdx @@ -55,7 +55,7 @@ $ kubectl cnp status Cluster Summary Name: cluster-example Namespace: default -PostgreSQL Image: docker.enterprisedb.com/k8s/postgresql:18.3-standard-ubi9 +PostgreSQL Image: docker.enterprisedb.com/k8s/postgresql:18.4-standard-ubi9 Primary instance: cluster-example-2 Status: Cluster in healthy state Instances: 3 diff --git a/product_docs/docs/postgres_for_kubernetes/1/declarative_role_management.mdx b/product_docs/docs/postgres_for_kubernetes/1/declarative_role_management.mdx index f4a04abeb3..70ad12a065 100644 --- a/product_docs/docs/postgres_for_kubernetes/1/declarative_role_management.mdx +++ b/product_docs/docs/postgres_for_kubernetes/1/declarative_role_management.mdx @@ -5,6 +5,8 @@ originalFilePath: 'src/declarative_role_management.md' +!!!info + From its inception, {{name.ln}} has managed the creation of specific roles required in PostgreSQL instances: @@ -13,13 +15,335 @@ required in PostgreSQL instances: - The application user, set as the low-privilege owner of the application database This process is described in the ["Bootstrap"](bootstrap.md) section. +!!! + +{{name.ln}} provides full lifecycle management for PostgreSQL database roles. +You can define roles either: + +1. as [standalone `DatabaseRole` resources](#the-databaserole-resource) (recommended), or +2. via [the `managed` stanza within the `Cluster` spec](#inline-managed-roles). + +## Coexistence and precedence + +The two methods are not mutually exclusive: you can manage different roles with +each one at the same time, which is what makes a gradual migration from the +inline stanza to `DatabaseRole` resources possible. They only need a rule for +the case where the same role name is defined in both places. + +In that case, **the Cluster specification (`managed.roles`) always takes +precedence**: the `DatabaseRole` is not reconciled and reports the conflict in +its status (see [Status of `DatabaseRole` resources](#status-of-databaserole-resources)). + +!!!important + +Declarative role management ignores roles that exist in the database but are +not included in either the Cluster spec or a `DatabaseRole`. The lifecycle of +those roles continues to be managed within PostgreSQL, allowing you to adopt +this feature at your convenience. +!!! + +* * * + +## General role configuration notes + +Regardless of the management method used, the role specification adheres to the +[PostgreSQL structure and naming conventions](https://www.postgresql.org/docs/current/sql-createrole.html). + +!!!tip + +Please refer to the [API reference](pg4k.v1.md#roleconfiguration) +for the full list of attributes. +!!! + +A few points are worth noting: + +1. The `ensure` attribute is **not** part of PostgreSQL. It enables + declarative role management to create (`present`, the default) or remove + (`absent`) a role, and is available **only** in the inline + [`managed.roles`](#inline-managed-roles) stanza. A `DatabaseRole` does not + support `ensure`; it expresses role removal through its + [reclaim policy](#role-reclaim-policy) instead. +2. The `inherit` attribute is true by default, following PostgreSQL + conventions. +3. The `connectionLimit` attribute defaults to -1, in line with PostgreSQL + conventions. +4. Role membership with `inRoles` defaults to no memberships. + +* * * + +## The `DatabaseRole` resource + +The `DatabaseRole` custom resource provides a dedicated, Kubernetes-native way to +manage PostgreSQL database roles. + +This is the recommended approach for modern environments and +GitOps workflows, as it decouples role lifecycle from the cluster +infrastructure. + +!!!note + +A `DatabaseRole` is applied when its specification or its password Secret +changes. Changes made directly in the database, such as a manual +`ALTER ROLE`, are not detected or reverted until the next time the resource +is applied. Inline managed roles, by contrast, are periodically compared +with the database catalog and brought back to their specification. +!!! + +See [Security](security.md#rbac-on-custom-resources) for the RBAC +implications of granting access to `DatabaseRole` resources. + +A `DatabaseRole` is namespace-scoped: the resource, the `Cluster` it references +through `spec.cluster`, and the `passwordSecret` it consumes must all live in +the same namespace. -With the `managed` stanza in the cluster spec, {{name.ln}} now provides full -lifecycle management for roles specified in `.spec.managed.roles`. +### Example manifest +```yaml +apiVersion: postgresql.k8s.enterprisedb.io/v1 +kind: DatabaseRole +metadata: + name: role-dante +spec: + cluster: + name: cluster-example + name: dante + comment: "Dante Alighieri" + login: true + superuser: false + createdb: true + databaseRoleReclaimPolicy: delete + inRoles: + - pg_monitor + passwordSecret: + name: cluster-example-dante +``` + +An example manifest for a role definition can be found in the file +[`role-examples.yaml`](../samples/role-examples.yaml). + +### Role reclaim policy + +The `databaseRoleReclaimPolicy` field defines the "final act" of the operator when a +`DatabaseRole` Custom Resource is removed from the Kubernetes API. +This mirrors the behavior of Kubernetes Persistent Volumes. + +- **`retain` (default):** The role is left in the database. This is the safest + setting for production, ensuring that even if a manifest is accidentally + deleted, the database user (and any objects they own) remains untouched. +- **`delete`:** The operator attempts to execute a `DROP ROLE` in PostgreSQL + before the Kubernetes object is finalized. This is ideal for ephemeral or + automated environments. + +!!!note + +If a role owns objects (tables, schemas, etc.), `DROP ROLE` fails and the +`DatabaseRole` stays in `Terminating`, retried periodically until those objects +are reassigned or dropped. The operator never drops owned objects on your +behalf: reassign or drop them in PostgreSQL, or switch to `retain`, to let the +deletion complete. +!!! + +### Removing a role + +How you remove a role depends on how it was created: + +- **Created through a `DatabaseRole`:** delete the resource. Whether the role is + also dropped from PostgreSQL is governed by its + [reclaim policy](#role-reclaim-policy). +- **Pre-existing, or managed elsewhere:** a `DatabaseRole` is not the tool to drop + it. Declare it `absent` through the inline [`managed.roles`](#inline-managed-roles) + stanza, or run `DROP ROLE` directly. + +!!!warning + +Creating a `DatabaseRole` for a role that already exists **adopts** it: the +operator alters the existing role so that **every** attribute matches the +manifest, including the attributes you omit, which are forced back to their +defaults. In particular, memberships not listed in `inRoles` are revoked, an +omitted `connectionLimit` is reset to `-1` (unlimited), and an omitted +`validUntil` becomes `infinity` if the role had an expiration date. Review +the current attributes and memberships of a role before adopting it, and do +not point a `DatabaseRole` at a role you only want to drop, since it will be +modified before it can be removed. +!!! + +### Status of `DatabaseRole` resources + +The `DatabaseRole` resource includes a dedicated `status` section for per-role +observability: + +```yaml +status: + applied: true + observedGeneration: 3 + conditions: + - lastTransitionTime: "2026-04-04T15:06:23Z" + message: "2051" + reason: ChangeDetected + status: "True" + type: PasswordSecretChange +``` + +The `PasswordSecretChange` condition is maintained by the operator as an +internal signal for the instance manager: its message carries the +`resourceVersion` of the password Secret the operator last observed, and a +change in that value triggers the re-application of the password. The +condition appears once a password Secret is in use and is removed when +`passwordSecret` is removed from the specification. + +If a `DatabaseRole` targets a name already managed in the Cluster spec +(see [Coexistence and precedence](#coexistence-and-precedence)), the `applied` +field will be `false` with the message: + +``` +database role is already managed by the CNP cluster +``` + +On a [replica cluster](replica_cluster.md) the role is owned by the primary +cluster, not reconciled locally. In that case the instance manager reports the +role as *unknown* rather than failed: the `applied` field is left unset (`nil`) +with an explanatory message. The role is reconciled normally once the cluster +is promoted to primary. + +### Client Certificate Generation + +The `DatabaseRole` resource supports opt-in generation of TLS client +certificates, signed by the cluster's client CA and stored in a Kubernetes +Secret. This enables [PostgreSQL `cert` authentication](https://www.postgresql.org/docs/current/auth-cert.html) +as an alternative to passwords: no passwords to rotate manually, and private +keys are stored as Kubernetes Secrets and never transmitted outside the cluster. + +To enable it, add a `clientCertificate` block to the spec: + +```yaml +apiVersion: postgresql.k8s.enterprisedb.io/v1 +kind: DatabaseRole +metadata: + name: role-dante +spec: + cluster: + name: cluster-example + name: dante + login: true + clientCertificate: + enabled: true + databaseRoleReclaimPolicy: retain +``` + +`clientCertificate.enabled` defaults to `true` when the block is present, so +`clientCertificate: {}` is equivalent to enabling it. Set `enabled: false` to +turn issuance off while keeping the block in place. + +!!!important + +`login: true` is required when `clientCertificate` issuance is enabled. The +operator enforces this via validation and will reject the resource otherwise. +!!! + +#### Generated Secret + +The operator creates a Secret named `-client-cert` in the +same namespace. It contains two keys: + +| Key | Contents | +| --------- | ----------------------------------------------------------------- | +| `tls.crt` | PEM-encoded client certificate, signed by the cluster's client CA | +| `tls.key` | PEM-encoded private key | + +The expiration time of the certificate is visible in +`status.clientCertificate.expiration`: + +```yaml +status: + clientCertificate: + expiration: "2026-07-01T12:00:00Z" +``` + +#### Configuring `pg_hba.conf` + +The operator generates the certificate but does **not** modify `pg_hba.conf` +automatically. You must add a `hostssl` rule with the `cert` method to the +cluster for the role to be able to authenticate: + +```yaml +spec: + postgresql: + pg_hba: + - hostssl all dante all cert +``` + +A working connection string using the generated Secret would look like: + +``` +psql "host=-rw..svc port=5432 dbname= user=dante \ + sslcert=/path/to/tls.crt sslkey=/path/to/tls.key \ + sslrootcert=/path/to/ca.crt sslmode=verify-full" +``` + +#### Renewal + +Client certificates inherit the operator's global certificate settings: they +are issued with a **90-day** lifetime by default and renewed automatically once +they fall within **7 days** of expiry. Both values are operator-wide and +configurable via the `CERTIFICATE_DURATION` and `EXPIRING_CHECK_THRESHOLD` +operator settings; they are not configurable per `DatabaseRole`. + +Renewal is driven by the reconcile loop: the operator checks whether the +certificate is approaching expiry and re-signs it if needed. Reconciles are +scheduled at least once per hour when `clientCertificate` issuance is enabled, +so renewal happens well before expiry even without a triggering event. The +current expiration is always reflected in `status.clientCertificate.expiration`. + +#### Deletion and opt-out + +| Scenario | Result | +| ------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------- | +| `clientCertificate.enabled` set to `false`, or the `clientCertificate` block removed | The cert Secret is deleted; `status.clientCertificate` is cleared | +| `DatabaseRole` deleted | The cert Secret is garbage-collected via owner reference, regardless of `databaseRoleReclaimPolicy` | + +!!!note + +`databaseRoleReclaimPolicy: retain` retains the PostgreSQL role, not the generated +Secret. The Secret is only meaningful while the operator is managing the role, +so it is always cleaned up on deletion. +!!! + +#### Bring-your-own-CA limitation + +If the cluster's client CA Secret does not contain a private key (i.e. you +supplied your own CA via `spec.certificates.clientCASecret`), the operator +cannot sign new certificates. It will record the reason in +`status.clientCertificate.message` and stop retrying: + +```yaml +status: + clientCertificate: + message: 'client CA secret "my-ca" has no private key; bring-your-own-CA + clusters require manual certificate management' +``` + +In this case, you must issue and renew client certificates manually. + +!!!note + +CNP does not manage Certificate Revocation Lists (CRLs). If a certificate must +be invalidated before it expires, rotate the cluster's client CA: on the next +reconcile the operator detects that the existing certificates are no longer +signed by the current CA and re-issues all managed client certificates. +Alternatively, delete the certificate's Secret to have the operator issue a +fresh one signed by the current CA. +!!! + +* * * + +## Inline managed roles + +With the `managed` stanza in the cluster spec, {{name.ln}} provides +management for roles specified in `.spec.managed.roles`. This feature enables declarative management of existing roles, as well as the -creation of new roles if they are not already present in the database. Role -creation will occur *after* the database bootstrapping is complete. +creation of new roles if they are not already present. + +### Example manifest An example manifest for a cluster with declarative role management can be found in the file [`cluster-example-with-roles.yaml`](../samples/cluster-example-with-roles.yaml). @@ -42,48 +366,93 @@ spec: - pg_signal_backend ``` -The role specification in `.spec.managed.roles` adheres to the -[PostgreSQL structure and naming conventions](https://www.postgresql.org/docs/current/sql-createrole.html). -Please refer to the [API reference](pg4k.v1.md#roleconfiguration) for -the full list of attributes you can define for each role. +### Status of inline managed roles -A few points are worth noting: +When using the inline method, the `Cluster` status includes a comprehensive +summary: -1. The `ensure` attribute is **not** part of PostgreSQL. It enables declarative - role management to create and remove roles. The two possible values are - `present` (the default) and `absent`. -2. The `inherit` attribute is true by default, following PostgreSQL conventions. -3. The `connectionLimit` attribute defaults to -1, in line with PostgreSQL conventions. -4. Role membership with `inRoles` defaults to no memberships. +```yaml +status: + managedRolesStatus: + byStatus: + reconciled: + - dante + reserved: + - postgres + - streaming_replica + cannotReconcile: + petrarca: + - 'could not perform UPDATE_MEMBERSHIPS on role petrarca: role "poets" does not exist' +``` -Declarative role management ensures that PostgreSQL instances align with the -spec. If a user modifies role attributes directly in the database, the -{{name.ln}} operator will revert those changes during the next reconciliation -cycle. +Note the special sub-section `cannotReconcile` for operations the database (and +{{name.ln}}) cannot honor, and which require human intervention. -## Password management +This section covers roles reserved for operator use and those that are **not** +under declarative management, providing a comprehensive view of the roles in +the database instances. + +The [kubectl plugin](kubectl-plugin.md) also shows the status of managed roles +in its `status` sub-command: + +```txt +Managed roles status +Status Roles +------ ----- +pending-reconciliation petrarca +reconciled app,dante +reserved postgres,streaming_replica + +Irreconcilable roles +Role Errors +---- ------ +petrarca could not perform UPDATE_MEMBERSHIPS on role petrarca: role "poets" does not exist +``` + +* * * + +## Migrating from inline managed roles to a `DatabaseRole` + +You can move a role from the inline `managed.roles` stanza to a standalone +`DatabaseRole` without disruption: + +1. Create the `DatabaseRole` with the desired specification. Both methods + share the same [`RoleConfiguration`](pg4k.v1.md#roleconfiguration) + structure, so the stanza can be copied across as-is. +2. Remove the matching entry from `.spec.managed.roles` in the `Cluster` + manifest. +3. The operator detects the change and hands management over to the + `DatabaseRole`. -The declarative role management feature includes reconciling of role passwords. -Passwords are managed in fundamentally different ways in the Kubernetes world -and in PostgreSQL, and as a result there are a few things to note. +Because the Cluster spec takes precedence while both exist (see +[Coexistence and precedence](#coexistence-and-precedence)), the handover +happens only once the inline entry is gone, so there is no window in which the +role is left unmanaged. -Managed role configurations may optionally specify the name of a -**Secret** where the username and password are stored (encoded in Base64 -as is usual in Kubernetes). For example: +When converting a role that the inline stanza removed with `ensure: absent`, +note that a `DatabaseRole` does not support `ensure: absent`. Express removal +through the [reclaim policy](#role-reclaim-policy) instead: delete the resource +with `databaseRoleReclaimPolicy: delete` to drop the role, or keep the default +`retain` to leave it in place. See [Removing a role](#removing-a-role) for the +full behavior. + +* * * + +## Password management + +The declarative role management feature (both with a `DatabaseRole` and the +inline `managed.roles` stanza) includes reconciling of role passwords. +Managed role configurations may optionally specify the name of a **Secret** +where the username and password are stored: ```yaml - managed: - roles: - - name: dante - ensure: present - [… snipped …] - passwordSecret: - name: cluster-example-dante + passwordSecret: + name: cluster-example-dante ``` -This would assume the existence of a Secret called `cluster-example-dante`, -containing a username and password. The username should match the role we -are setting the password for. For example, : +The Secret must be of type `kubernetes.io/basic-auth`. The username (encoded in +*Base64* as is usual in Kubernetes) should match the role we are setting the +password for. For example: ```yaml apiVersion: v1 @@ -98,32 +467,36 @@ metadata: type: kubernetes.io/basic-auth ``` -If there is no `passwordSecret` specified for a role, the instance manager will -not try to CREATE / ALTER the role with a password. This keeps with PostgreSQL -conventions, where ALTER will not update passwords unless directed to with -`WITH PASSWORD`. +!!!important + +Label the Secret with `k8s.enterprisedb.io/reload: "true"`, as shown above. Password +changes in labeled Secrets are applied immediately, while changes in +unlabeled Secrets are only applied at a subsequent reconciliation, for +example when the operator refreshes its internal cache. +!!! + +If no `passwordSecret` is specified, the instance manager will not try to +`CREATE/ALTER` the role with a password, keeping with PostgreSQL conventions. -If a role was initially created with a password, and we would like to set the -password to NULL in PostgreSQL, this necessitates being explicit on the part of -the user of {{name.ln}}. -To distinguish "no password provided in spec" from "set the password to NULL", -the field `DisablePassword` should be used. +!!!important -Imagine we decided we would like to have no password on the `dante` role in the -database. In such case we would specify the following: +New roles created without `passwordSecret` will have a `NULL` password inside +PostgreSQL. +!!! + +### Disabling passwords + +To explicitly set a password to `NULL` in PostgreSQL (distinguished from simply +omitting a password update), use the `disablePassword` field: ```yaml - managed: - roles: - - name: dante - ensure: present - [… snipped …] - disablePassword: true + disablePassword: true ``` -NOTE: it is considered an error to set both `passwordSecret` and -`disablePassword` on a given role. -This configuration will be rejected by the validation webhook. +!!!note + +It is an error to set both `passwordSecret` and `disablePassword` on a given role. +!!! ### Password expiry, `VALID UNTIL` @@ -154,12 +527,7 @@ never expires, mirroring the behavior of PostgreSQL. Specifically: UNTIL` was not set to `NULL` in the database (this is due to PostgreSQL not allowing `VALID UNTIL NULL` in the `ALTER ROLE` SQL statement) -!!!warning -New roles created without `passwordSecret` will have a `NULL` password -inside PostgreSQL. -!!! - -### Password hashed +### Pre-hashed passwords You can also provide pre-encrypted passwords by specifying the password in MD5/SCRAM-SHA-256 hash format: @@ -177,23 +545,77 @@ stringData: password: SCRAM-SHA-256$:$: ``` +!!!warning + +The example above uses `stringData:`, where Kubernetes encodes the value +for you, which is the safest path for pre-hashed passwords. If you must +use `data:`, encode the bytes exactly with `printf '%s' "$hash" | base64` +(or `echo -n "$hash" | base64`). A trailing newline from a naive +`echo "$hash" | base64` makes the value miss the SCRAM/MD5 shadow-format +check, so the operator falls back to treating it as cleartext and +re-hashes it, and login stops working. +!!! + ### Safety when transmitting cleartext passwords -While role passwords are safely managed in Kubernetes using Secrets, -there is still a risk on the PostgreSQL side. If creating/altering a role with -password, PostgreSQL may print the password as part of the query statement -in some `postgres` logs, as mentioned in the [PostgreSQL documentation](https://www.postgresql.org/docs/current/sql-createrole.html): +Role passwords are safely managed in Kubernetes using Secrets, but the +SQL path between the operator and PostgreSQL is also a concern. As noted +in the [PostgreSQL documentation](https://www.postgresql.org/docs/current/sql-createrole.html): > The password will be transmitted to the server in cleartext, and it might > also be logged in the client's command history or the server log -{{name.ln}} adds a safety layer by temporarily suppressing both statement -logging (`log_statement`) and error statement logging -(`log_min_error_statement`) for any CREATE or ALTER operation on a role with -password, thus preventing leakage in both success and failure scenarios. +{{name.ln}} protects this path in two complementary ways: + +1. Before emitting `CREATE`/`ALTER ROLE ... PASSWORD '...'`, the operator + SCRAM-SHA-256 encodes any cleartext password operator-side (client-side + from PostgreSQL's point of view). This is the standard PostgreSQL + practice for keeping cleartext out of server logs and extensions like + `pg_stat_statements` or `pgaudit`, and is the same encoding that + `psql \password` and libpq's `PQencryptPasswordConn` perform. The + literal PostgreSQL receives is the SCRAM-SHA-256 verifier stored in + `pg_authid.rolpassword`. Passwords already provided in MD5 or + SCRAM-SHA-256 shadow form are forwarded unchanged. +2. The same `CREATE`/`ALTER ROLE` statements are executed inside a + transaction that temporarily suppresses both statement logging + (`log_statement`) and error statement logging + (`log_min_error_statement`), preventing leakage to the PostgreSQL log + in both success and failure scenarios. + The Status section of the cluster does not print the query statement for any managed role operation. +#### Opting out of operator-side encoding + +If you need PostgreSQL (not the operator) to decide how the password is +hashed (for example, on a cluster running `password_encryption = md5`), +set the annotation `k8s.enterprisedb.io/passwordPassthrough: "enabled"` on the +basic-auth Secret. The operator will then forward the password value +verbatim. + +!!!warning + +The `k8s.enterprisedb.io/passwordPassthrough` annotation must be set on the +**basic-auth Secret** itself, not on the `Cluster` resource. Placing it +on the `Cluster` has no effect, and the operator will continue to apply +SCRAM-SHA-256 encoding to the password before sending it to PostgreSQL. +!!! + +The opt-in is per-Secret and applies to every basic-auth Secret the +operator consumes (managed-role secrets, but also the superuser and +application-user secrets), so a single cluster can mix passthrough +secrets and operator-encoded secrets freely. The statement-logging +suppression layer described above still applies in both modes. + +!!!warning + +With `k8s.enterprisedb.io/passwordPassthrough: "enabled"`, the operator forwards +the Secret's `password` value verbatim. If that value is cleartext (the +common case on a `password_encryption = md5` cluster), extensions such +as `pg_stat_statements` or `pgaudit` will observe it. This is the +expected trade-off for letting PostgreSQL choose the hash format. +!!! + ## Unrealizable role configurations In PostgreSQL, in some cases, commands cannot be honored by the database and @@ -215,63 +637,6 @@ above could be fixed by creating the role `poets` or dropping the database `inferno` respectively, but they might have originated due to human error, and in such case, the "fix" proposed might be the wrong thing to do. -{{name.ln}} will record when such fundamental errors occur, and will display -them in the cluster Status. Which segues into… - -## Status of managed roles - -The Cluster status includes a section for the managed roles' status, as shown -below: - -```yaml -status: - […snipped…] - managedRolesStatus: - byStatus: - not-managed: - - app - pending-reconciliation: - - dante - - petrarca - reconciled: - - ariosto - reserved: - - postgres - - streaming_replica - cannotReconcile: - dante: - - 'could not perform DELETE on role dante: owner of database inferno' - petrarca: - - 'could not perform UPDATE_MEMBERSHIPS on role petrarca: role "poets" does not exist' -``` - -Note the special sub-section `cannotReconcile` for operations the database (and -{{name.ln}}) cannot honor, and which require human intervention. - -This section covers roles reserved for operator use and those that are **not** -under declarative management, providing a comprehensive view of the roles in -the database instances. - -The [kubectl plugin](kubectl-plugin.md) also shows the status of managed roles -in its `status` sub-command: - -```txt -Managed roles status -Status Roles ------- ----- -pending-reconciliation petrarca -reconciled app,dante -reserved postgres,streaming_replica - -Irreconcilable roles -Role Errors ----- ------ -petrarca could not perform UPDATE_MEMBERSHIPS on role petrarca: role "poets" does not exist -``` - -!!!info Important -In terms of backward compatibility, declarative role management is designed -to ignore roles that exist in the database but are not included in the spec. -The lifecycle of these roles will continue to be managed within PostgreSQL, -allowing {{name.ln}} users to adopt this feature at their convenience. -!!! +{{name.ln}} will record when such fundamental errors occur, and will display +them in the cluster Status, as described in +[Status of inline managed roles](#status-of-inline-managed-roles). diff --git a/product_docs/docs/postgres_for_kubernetes/1/failover.mdx b/product_docs/docs/postgres_for_kubernetes/1/failover.mdx index e0e1e4f43e..ec966611d2 100644 --- a/product_docs/docs/postgres_for_kubernetes/1/failover.mdx +++ b/product_docs/docs/postgres_for_kubernetes/1/failover.mdx @@ -51,6 +51,136 @@ and clients are forcibly disconnected, then the server is shut down. without a clean shutdown. !!! +## Safe primary election + +To ensure that at most one instance promotes itself to primary at any +given time, {{name.ln}} backs the election described above with a +Kubernetes `Lease` object, named after the `Cluster` and living in +its namespace. An instance must acquire and hold this lease before +it promotes to primary. On a clean shutdown the former primary +releases the lease, so an eligible replica can take over without +waiting for the lease to expire. + +### What the primary lease protects against + +Consider a replica catching up by reading WAL files from the archive +rather than streaming from the previous primary. PostgreSQL stops +replaying as soon as the archive returns "file not found" for the +next expected segment, treating it as the end of the WAL stream. If +a replica promotes while the previous primary still has WAL it has +not finished archiving, that signal arrives before the true end of +the stream: the replica forks a new timeline at an LSN earlier than +the last writes the previous primary acknowledged, and those writes +are lost. + +The lease holds promotion back until the previous primary releases +it. On a clean shutdown the release happens after PostgreSQL has +flushed and archived its remaining WAL, so the replica that takes +over sees the archive at its definitive end. If the previous primary +cannot release the lease (crash, node failure, or the instance +manager itself unreachable), the lease expires after +`leaseDurationSeconds` elapses and the replica can promote. In that +path the archive may not have caught up, and any writes the previous +primary did not finish archiving are lost. + +### Relationship with the primary isolation check + +The lease does not fence a primary that has lost connectivity to the +Kubernetes API server but is still running; that is the job of the +[primary isolation](instance_manager.md#primary-isolation) check. +The two mechanisms are complementary and both are enabled by default: + +- The lease prevents *premature* promotion: a replica cannot promote + while the former primary still holds the lease. +- The isolation check stops an *isolated* primary from continuing to + accept writes. + +Keep both enabled. Disabling the isolation check leaves the lease +alone responsible for primary safety, and the lease alone cannot +prevent split-brain when the former primary cannot reach the API +server but remains otherwise healthy. + +### Inspecting the primary lease + +The lease shares the cluster's name, so you can inspect it directly. For a +cluster called `cluster-example`: + +```sh +kubectl get lease cluster-example +``` + +The `HOLDER` column reports the pod that currently holds the lease, which is the +current primary: + +```console +NAME HOLDER AGE +cluster-example cluster-example-1 5m +``` + +For the full picture, including the lease duration in effect and the +last renewal time, use: + +```sh +kubectl get lease cluster-example -o yaml +``` + +### Tuning the primary lease + +The lease timings are exposed under `.spec.primaryLease` and default to values +suitable for most clusters. They map directly onto the underlying Kubernetes +leader-election parameters. + +| Field | Default | Description | +| ------------------------------ | ------- | ------------------------------------------------------------------------ | +| `leaseDurationSeconds` | `15` | How long the lease is valid before another instance may acquire it. | +| `renewDeadlineSeconds` | `10` | How long the primary keeps retrying to renew the lease before giving up. | +| `retryPeriodSeconds` | `2` | How frequently a non-holder retries acquiring or renewing the lease. | +| `releasedLeaseDurationSeconds` | `1` | TTL written when the primary releases the lease on a clean shutdown. | + +For example, to make the cluster more tolerant of a slow or briefly unreachable +API server: + +```yaml +spec: + primaryLease: + leaseDurationSeconds: 60 + renewDeadlineSeconds: 40 + retryPeriodSeconds: 15 +``` + +!!!warning + +Tune these values only if you understand the impact on failover timing: longer +intervals make the cluster more tolerant of transient API server unavailability +but slow down legitimate promotions. Two invariants are enforced by the +admission webhook: `leaseDurationSeconds` must be greater than +`renewDeadlineSeconds`, and `renewDeadlineSeconds` must be greater than +`retryPeriodSeconds` multiplied by `1.2`. Both mirror the requirements of the +underlying Kubernetes leader election. +!!! + +!!!note + +`leaseDurationSeconds` and `retryPeriodSeconds` govern two different timings. +After an abrupt primary loss (the previous primary did not release the lease), a +candidate must observe the lease unchanged for a full `leaseDurationSeconds` +before it may take over: this is what holds back a premature promotion while the +former primary may still be alive. After a clean switchover (the previous primary +released the lease), there is no such wait; the candidate simply notices the +released lease on its next poll, so the hand-over latency is bounded by +`retryPeriodSeconds`. Lowering `retryPeriodSeconds` speeds up switchover without +shortening the take-over wait that guards against premature promotion, at the +cost of more frequent lease renewals against the API server. +!!! + +!!!note + +The primary instance captures these timings the first time it acquires the +lease. Changing `.spec.primaryLease` on a running cluster therefore takes effect +only after the affected primary Pod restarts; until then the primary keeps using +the values it started with. +!!! + ## RTO and RPO impact Failover may result in the service being impacted ([RTO](before_you_start.md#postgresql-terminology)) diff --git a/product_docs/docs/postgres_for_kubernetes/1/faq.mdx b/product_docs/docs/postgres_for_kubernetes/1/faq.mdx index ceeb996cf0..cc4aa8b870 100644 --- a/product_docs/docs/postgres_for_kubernetes/1/faq.mdx +++ b/product_docs/docs/postgres_for_kubernetes/1/faq.mdx @@ -172,7 +172,7 @@ by creating the first instance, configuring the replication, cloning a second instance, and the third one. In a declarative approach, the state of a system is defined using -configuration, namely: there's a PostgreSQL 13 cluster with two replicas. +configuration, namely: there's a PostgreSQL 18 cluster with two replicas. This approach highly simplifies change management operations, and when these are stored in source control systems like Git, it enables the Infrastructure as Code capability. And Kubernetes takes it farther than diff --git a/product_docs/docs/postgres_for_kubernetes/1/image_catalog.mdx b/product_docs/docs/postgres_for_kubernetes/1/image_catalog.mdx index b6a47175de..bd5eccfc3d 100644 --- a/product_docs/docs/postgres_for_kubernetes/1/image_catalog.mdx +++ b/product_docs/docs/postgres_for_kubernetes/1/image_catalog.mdx @@ -32,6 +32,9 @@ Both resources share a common schema: - **Uniqueness**: The `major` field must be unique within a single catalog. - **Extensions**: Support for certified extension container images (available for PostgreSQL 18+ via `extension_control_path`). +- **Component images**: An optional list of named images for non-PostgreSQL + components such as PgBouncer (see + [Component images](#component-images)). !!!warning @@ -43,6 +46,46 @@ must ensure the declared major version matches the actual PostgreSQL images to maintain compatibility. !!! +## Component images + +In addition to PostgreSQL images, a catalog can store images for other +components via the `componentImages` field. Each entry is identified by a string +**key** — a lowercase alphanumeric identifier (hyphens allowed, 1–63 +characters) that must be unique within the catalog. + +Currently, the only consumer of component images is the `Pooler` resource, +which can reference a component image entry to centrally manage the PgBouncer +container image (see +[Using an image catalog](connection_pooling.md#using-an-image-catalog)). + +The following example defines a namespaced `ImageCatalog` with a PgBouncer +component image: + +```yaml +apiVersion: postgresql.k8s.enterprisedb.io/v1 +kind: ImageCatalog +metadata: + name: my-catalog + namespace: default +spec: + images: + - major: 18 + image: docker.enterprisedb.com/k8s/postgresql:18.4-standard-ubi9 + componentImages: + - key: pgbouncer + image: docker.enterprisedb.com/k8s/pgbouncer:1.25.1-ubi9 +``` + +For a cluster-wide catalog, use `kind: ClusterImageCatalog` and drop the +`metadata.namespace` field (the `spec` is otherwise identical). + +!!!info + +A catalog may contain up to 32 component image entries. Keys are lowercase +alphanumeric characters or hyphens, starting and ending with an alphanumeric +character, up to 63 characters long. +!!! + ## Configuration examples ### Defining a catalog @@ -66,7 +109,7 @@ spec: - major: 17 image: docker.enterprisedb.com/k8s/postgresql:17.6-standard-ubi9 - major: 18 - image: docker.enterprisedb.com/k8s/postgresql:18.3-standard-ubi9 + image: docker.enterprisedb.com/k8s/postgresql:18.4-standard-ubi9 ``` The following example defines a cluster-wide `ClusterImageCatalog`: @@ -85,7 +128,7 @@ spec: - major: 17 image: docker.enterprisedb.com/k8s/postgresql:17.6-standard-ubi9 - major: 18 - image: docker.enterprisedb.com/k8s/postgresql:18.3-standard-ubi9 + image: docker.enterprisedb.com/k8s/postgresql:18.4-standard-ubi9 ``` ### Referencing a Catalog in a Cluster @@ -121,7 +164,7 @@ metadata: spec: images: - major: 18 - image: docker.enterprisedb.com/k8s_enterprise/postgresql:18.3-minimal-ubi9 + image: docker.enterprisedb.com/k8s/postgresql:18.4-minimal-ubi9 extensions: - name: foo image: @@ -221,7 +264,7 @@ You can install all the available catalogs by using the `kustomization` file present in the `image-catalogs` directory: ```shell -kubectl apply -k https://github.com/cloudnative-pg/artifacts//image-catalogs?ref=main +kubectl apply -k 'https://github.com/cloudnative-pg/artifacts//image-catalogs?ref=main' ``` You can then view all the catalogs deployed with: diff --git a/product_docs/docs/postgres_for_kubernetes/1/imagevolume_extensions.mdx b/product_docs/docs/postgres_for_kubernetes/1/imagevolume_extensions.mdx index 0eb46d1601..61f3c64c3a 100644 --- a/product_docs/docs/postgres_for_kubernetes/1/imagevolume_extensions.mdx +++ b/product_docs/docs/postgres_for_kubernetes/1/imagevolume_extensions.mdx @@ -105,7 +105,10 @@ must be unique within the cluster. !!!important The `name` must consist of lowercase alphanumeric characters, underscores (`_`) -or hyphens (`-`) and must start and end with an alphanumeric character. +or hyphens (`-`) and must start and end with an alphanumeric character. It is +limited to 59 characters, leaving room for the prefix {{name.ln}} adds when +deriving the extension's Kubernetes volume name (capped at the RFC 1123 limit of +63 characters). !!! Each entry defines the configuration for a container image and specifies the diff --git a/product_docs/docs/postgres_for_kubernetes/1/installation_upgrade.mdx b/product_docs/docs/postgres_for_kubernetes/1/installation_upgrade.mdx index a040731a56..bd65061da9 100644 --- a/product_docs/docs/postgres_for_kubernetes/1/installation_upgrade.mdx +++ b/product_docs/docs/postgres_for_kubernetes/1/installation_upgrade.mdx @@ -71,12 +71,12 @@ kubectl create secret -n postgresql-operator-system docker-registry edb-pull-sec Now that the pull-secret has been added to the namespace, the operator can be installed like any other resource in Kubernetes, through a YAML manifest applied via `kubectl`. -You can install the [latest operator manifest](https://get.enterprisedb.io/pg4k/pg4k-1.29.1.yaml) +You can install the [latest operator manifest](https://get.enterprisedb.io/pg4k/pg4k-1.30.0-rc1.yaml) for this minor release as follows: ```sh kubectl apply --server-side -f \ - https://get.enterprisedb.io/pg4k/pg4k-1.29.1.yaml + https://get.enterprisedb.io/pg4k/pg4k-1.30.0-rc1.yaml ``` You can verify that with: @@ -288,45 +288,169 @@ When versions are not directly upgradable, the old version needs to be removed before installing the new one. This won't affect user data but only the operator itself. -### Upgrading to 1.29.1, 1.28.3, or 1.25.8 +### Upgrading to 1.30.0, 1.29.2, or 1.28.4 -Version 1.29.1, 1.28.3, and 1.25.8 ship the fix for `CVE-2026-44477` / -`GHSA-423p-g724-fr39`. The metrics exporter now authenticates as a -dedicated `cnp_metrics_exporter` role with `pg_monitor` privileges -only, instead of the `postgres` superuser. +!!!info Important -Custom monitoring queries that read user-owned tables, or use -`target_databases: '*'` against databases where `PUBLIC` `CONNECT` -has been revoked, need explicit `GRANT` statements to -`cnp_metrics_exporter`. See ["Custom query privileges and -safety"](monitoring.md#custom-query-privileges-and-safety) and ["Manually creating -the metrics exporter -role"](monitoring.md#manually-creating-the-metrics-exporter-role) in -the monitoring documentation. +We strongly recommend that all {{name.ln}} users upgrade to version +1.30.0, or at least to the latest stable version of your current minor release +(e.g., 1.29.2 or 1.28.4). +!!! -### Upgrading to 1.29.0 or 1.28.x +These releases introduce changes worth reviewing before you upgrade. Two are +security changes that apply to **1.30.0, 1.29.2, and 1.28.4**: operator-side +password encoding and `search_path` hardening. The other three are new in +**1.30.0** only: the `DatabaseRole` resource for declarative role management, +safe primary election via a per-cluster Lease, and operator-to-instance +authentication on the instance manager's status port. +In addition, if you are upgrading from a release **older than 1.29.1, 1.28.3, or +1.25.8**, the metrics-exporter privilege separation from `CVE-2026-44477` also +applies. +Each is covered in its own subsection below. + +#### Operator-side password encoding + +Starting from versions 1.30.0, 1.29.2, and 1.28.4, for security reasons, +{{name.ln}} SCRAM-SHA-256 encodes role passwords **operator-side** +(client-side from PostgreSQL's point of view) before issuing +`CREATE`/`ALTER ROLE` statements. As a result, the literal that reaches +the PostgreSQL parser (and that extensions such as `pg_stat_statements` +or `pgaudit` may observe) is the same hash that ends up in +`pg_authid.rolpassword`, never the cleartext secret. The encoding is +applied to every basic-auth `Secret` the operator consumes: the +`postgres` superuser secret, the application-user secret, and any +managed-role password secret. Passwords already supplied in MD5 or +SCRAM-SHA-256 shadow form are passed through unchanged. + +Since PostgreSQL [14](https://www.postgresql.org/docs/release/14.0/), +`password_encryption` defaults to `scram-sha-256`, so we do not expect +existing installations to be affected by this change. + +If your cluster has explicitly overridden `password_encryption` to a +value other than `scram-sha-256` (for example, `md5`) and you want +PostgreSQL (not the operator) to decide how the password is hashed, +opt out by setting the annotation `k8s.enterprisedb.io/passwordPassthrough: "enabled"` +on each basic-auth `Secret` the operator consumes. The operator will +then forward the password value verbatim, and PostgreSQL will encode it +according to its own `password_encryption` GUC. -!!!info Important +!!!warning -We strongly recommend that all {{name.ln}} users upgrade to version -1.29.0, or at least to the latest stable version of your current minor release -(e.g., 1.28.x). +The `k8s.enterprisedb.io/passwordPassthrough` annotation must be set on the +**basic-auth Secret** itself, not on the `Cluster` resource. Placing it +on the `Cluster` has no effect, and the operator will continue to apply +SCRAM-SHA-256 encoding to the password before sending it to PostgreSQL. !!! -### Upgrading to 1.27 from a previous minor version +!!!warning + +With `k8s.enterprisedb.io/passwordPassthrough: "enabled"` the operator forwards the +Secret's `password` value verbatim. If that value is cleartext, as is +common on `password_encryption = md5` clusters, extensions such as +`pg_stat_statements` or `pgaudit` will observe it. +!!! -Version 1.27 introduces a change in the default behavior of the -[liveness probe](instance_manager.md#liveness-probe): it now enforces the -[shutdown of an isolated primary](instance_manager.md#primary-isolation) -within the `livenessProbeTimeout` (30 seconds). +See ["Opting out of operator-side encoding"](declarative_role_management.md#opting-out-of-operator-side-encoding) +for details. + +#### `search_path` hardening + +Also starting from versions 1.30.0, 1.29.2, and 1.28.4, for security reasons, +{{name.ln}} pins the `search_path` to a fixed `pg_catalog, public, +pg_temp` on every connection it opens to PostgreSQL, so that a +tenant-controlled `ALTER DATABASE`/`ALTER ROLE` setting can no longer +influence how operator-issued queries resolve unqualified object names. +The `SECURITY DEFINER` lookup function used by the PgBouncer integration +is recreated automatically with its own pinned `search_path` during the +first reconciliation after the upgrade. +See [Schema resolution and `search_path` hardening](security.md#schema-resolution-and-search_path-hardening) +for the rationale. + +This change also affects custom monitoring queries, which now run inside +a transaction whose `search_path` is pinned to `pg_catalog, public, +pg_temp`. If any of your custom metrics reference objects that live in +other user-defined schemas through an unqualified name, schema-qualify +them (for example `myschema.mytable`) so they keep resolving after the +upgrade. User-authored bootstrap (`postInit*`) and logical-import +post-import SQL are unaffected: they continue to run with the standard +`"$user", public` resolution. + +#### Declarative role management with the `DatabaseRole` resource + +Starting from version 1.30.0, you can also manage a PostgreSQL role as a +standalone [`DatabaseRole`](declarative_role_management.md) resource instead +of declaring it inline in the Cluster's `.spec.managed.roles` stanza. This is +an opt-in enhancement and requires no action on upgrade: existing inline roles +keep working unchanged, and the inline `managed.roles` method remains fully +supported. + +To move an existing inline role under a `DatabaseRole` without disruption, +create the `DatabaseRole` first and only then remove the matching entry from +`.spec.managed.roles`. While both exist the Cluster spec always takes +precedence, so management is handed over only once the inline entry is gone. +See [Migrating from inline managed roles](declarative_role_management.md#migrating-from-inline-managed-roles-to-a-databaserole) +for the full procedure. + +A `DatabaseRole` does not support `ensure: absent`: where the inline +`managed.roles` stanza drops a role by setting `ensure: absent`, a +`DatabaseRole` instead relies on the `databaseRoleReclaimPolicy` field. Delete +the resource with `databaseRoleReclaimPolicy: delete` to drop the role from +PostgreSQL, or keep the default `retain` to leave the role in place. + +#### Safe primary election + +Starting from version 1.30.0, {{name.ln}} coordinates primary promotion +through a per-cluster Kubernetes `Lease`, ensuring that at most one instance +promotes itself at any given time. The behavior is enabled automatically and +requires no configuration; the lease timings can optionally be tuned via +`.spec.primaryLease` (see ["Safe primary election"](failover.md#safe-primary-election)). -If this behavior is not suitable for your environment, you can disable the -*isolation check* in the liveness probe with the following configuration: +!!!warning -```yaml -spec: - probes: - liveness: - isolationCheck: - enabled: false -``` +This feature requires the operator to manage `Lease` objects in the +`coordination.k8s.io` API group. The bundled operator manifest and the Helm +chart grant the required permissions automatically. If you manage the +operator's RBAC yourself, you must add the `create`, `get`, `list`, `update` +and `watch` verbs on `leases` in the `coordination.k8s.io` API group before +upgrading, otherwise primaries will be unable to promote. +!!! + +#### Operator-to-instance authentication + +Starting from version 1.30.0, the operator authenticates its calls to the +sensitive endpoints of the instance manager's status port (backup, +`pg_controldata`, partial WAL archive, and instance-manager upgrade) by pinning +an in-memory client certificate. This is enabled automatically and requires no +configuration. Status, health, and probe endpoints remain unauthenticated. See +[Operator-to-instance authentication](security.md#operator-to-instance-authentication) +for details. + +!!!warning + +This protection has a hard requirement: the status port **must** be served over +TLS, which has been the default since v1.24. Instances created by an operator +older than v1.24 serve the status port over plain HTTP; once their instance +manager is upgraded to 1.30.0 the operator can no longer authenticate to them +and every call to the protected endpoints is **permanently** rejected with +`401 Unauthorized`. If you still run such instances, perform a rolling update so +their Pods are recreated with a TLS-enabled status port. Instances created by +v1.24 or later are unaffected. +!!! + +#### Metrics exporter privilege separation (`CVE-2026-44477`) + +This applies only if you are upgrading from a release **older than 1.29.1, +1.28.3, or 1.25.8** (for example 1.29.0, 1.28.2, 1.25.7, or any earlier +version); installations already on 1.29.1, 1.28.3, 1.25.8, or later already +have this change. + +The fix for `CVE-2026-44477` / `GHSA-423p-g724-fr39` makes the metrics exporter +authenticate as a dedicated `cnp_metrics_exporter` role with `pg_monitor` +privileges only, instead of the `postgres` superuser. + +Custom monitoring queries that read user-owned tables, or use +`target_databases: '*'` against databases where `PUBLIC` `CONNECT` has been +revoked, need explicit `GRANT` statements to `cnp_metrics_exporter`. +See ["Custom query privileges and safety"](monitoring.md#custom-query-privileges-and-safety) +and ["Manually creating the metrics exporter role"](monitoring.md#manually-creating-the-metrics-exporter-role) +in the monitoring documentation. diff --git a/product_docs/docs/postgres_for_kubernetes/1/instance_manager.mdx b/product_docs/docs/postgres_for_kubernetes/1/instance_manager.mdx index 99f6dec3c0..dc40ad1b96 100644 --- a/product_docs/docs/postgres_for_kubernetes/1/instance_manager.mdx +++ b/product_docs/docs/postgres_for_kubernetes/1/instance_manager.mdx @@ -242,6 +242,14 @@ spec: connectionTimeout: "2000" ``` +!!!info + +Primary isolation is distinct from the [safe primary election](failover.md#safe-primary-election) +mechanism. The isolation check *fences* a primary that has lost connectivity to +both the API server and the other instances, while the primary lease coordinates +*which instance is allowed to promote*. The two mechanisms are complementary. +!!! + ## Readiness Probe The readiness probe starts once the startup probe has successfully completed. diff --git a/product_docs/docs/postgres_for_kubernetes/1/kubectl-plugin.mdx b/product_docs/docs/postgres_for_kubernetes/1/kubectl-plugin.mdx index d4f8923d5a..e053358f23 100644 --- a/product_docs/docs/postgres_for_kubernetes/1/kubectl-plugin.mdx +++ b/product_docs/docs/postgres_for_kubernetes/1/kubectl-plugin.mdx @@ -36,11 +36,11 @@ them in your systems. #### Debian packages -For example, let's install the 1.29.1 release of the plugin, for an Intel based +For example, let's install the 1.30.0-rc1 release of the plugin, for an Intel based 64 bit server. First, we download the right `.deb` file. ```sh -wget https://github.com/EnterpriseDB/kubectl-cnp/releases/download/v1.29.1/kubectl-cnp_1.29.1_linux_x86_64.deb \ +wget https://github.com/EnterpriseDB/kubectl-cnp/releases/download/v1.30.0-rc1/kubectl-cnp_1.30.0-rc1_linux_x86_64.deb \ --output-document kube-plugin.deb ``` @@ -51,17 +51,17 @@ $ sudo dpkg -i kube-plugin.deb Selecting previously unselected package cnp. (Reading database ... 6688 files and directories currently installed.) Preparing to unpack kube-plugin.deb ... -Unpacking kubectl-cnp (1.29.1) ... -Setting up kubectl-cnp (1.29.1) ... +Unpacking kubectl-cnp (1.30.0-rc1) ... +Setting up kubectl-cnp (1.30.0-rc1) ... ``` #### RPM packages -As in the example for `.rpm` packages, let's install the 1.29.1 release for an +As in the example for `.rpm` packages, let's install the 1.30.0-rc1 release for an Intel 64 bit machine. Note the `--output` flag to provide a file name. ```sh -curl -L https://github.com/EnterpriseDB/kubectl-cnp/releases/download/v1.29.1/kubectl-cnp_1.29.1_linux_x86_64.rpm \ +curl -L https://github.com/EnterpriseDB/kubectl-cnp/releases/download/v1.30.0-rc1/kubectl-cnp_1.30.0-rc1_linux_x86_64.rpm \ --output kube-plugin.rpm ``` @@ -75,7 +75,7 @@ Dependencies resolved. Package Architecture Version Repository Size ==================================================================================================== Installing: - cnp x86_64 1.29.1-1 @commandline 20 M + cnp x86_64 1.30.0-rc1-1 @commandline 20 M Transaction Summary ==================================================================================================== @@ -246,9 +246,9 @@ sandbox-3 0/604DE38 0/604DE38 0/604DE38 0/604DE38 00:00:00 00:00:00 00 Instances status Name Current LSN Replication role Status QoS Manager Version Node ---- ----------- ---------------- ------ --- --------------- ---- -sandbox-1 0/604DE38 Primary OK BestEffort 1.29.1 k8s-eu-worker -sandbox-2 0/604DE38 Standby (async) OK BestEffort 1.29.1 k8s-eu-worker2 -sandbox-3 0/604DE38 Standby (async) OK BestEffort 1.29.1 k8s-eu-worker +sandbox-1 0/604DE38 Primary OK BestEffort 1.30.0-rc1 k8s-eu-worker +sandbox-2 0/604DE38 Standby (async) OK BestEffort 1.30.0-rc1 k8s-eu-worker2 +sandbox-3 0/604DE38 Standby (async) OK BestEffort 1.30.0-rc1 k8s-eu-worker ``` If you require more detailed status information, use the `--verbose` option (or @@ -302,9 +302,9 @@ sandbox-primary primary 1 1 1 Instances status Name Current LSN Replication role Status QoS Manager Version Node ---- ----------- ---------------- ------ --- --------------- ---- -sandbox-1 0/6053720 Primary OK BestEffort 1.29.1 k8s-eu-worker -sandbox-2 0/6053720 Standby (async) OK BestEffort 1.29.1 k8s-eu-worker2 -sandbox-3 0/6053720 Standby (async) OK BestEffort 1.29.1 k8s-eu-worker +sandbox-1 0/6053720 Primary OK BestEffort 1.30.0-rc1 k8s-eu-worker +sandbox-2 0/6053720 Standby (async) OK BestEffort 1.30.0-rc1 k8s-eu-worker2 +sandbox-3 0/6053720 Standby (async) OK BestEffort 1.30.0-rc1 k8s-eu-worker ``` With an additional `-v` (e.g. `kubectl cnp status sandbox -v -v`), you can @@ -532,12 +532,12 @@ and previous logs are available, it will show them both. ```output ====== Begin of Previous Log ===== -2023-03-28T12:56:41.251711811Z {"level":"info","ts":"2023-03-28T12:56:41Z","logger":"setup","msg":"Starting EDB Postgres for Kubernetes Operator","version":"1.29.1","build":{"Version":"1.29.1+dev107","Commit":"cc9bab17","Date":"2023-03-28"}} +2023-03-28T12:56:41.251711811Z {"level":"info","ts":"2023-03-28T12:56:41Z","logger":"setup","msg":"Starting EDB Postgres for Kubernetes Operator","version":"1.30.0-rc1","build":{"Version":"1.30.0-rc1+dev107","Commit":"cc9bab17","Date":"2023-03-28"}} 2023-03-28T12:56:41.251851909Z {"level":"info","ts":"2023-03-28T12:56:41Z","logger":"setup","msg":"Starting pprof HTTP server","addr":"0.0.0.0:6060"} ====== End of Previous Log ===== -2023-03-28T12:57:09.854306024Z {"level":"info","ts":"2023-03-28T12:57:09Z","logger":"setup","msg":"Starting EDB Postgres for Kubernetes Operator","version":"1.29.1","build":{"Version":"1.29.1+dev107","Commit":"cc9bab17","Date":"2023-03-28"}} +2023-03-28T12:57:09.854306024Z {"level":"info","ts":"2023-03-28T12:57:09Z","logger":"setup","msg":"Starting EDB Postgres for Kubernetes Operator","version":"1.30.0-rc1","build":{"Version":"1.30.0-rc1+dev107","Commit":"cc9bab17","Date":"2023-03-28"}} 2023-03-28T12:57:09.854363943Z {"level":"info","ts":"2023-03-28T12:57:09Z","logger":"setup","msg":"Starting pprof HTTP server","addr":"0.0.0.0:6060"} ``` diff --git a/product_docs/docs/postgres_for_kubernetes/1/labels_annotations.mdx b/product_docs/docs/postgres_for_kubernetes/1/labels_annotations.mdx index ccf6cb654b..e89ddf7ba8 100644 --- a/product_docs/docs/postgres_for_kubernetes/1/labels_annotations.mdx +++ b/product_docs/docs/postgres_for_kubernetes/1/labels_annotations.mdx @@ -203,6 +203,14 @@ instead `k8s.enterprisedb.io/operatorVersion` : Version of the operator. +`k8s.enterprisedb.io/passwordPassthrough` +: When set to `enabled` on a basic-auth `Secret` consumed by the + operator (superuser, application user, or a managed-role password + secret), the operator forwards the password value verbatim in the + `CREATE`/`ALTER ROLE` statement instead of SCRAM-SHA-256 encoding + it operator-side. PostgreSQL then encodes the value according to its + own `password_encryption` setting. See [Opting out of operator-side encoding](declarative_role_management.md#opting-out-of-operator-side-encoding). + `k8s.enterprisedb.io/pgControldata` : Output of the `pg_controldata` command. This annotation replaces the old, deprecated `k8s.enterprisedb.io/hibernatePgControlData` annotation. @@ -214,10 +222,19 @@ instead : Annotation can be applied on a `Cluster` resource. ``` -When set to JSON-patch formatted patch, the patch will be applied on the instance Pods. +When set to a JSON-patch formatted patch, the patch will be applied to the +instance Pods. The patch can modify any field of the Pod specification, +including security-sensitive fields. The operator validates only that the +patch is syntactically correct and applicable. + +As with all Cluster fields that affect Pod specifications, enforcement of +security constraints is delegated to the Kubernetes admission control chain. +See the +[Trust Model and Security Boundaries](security.md#trust-model-and-security-boundaries) +section for details. **⚠️ WARNING:** This feature may introduce discrepancies between the -operator’s expectations and Kubernetes behavior. Use with caution and only as a +operator's expectations and Kubernetes behavior. Use with caution and only as a last resort. **IMPORTANT**: adding or changing this annotation won't trigger a rolling deployment diff --git a/product_docs/docs/postgres_for_kubernetes/1/logical_replication.mdx b/product_docs/docs/postgres_for_kubernetes/1/logical_replication.mdx index 3b8dbc128a..fd0fc9c06c 100644 --- a/product_docs/docs/postgres_for_kubernetes/1/logical_replication.mdx +++ b/product_docs/docs/postgres_for_kubernetes/1/logical_replication.mdx @@ -147,6 +147,13 @@ The `Publication` object must reference a specific `Cluster`, determining where the publication will be created. It is managed by the cluster's primary instance, ensuring the publication is created or updated as needed. +!!!warning + +The `spec.cluster` field is immutable after creation. To create a +publication on a different `Cluster`, create a new `Publication` resource +instead of updating an existing one. +!!! + ### Reconciliation and Status After creating a `Publication`, {{name.ln}} manages it on the primary @@ -189,6 +196,11 @@ spec: In this case, deleting the `Publication` object also removes the `publisher` publication from the `app` database of the `freddie` cluster. +On a replica cluster the database is read-only, so deleting a `Publication` +object releases its finalizer and removes the Kubernetes object without dropping +the publication in PostgreSQL, even with `publicationReclaimPolicy: delete`. +Dropping the publication is left to the primary cluster, which owns it. + ## Subscriptions In PostgreSQL's publish-and-subscribe replication model, a @@ -285,6 +297,13 @@ where the subscription will be managed. {{name.ln}} ensures that the subscription is created or updated on the primary instance of the specified cluster. +!!!warning + +The `spec.cluster` field is immutable after creation. To manage the +subscription on a different `Cluster`, create a new `Subscription` +resource instead of updating an existing one. +!!! + ### Reconciliation and Status After creating a `Subscription`, {{name.ln}} manages it on the primary @@ -327,6 +346,11 @@ spec: In this case, deleting the `Subscription` object also removes the `subscriber` subscription from the `app` database of the `king` cluster. +On a replica cluster the database is read-only, so deleting a `Subscription` +object releases its finalizer and removes the Kubernetes object without dropping +the subscription in PostgreSQL, even with `subscriptionReclaimPolicy: delete`. +Dropping the subscription is left to the primary cluster, which owns it. + ### Resilience to Failovers To ensure that your logical replication subscriptions remain operational after @@ -386,6 +410,17 @@ resource: ```yaml apiVersion: postgresql.k8s.enterprisedb.io/v1 +kind: DatabaseRole +metadata: + name: freddie-app +spec: + cluster: + name: freddie + name: app + login: true + replication: true +--- +apiVersion: postgresql.k8s.enterprisedb.io/v1 kind: Cluster metadata: name: freddie @@ -403,12 +438,6 @@ spec: - CREATE TABLE n (i SERIAL PRIMARY KEY, m INTEGER) - INSERT INTO n (m) (SELECT generate_series(1, 10000)) - ALTER TABLE n OWNER TO app - - managed: - roles: - - name: app - login: true - replication: true --- apiVersion: postgresql.k8s.enterprisedb.io/v1 kind: Publication diff --git a/product_docs/docs/postgres_for_kubernetes/1/monitoring.mdx b/product_docs/docs/postgres_for_kubernetes/1/monitoring.mdx index 35f5442f0d..1863ed31e7 100644 --- a/product_docs/docs/postgres_for_kubernetes/1/monitoring.mdx +++ b/product_docs/docs/postgres_for_kubernetes/1/monitoring.mdx @@ -263,7 +263,7 @@ cnp_collector_up{cluster="cluster-example"} 1 # HELP cnp_collector_postgres_version Postgres version # TYPE cnp_collector_postgres_version gauge -cnp_collector_postgres_version{cluster="cluster-example",full="18.3"} 18.3 +cnp_collector_postgres_version{cluster="cluster-example",full="18.4"} 18.4 # HELP cnp_collector_last_failed_backup_timestamp The last failed backup as a unix timestamp (Deprecated) # TYPE cnp_collector_last_failed_backup_timestamp gauge @@ -534,6 +534,14 @@ collect per-database metrics across the whole cluster. Schema-qualify catalog references (`pg_catalog.now()`, `pg_catalog.current_database()`) to prevent `search_path` shadowing by user-owned objects. + +Custom monitoring queries run inside a transaction whose +`search_path` is pinned to `pg_catalog, public, pg_temp`, +regardless of any `search_path` configured on the database or the +role. Unqualified references to objects in other user-defined +schemas will therefore fail to resolve: schema-qualify them (e.g. +`myschema.mytable`) so the query does not depend on the +`search_path`. !!! #### Example of a user defined metric @@ -995,7 +1003,7 @@ metadata: spec: containers: - name: curl - image: curlimages/curl:8.17.0 + image: curlimages/curl:8.21.0 command: ['sleep', '3600'] EOF ``` diff --git a/product_docs/docs/postgres_for_kubernetes/1/object_stores.mdx b/product_docs/docs/postgres_for_kubernetes/1/object_stores.mdx index 5ab5b7c71f..cd86ab30b8 100644 --- a/product_docs/docs/postgres_for_kubernetes/1/object_stores.mdx +++ b/product_docs/docs/postgres_for_kubernetes/1/object_stores.mdx @@ -167,6 +167,27 @@ spec: [...] ``` +!!!note + +Recent changes to the [boto3 implementation](https://github.com/boto/boto3/issues/4392) +of [Amazon S3 Data Integrity Protections](https://docs.aws.amazon.com/sdkref/latest/guide/feature-dataintegrity.html) +may lead to the `x-amz-content-sha256` error. If you encounter this issue, you +can apply the following workaround by setting specific environment variables at +the cluster level through `spec.env`: + +```yaml +apiVersion: postgresql.k8s.enterprisedb.io/v1 +kind: Cluster +[...] +spec: + env: + - name: AWS_REQUEST_CHECKSUM_CALCULATION + value: when_required + - name: AWS_RESPONSE_CHECKSUM_VALIDATION + value: when_required +``` +!!! + ### Using Object Storage with a private CA Suppose you configure an Object Storage provider which uses a certificate diff --git a/product_docs/docs/postgres_for_kubernetes/1/operator_capability_levels.mdx b/product_docs/docs/postgres_for_kubernetes/1/operator_capability_levels.mdx index 5fdbe783be..87b9bf0e29 100644 --- a/product_docs/docs/postgres_for_kubernetes/1/operator_capability_levels.mdx +++ b/product_docs/docs/postgres_for_kubernetes/1/operator_capability_levels.mdx @@ -43,9 +43,17 @@ We consider information security part of this level. ### Operator deployment via declarative configuration -The operator is installed in a declarative way using a Kubernetes manifest -that defines four major `CustomResourceDefinition` objects: `Cluster`, `Pooler`, -`Backup`, and `ScheduledBackup`. +The operator is installed in a declarative way using a Kubernetes manifest that +defines the core `CustomResourceDefinition` objects required to manage the +PostgreSQL lifecycle. These include: + +- **Configuration & Topology:** `Cluster`, `Pooler`, `ImageCatalog`, and + `ClusterImageCatalog`. +- **Identity & Schema:** `DatabaseRole` and `Database`. +- **Business Continuity:** `Backup`, `ScheduledBackup`, `Publication`, and + `Subscription`. +- **Runtime Orchestration:** `FailoverQuorum` (used by the operator for + consensus during automated failover). ### PostgreSQL cluster deployment via declarative configuration @@ -53,9 +61,13 @@ You define a PostgreSQL cluster (operand) using the `Cluster` custom resource in a fully declarative way. The PostgreSQL version is determined by the operand container image defined in the CR, which is automatically fetched from the requested registry. -When deploying an operand, the operator also creates the following resources: -`Pod`, `Service`, `Secret`, `ConfigMap`, `PersistentVolumeClaim`, -`PodDisruptionBudget`, `ServiceAccount`, `RoleBinding`, and `Role`. + +The operator orchestrates the deployment by creating and managing standard +Kubernetes resources (`Pod`, `Service`, `Secret`, `ConfigMap`, +`PersistentVolumeClaim`, `PodDisruptionBudget`, `ServiceAccount`, +`RoleBinding`, and `Role`), and reconciles user-defined CNP resources such as +`Database` and `DatabaseRole` to ensure the database environment matches the +desired state. You can optionally provide a pre-existing ServiceAccount for both `Cluster` and `Pooler` resources. This shared ServiceAccount support enables seamless @@ -83,6 +95,9 @@ Beyond just the core PostgreSQL engine, image catalogs now allow you to define ensuring that the database and its associated modules are always compatible, version-aligned, and treated as a single cohesive unit across your entire infrastructure. +The same catalog mechanism also governs [PgBouncer](connection_pooling.md) +pooler images, making image catalogs a unified supply-chain primitive across +the entire PostgreSQL stack managed by the operator. ### Labels and annotations @@ -184,8 +199,24 @@ authentication rules in the `postgresql` section of the CR. ### Configuration of Postgres roles, users, and groups {{name.ln}} supports -[management of PostgreSQL roles, users, and groups through declarative configuration](declarative_role_management.md) -using the `.spec.managed.roles` stanza. +[comprehensive management of PostgreSQL roles, users, and groups](declarative_role_management.md) +through two declarative methods: + +- The `DatabaseRole` CRD (Recommended): A standalone resource for granular lifecycle + management. It includes a `databaseRoleReclaimPolicy` (supporting `retain` or + `delete`) to define whether the database role should be dropped when the + Kubernetes resource is removed. + +- The `managed` stanza: For simpler requirements, roles can be defined inline + within the `.spec.managed.roles` section of the `Cluster` resource. + +Both methods provide automated reconciliation of role attributes (e.g., +`login`, `superuser`, `connectionLimit`) and secure, versioned password +management via Kubernetes Secrets. Passwords are SCRAM-SHA-256 encoded +operator-side before they are sent to PostgreSQL, so the cleartext value never +reaches the server log or extensions. A `DatabaseRole` can additionally request +a TLS client certificate that the operator generates and renews automatically, +enabling password-free `cert` authentication. ### Configuration of Postgres extensions @@ -401,6 +432,10 @@ consistency and initiates a job to validate upgrade conditions and execute files, and tablespaces before re-creating the replicas. This structured workflow provides a reliable path for major version transitions and supports automatic rollback cleanup when the user reverts the image after a failure. +Clusters that use Image Volume extensions are also supported: the source- and +target-version extension images are mounted side by side during the upgrade +job, so the old server keeps its libraries and a failed upgrade reverts +cleanly. ### Display cluster availability status during upgrade @@ -605,7 +640,12 @@ The operator allows you to scale up and down the number of instances in a PostgreSQL cluster. New replicas are started up from the primary server and participate in the cluster's HA infrastructure. The CRD declares a "scale" subresource that allows you to use the -`kubectl scale` command. +`kubectl scale` command. The scale subresource also publishes the label +selector of the managed instance pods, which lets autoscalers discover them. +See the [Vertical Pod Autoscaler integration](resource_management.md#integration-with-the-vertical-pod-autoscaler-vpa) +for the recommended use, and the +[Horizontal Pod Autoscaler integration](resource_management.md#integration-with-the-horizontal-pod-autoscaler-hpa) +for the caveats that apply to HPA. ### Maintenance window and PodDisruptionBudget for Kubernetes nodes @@ -654,6 +694,10 @@ to clone the data from the primary again. The operator allows administrators to control and manage resource usage by the cluster's pods in the `resources` section of the manifest. In particular, you can set `requests` and `limits` values for both CPU and RAM. +Because the `Cluster` exposes a label selector through its scale subresource, +it can also be used as a target for the +[Vertical Pod Autoscaler](resource_management.md#integration-with-the-vertical-pod-autoscaler-vpa) +in recommendation-only mode, to obtain sizing suggestions for these values. ### Connection pooling with PgBouncer @@ -665,15 +709,23 @@ to access the database. This optimizes the query flow toward the instances and makes the use of the underlying PostgreSQL resources more efficient. Instead of connecting directly to a PostgreSQL service, applications can now connect to the PgBouncer service and start reusing any existing connection. +The PgBouncer image can be managed centrally through an `ImageCatalog` or +`ClusterImageCatalog` (via `spec.pgbouncer.imageCatalogRef`), and the `Pooler` +metrics endpoint can optionally be served over TLS. ### Logical Replication {{name.ln}} supports PostgreSQL's logical replication in a declarative manner -using `Publication` and `Subscription` custom resource definitions. +using the `Publication` and `Subscription` custom resource definitions. + +Logical replication is particularly useful for: -Logical replication is particularly useful together with the import facility -for online data migrations (even from public DBaaS solutions) and major -PostgreSQL upgrades. +- Online data migrations: Moving data from external PostgreSQL instances or + public DBaaS solutions with minimal downtime. +- Major PostgreSQL upgrades: Facilitating near-zero-downtime upgrades between + major versions. +- Selective Data Distribution: Replicating specific tables or data sets across + different clusters for reporting or localized workloads. ### Integration with external backup tools for Kubernetes @@ -769,6 +821,16 @@ the cluster. It does this by either becoming the new primary or by following it. In case the former primary comes back up, the same mechanism avoids a split-brain by preventing applications from reaching it, running `pg_rewind` on the server and restarting it as a standby. +The operator further coordinates primary promotion through a per-cluster +Kubernetes `Lease` that acts as a mutex, ensuring at most one instance promotes +at any given time: an instance must hold the lease before acting as primary and +releases it on a clean shutdown, so replicas can promote without waiting for the +full TTL. +If synchronous failover quorum is enabled, the operator's "Auto Pilot" logic +becomes even more sophisticated: it will actively block a promotion if a quorum +of replicas cannot verify the transaction state. This prevents accidental data +loss during complex failure scenarios, such as network partitions affecting +both the primary and its synchronous standby. ### Automated recreation of a standby diff --git a/product_docs/docs/postgres_for_kubernetes/1/operator_conf.mdx b/product_docs/docs/postgres_for_kubernetes/1/operator_conf.mdx index aa39c3c4bc..cf1f194f4c 100644 --- a/product_docs/docs/postgres_for_kubernetes/1/operator_conf.mdx +++ b/product_docs/docs/postgres_for_kubernetes/1/operator_conf.mdx @@ -43,31 +43,43 @@ As a result, if a parameter is defined in both places, the one in the Secret wil The operator looks for the following environment variables to be defined in the `ConfigMap`/`Secret`: -| Name | Description | -| ----------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `CERTIFICATE_DURATION` | Determines the lifetime of the generated certificates in days. Default is 90. | -| `CLUSTERS_ROLLOUT_DELAY` | The duration (in seconds) to wait between the roll-outs of different clusters during an operator upgrade. This setting controls the timing of upgrades across clusters, spreading them out to reduce system impact. The default value is `0` which means no delay between PostgreSQL cluster upgrades. | -| `CREATE_ANY_SERVICE` | When set to `true`, will create `-any` service for the cluster. Default is `false` | -| `DRAIN_TAINTS` | Specifies the taint keys that should be interpreted as indicators of node drain. By default, it includes the taints commonly applied by [kubectl](https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/), [Cluster Autoscaler](https://github.com/kubernetes/autoscaler), and [Karpenter](https://github.com/aws/karpenter-provider-aws): `node.kubernetes.io/unschedulable`, `ToBeDeletedByClusterAutoscaler`, `karpenter.sh/disrupted`, `karpenter.sh/disruption`. | -| `EDB_LICENSE_KEY` | Default license key (to be used only if the cluster does not define one, and preferably in the `Secret`) | -| `ENABLE_INSTANCE_MANAGER_INPLACE_UPDATES` | When set to `true`, enables in-place updates of the instance manager after an update of the operator, avoiding rolling updates of the cluster (default `false`) | -| `ENABLE_REDWOOD_BY_DEFAULT` | Enable the Redwood compatibility by default when using EPAS. | -| `EXPIRING_CHECK_THRESHOLD` | Determines the threshold, in days, for identifying a certificate as expiring. Default is 7. | -| `EXTERNAL_BACKUP_ADDON_CONFIGURATION` | Configuration for the `external-backup-adapter` add-on. (See ["Customizing the adapter" in Add-ons](addons.md#customizing-the-adapter)) | -| `INCLUDE_PLUGINS` | A comma-separated list of plugins to be always included in the Cluster's reconciliation. | -| `INHERITED_ANNOTATIONS` | List of annotation names that, when defined in a `Cluster` metadata, will be inherited by all the generated resources, including pods | -| `INHERITED_LABELS` | List of label names that, when defined in a `Cluster` metadata, will be inherited by all the generated resources, including pods | -| `INSTANCES_ROLLOUT_DELAY` | The duration (in seconds) to wait between roll-outs of individual PostgreSQL instances within the same cluster during an operator upgrade. The default value is `0`, meaning no delay between upgrades of instances in the same PostgreSQL cluster. | -| `KUBERNETES_CLUSTER_DOMAIN` | Defines the domain suffix for service FQDNs within the Kubernetes cluster. If left unset, it defaults to "cluster.local". | -| `METRICS_CERT_DIR` | The directory where TLS certificates for the operator metrics server are stored. When set, enables TLS for the metrics endpoint on port 8080. The directory must contain `tls.crt` and `tls.key` files following standard Kubernetes TLS secret conventions. If not set, the metrics server operates without TLS (default behavior). | -| `MONITORING_QUERIES_CONFIGMAP` | The name of a ConfigMap in the operator's namespace with a set of default queries (to be specified under the key `queries`) to be applied to all created Clusters | -| `MONITORING_QUERIES_SECRET` | The name of a Secret in the operator's namespace with a set of default queries (to be specified under the key `queries`) to be applied to all created Clusters | -| `OPERATOR_IMAGE_NAME` | The name of the operator image used to bootstrap Pods. Defaults to the image specified during installation. | -| `PGBOUNCER_IMAGE_NAME` | The name of the PgBouncer image used by default for new poolers. Defaults to the version specified in the operator. | -| `POSTGRES_IMAGE_NAME` | The name of the PostgreSQL image used by default for new clusters. Defaults to the version specified in the operator. | -| `PULL_SECRET_NAME` | Name of an additional pull secret to be defined in the operator's namespace and to be used to download images | -| `STANDBY_TCP_USER_TIMEOUT` | Defines the [`TCP_USER_TIMEOUT` socket option](https://www.postgresql.org/docs/current/runtime-config-connection.html#GUC-TCP-USER-TIMEOUT) in milliseconds for replication connections from standby instances to the primary. Default is 5000 (5 seconds). Set to `0` to use the system's default. | -| `WATCH_NAMESPACE` | Specifies the namespace(s) where the operator should watch for resources. Multiple namespaces can be specified separated by commas. If not set, the operator watches all namespaces (cluster-wide mode). | +| Name | Description | +| ----------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `CERTIFICATE_DURATION` | Determines the lifetime of the generated certificates in days. Default is 90. | +| `CLUSTERS_ROLLOUT_DELAY` | The duration (in seconds) to wait between the roll-outs of different clusters during an operator upgrade. This setting controls the timing of upgrades across clusters, spreading them out to reduce system impact. The default value is `0` which means no delay between PostgreSQL cluster upgrades. | +| `CREATE_ANY_SERVICE` | When set to `true`, will create `-any` service for the cluster. Default is `false` | +| `DRAIN_TAINTS` | Specifies the taint keys that should be interpreted as indicators of node drain. By default, it includes the taints commonly applied by [kubectl](https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/), [Cluster Autoscaler](https://github.com/kubernetes/autoscaler), and [Karpenter](https://github.com/aws/karpenter-provider-aws): `node.kubernetes.io/unschedulable`, `ToBeDeletedByClusterAutoscaler`, `karpenter.sh/disrupted`, `karpenter.sh/disruption`. | +| `EDB_LICENSE_KEY` | Default license key (to be used only if the cluster does not define one, and preferably in the `Secret`) | +| `ENABLE_INSTANCE_MANAGER_INPLACE_UPDATES` | When set to `true`, enables in-place updates of the instance manager after an update of the operator, avoiding rolling updates of the cluster (default `false`) | +| `ENABLE_REDWOOD_BY_DEFAULT` | Enable the Redwood compatibility by default when using EPAS. | +| `ENABLE_WEBHOOK_NAMESPACE_SUFFIX` | When set to `true`, the operator looks up its `MutatingWebhookConfiguration` and `ValidatingWebhookConfiguration` under names suffixed with `-` (e.g. `postgresql-operator-mutating-webhook-configuration-postgresql-operator-team-a` and `postgresql-operator-validating-webhook-configuration-postgresql-operator-team-a`). Use this when running multiple namespaced operator instances on the same cluster to avoid name collisions. The operator does not create the suffixed configurations; you must create them before starting the operator with this flag enabled. If `OPERATOR_NAMESPACE` is not set when this flag is enabled, the operator will refuse to start. Default is `false`. | +| `EXPIRING_CHECK_THRESHOLD` | Determines the threshold, in days, for identifying a certificate as expiring. Default is 7. | +| `EXTERNAL_BACKUP_ADDON_CONFIGURATION` | Configuration for the `external-backup-adapter` add-on. (See ["Customizing the adapter" in Add-ons](addons.md#customizing-the-adapter)) | +| `INCLUDE_PLUGINS` | A comma-separated list of plugins to be always included in the Cluster's reconciliation. | +| `INHERITED_ANNOTATIONS` | List of annotation names that, when defined in a `Cluster` metadata, will be inherited by all the generated resources, including pods | +| `INHERITED_LABELS` | List of label names that, when defined in a `Cluster` metadata, will be inherited by all the generated resources, including pods | +| `INSTANCES_ROLLOUT_DELAY` | The duration (in seconds) to wait between roll-outs of individual PostgreSQL instances within the same cluster during an operator upgrade. The default value is `0`, meaning no delay between upgrades of instances in the same PostgreSQL cluster. | +| `KUBERNETES_CLUSTER_DOMAIN` | Defines the domain suffix for service FQDNs within the Kubernetes cluster. If left unset, it defaults to "cluster.local". | +| `MANAGE_WEBHOOK_CONFIGURATIONS` | When set to `true` (default), the operator injects its CA bundle into the `MutatingWebhookConfiguration` and `ValidatingWebhookConfiguration`. Set to `false` when the CA bundle is injected externally, for example by cert-manager's CA injector or by GitOps. This is independent of the webhook serving certificate, which the operator always manages when it owns its PKI. | +| `METRICS_CERT_DIR` | The directory where TLS certificates for the operator metrics server are stored. When set, enables TLS for the metrics endpoint on port 8080. The directory must contain `tls.crt` and `tls.key` files following standard Kubernetes TLS secret conventions. If not set, the metrics server operates without TLS (default behavior). | +| `MONITORING_QUERIES_CONFIGMAP` | The name of a ConfigMap in the operator's namespace with a set of default queries (to be specified under the key `queries`) to be applied to all created Clusters | +| `MONITORING_QUERIES_SECRET` | The name of a Secret in the operator's namespace with a set of default queries (to be specified under the key `queries`) to be applied to all created Clusters | +| `OPERATOR_IMAGE_NAME` | The name of the operator image used to bootstrap Pods. Defaults to the image specified during installation. | +| `PGBOUNCER_IMAGE_NAME` | The name of the PgBouncer image used by default for new poolers. Defaults to the version specified in the operator. | +| `POSTGRES_IMAGE_NAME` | The name of the PostgreSQL image used by default for new clusters. Defaults to the version specified in the operator. | +| `PULL_SECRET_NAME` | Name of an additional pull secret to be defined in the operator's namespace and to be used to download images | +| `STANDBY_TCP_USER_TIMEOUT` | Defines the [`TCP_USER_TIMEOUT` socket option](https://www.postgresql.org/docs/current/runtime-config-connection.html#GUC-TCP-USER-TIMEOUT) in milliseconds for replication connections from standby instances to the primary. Default is 5000 (5 seconds). Set to `0` to use the system's default. | +| `WATCH_NAMESPACE` | Specifies the namespace(s) where the operator should watch for resources. Multiple namespaces can be specified separated by commas. If not set, the operator watches all namespaces (cluster-wide mode). | + +!!!warning + +{{name.ln}} does NOT currently support running multiple operators on +the same cluster. While this can be achieved through the use of namespaced +deployments using `ENABLE_WEBHOOK_NAMESPACE_SUFFIX` and `WATCH_NAMESPACE`, +multiple operators still use the same set of shared CRDs. We cannot +guarantee a backwards compatible upgrade across multiple concurrently +running operators. +!!! Values in `INHERITED_ANNOTATIONS` and `INHERITED_LABELS` support path-like wildcards. For example, the value `example.com/*` will match both the value `example.com/one` and `example.com/two`. @@ -161,6 +173,24 @@ Following the above example, if the `Cluster` definition contains a `categories` annotation and any of the `environment`, `workload`, or `app` labels, these will be inherited by all the resources generated by the deployment. +## Defaulting and validation without admission webhooks + +{{name.ln}} normally defaults and validates its resources through admission +webhooks. When the webhooks are not installed, or are temporarily unable to +respond, the operator performs the same defaulting and validation during +reconciliation as a fallback. + +If a resource fails validation, reconciliation stops and the reason is surfaced +on the resource status: `Cluster` and `Backup` move to the `Invalid cluster +definition` and `invalid backup definition` phases respectively, while `Pooler` +and `ScheduledBackup` report it in `.status.error`. The status lists only the +offending field paths; the full validation error, which may contain field +values, is written to the operator logs only. Correcting the spec clears the +error and resumes reconciliation. + +Validation performed during reconciliation honors the `k8s.enterprisedb.io/validation: +disabled` annotation, exactly as the admission webhook does. + ## Profiling tools The operator can expose a pprof HTTP server on `localhost:6060`. diff --git a/product_docs/docs/postgres_for_kubernetes/1/pg4k.v1/v1.30.0-rc1-next.mdx b/product_docs/docs/postgres_for_kubernetes/1/pg4k.v1/v1.30.0-rc1-next.mdx new file mode 100644 index 0000000000..b041297ffb --- /dev/null +++ b/product_docs/docs/postgres_for_kubernetes/1/pg4k.v1/v1.30.0-rc1-next.mdx @@ -0,0 +1,2618 @@ +--- +title: API Reference - v1.30.0-rc1-next +navTitle: v1.30.0-rc1-next +pdfExclude: 'true' + +--- + +## Packages + +- [postgresql.k8s.enterprisedb.io/v1](#postgresqlk8senterprisedbiov1) + +## postgresql.k8s.enterprisedb.io/v1 + +Package v1 contains API Schema definitions for the postgresql v1 API group + +### Resource Types + +- [Backup](#backup) +- [Cluster](#cluster) +- [ClusterImageCatalog](#clusterimagecatalog) +- [Database](#database) +- [DatabaseRole](#databaserole) +- [DatabaseRoleList](#databaserolelist) +- [FailoverQuorum](#failoverquorum) +- [ImageCatalog](#imagecatalog) +- [Pooler](#pooler) +- [Publication](#publication) +- [ScheduledBackup](#scheduledbackup) +- [Subscription](#subscription) + +#### AffinityConfiguration + +AffinityConfiguration contains the info we need to create the +affinity rules for Pods + +*Appears in:* + +- [ClusterSpec](#clusterspec) + +| Field | Description | Required | Default | Validation | +| --------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------- | ------- | ---------- | +| `enablePodAntiAffinity` *boolean* | Activates anti-affinity for the pods. The operator will define pods
anti-affinity unless this field is explicitly set to false | | | | +| `topologyKey` *string* | TopologyKey to use for anti-affinity configuration. See k8s documentation
for more info on that | | | | +| `nodeSelector` *object (keys:string, values:string)* | NodeSelector is map of key-value pairs used to define the nodes on which
the pods can run.
More info: | | | | +| `nodeAffinity` *[NodeAffinity](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#nodeaffinity-v1-core)* | NodeAffinity describes node affinity scheduling rules for the pod.
More info: | | | | +| `tolerations` *[Toleration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#toleration-v1-core) array* | Tolerations is a list of Tolerations that should be set for all the pods, in order to allow them to run
on tainted nodes.
More info: | | | | +| `podAntiAffinityType` *string* | PodAntiAffinityType allows the user to decide whether pod anti-affinity between cluster instance has to be
considered a strong requirement during scheduling or not. Allowed values are: "preferred" (default if empty) or
"required". Setting it to "required", could lead to instances remaining pending until new kubernetes nodes are
added if all the existing nodes don't match the required pod anti-affinity rule.
More info:
| | | | +| `additionalPodAntiAffinity` *[PodAntiAffinity](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#podantiaffinity-v1-core)* | AdditionalPodAntiAffinity allows to specify pod anti-affinity terms to be added to the ones generated
by the operator if EnablePodAntiAffinity is set to true (default) or to be used exclusively if set to false. | | | | +| `additionalPodAffinity` *[PodAffinity](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#podaffinity-v1-core)* | AdditionalPodAffinity allows to specify pod affinity terms to be passed to all the cluster's pods. | | | | + +#### AvailableArchitecture + +AvailableArchitecture represents the state of a cluster's architecture + +*Appears in:* + +- [ClusterStatus](#clusterstatus) + +| Field | Description | Required | Default | Validation | +| ----------------- | ------------------------------------------------- | -------- | ------- | ---------- | +| `goArch` *string* | GoArch is the name of the executable architecture | True | | | +| `hash` *string* | Hash is the hash of the executable | True | | | + +#### Backup + +A Backup resource is a request for a PostgreSQL backup by the user. + +| Field | Description | Required | Default | Validation | +| ------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ---------- | +| `apiVersion` *string* | `postgresql.k8s.enterprisedb.io/v1` | True | | | +| `kind` *string* | `Backup` | True | | | +| `metadata` *[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#objectmeta-v1-meta)* | Refer to Kubernetes API documentation for fields of `metadata`. | True | | | +| `spec` *[BackupSpec](#backupspec)* | Specification of the desired behavior of the backup.
More info: | True | | | +| `status` *[BackupStatus](#backupstatus)* | Most recently observed status of the backup. This data may not be up to
date. Populated by the system. Read-only.
More info: | | | | + +#### BackupConfiguration + +BackupConfiguration defines how the backup of the cluster are taken. +The supported backup methods are BarmanObjectStore and VolumeSnapshot. +For details and examples refer to the Backup and Recovery section of the +documentation + +*Appears in:* + +- [ClusterSpec](#clusterspec) + +| Field | Description | Required | Default | Validation | +| -------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ------------------------------------- | +| `volumeSnapshot` *[VolumeSnapshotConfiguration](#volumesnapshotconfiguration)* | VolumeSnapshot provides the configuration for the execution of volume snapshot backups. | | | | +| `barmanObjectStore` *[BarmanObjectStoreConfiguration](https://pkg.go.dev/github.com/cloudnative-pg/barman-cloud/pkg/api#BarmanObjectStoreConfiguration)* | The configuration for the barman-cloud tool suite | | | | +| `retentionPolicy` *string* | RetentionPolicy is the retention policy to be used for backups
and WALs (i.e. '60d'). The retention policy is expressed in the form
of `XXu` where `XX` is a positive integer and `u` is in `[dwm]` -
days, weeks, months.
It's currently only applicable when using the BarmanObjectStore method. | | | Pattern: `^[1-9][0-9]*[dwm]$`
| +| `target` *[BackupTarget](#backuptarget)* | The policy to decide which instance should perform backups. Available
options are empty string, which will default to `prefer-standby` policy,
`primary` to have backups run always on primary instances, `prefer-standby`
to have backups run preferably on the most updated standby, if available. | | | Enum: [primary prefer-standby]
| + +#### BackupMethod + +*Underlying type:* *string* + +BackupMethod defines the way of executing the physical base backups of +the selected PostgreSQL instance + +*Appears in:* + +- [BackupSpec](#backupspec) +- [BackupStatus](#backupstatus) +- [ClusterStatus](#clusterstatus) +- [ScheduledBackupSpec](#scheduledbackupspec) + +| Field | Description | +| ------------------- | -------------------------------------------------------------------------------------------- | +| `volumeSnapshot` | BackupMethodVolumeSnapshot means using the volume snapshot
Kubernetes feature
| +| `barmanObjectStore` | BackupMethodBarmanObjectStore means using barman to backup the
PostgreSQL cluster
| +| `plugin` | BackupMethodPlugin means that this backup should be handled by
a plugin
| + +#### BackupPhase + +*Underlying type:* *string* + +BackupPhase is the phase of the backup + +*Appears in:* + +- [BackupStatus](#backupstatus) + +#### BackupPluginConfiguration + +BackupPluginConfiguration contains the backup configuration used by +the backup plugin + +*Appears in:* + +- [BackupSpec](#backupspec) +- [ScheduledBackupSpec](#scheduledbackupspec) + +| Field | Description | Required | Default | Validation | +| -------------------------------------------------- | -------------------------------------------------------------------------------------------- | -------- | ------- | ---------- | +| `name` *string* | Name is the name of the plugin managing this backup | True | | | +| `parameters` *object (keys:string, values:string)* | Parameters are the configuration parameters passed to the backup
plugin for this backup | | | | + +#### BackupSnapshotElementStatus + +BackupSnapshotElementStatus is a volume snapshot that is part of a volume snapshot method backup + +*Appears in:* + +- [BackupSnapshotStatus](#backupsnapshotstatus) + +| Field | Description | Required | Default | Validation | +| ------------------------- | -------------------------------------------------------------------------------------------------- | -------- | ------- | ---------- | +| `name` *string* | Name is the snapshot resource name | True | | | +| `type` *string* | Type is tho role of the snapshot in the cluster, such as PG_DATA, PG_WAL and PG_TABLESPACE | True | | | +| `tablespaceName` *string* | TablespaceName is the name of the snapshotted tablespace. Only set
when type is PG_TABLESPACE | | | | + +#### BackupSnapshotStatus + +BackupSnapshotStatus the fields exclusive to the volumeSnapshot method backup + +*Appears in:* + +- [BackupStatus](#backupstatus) + +| Field | Description | Required | Default | Validation | +| ------------------------------------------------------------------------------ | --------------------------------------------------------------- | -------- | ------- | ---------- | +| `elements` *[BackupSnapshotElementStatus](#backupsnapshotelementstatus) array* | The elements list, populated with the gathered volume snapshots | | | | + +#### BackupSource + +BackupSource contains the backup we need to restore from, plus some +information that could be needed to correctly restore it. + +*Appears in:* + +- [BootstrapRecovery](#bootstraprecovery) + +| Field | Description | Required | Default | Validation | +| -------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ---------- | +| `name` *string* | Name of the referent. | True | | | +| `endpointCA` *[SecretKeySelector](https://pkg.go.dev/github.com/cloudnative-pg/machinery/pkg/api#SecretKeySelector)* | EndpointCA store the CA bundle of the barman endpoint.
Useful when using self-signed certificates to avoid
errors with certificate issuer and barman-cloud-wal-archive. | | | | + +#### BackupSpec + +BackupSpec defines the desired state of Backup + +*Appears in:* + +- [Backup](#backup) + +| Field | Description | Required | Default | Validation | +| ----------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ----------------- | ------------------------------------------------------ | +| `cluster` *[LocalObjectReference](https://pkg.go.dev/github.com/cloudnative-pg/machinery/pkg/api#LocalObjectReference)* | The cluster to backup | True | | | +| `target` *[BackupTarget](#backuptarget)* | The policy to decide which instance should perform this backup. If empty,
it defaults to `cluster.spec.backup.target`.
Available options are empty string, `primary` and `prefer-standby`.
`primary` to have backups run always on primary instances,
`prefer-standby` to have backups run preferably on the most updated
standby, if available. | | | Enum: [primary prefer-standby]
| +| `method` *[BackupMethod](#backupmethod)* | The backup method to be used, possible options are `barmanObjectStore`,
`volumeSnapshot` or `plugin`. Defaults to: `barmanObjectStore`. | | barmanObjectStore | Enum: [barmanObjectStore volumeSnapshot plugin]
| +| `pluginConfiguration` *[BackupPluginConfiguration](#backuppluginconfiguration)* | Configuration parameters passed to the plugin managing this backup | | | | +| `online` *boolean* | Whether the default type of backup with volume snapshots is
online/hot (`true`, default) or offline/cold (`false`)
Overrides the default setting specified in the cluster field '.spec.backup.volumeSnapshot.online' | | | | +| `onlineConfiguration` *[OnlineConfiguration](#onlineconfiguration)* | Configuration parameters to control the online/hot backup with volume snapshots
Overrides the default settings specified in the cluster '.backup.volumeSnapshot.onlineConfiguration' stanza | | | | + +#### BackupStatus + +BackupStatus defines the observed state of Backup + +*Appears in:* + +- [Backup](#backup) + +| Field | Description | Required | Default | Validation | +| ------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ---------- | +| `googleCredentials` *[GoogleCredentials](https://pkg.go.dev/github.com/cloudnative-pg/barman-cloud/pkg/api#GoogleCredentials)* | The credentials to use to upload data to Google Cloud Storage | | | | +| `s3Credentials` *[S3Credentials](https://pkg.go.dev/github.com/cloudnative-pg/barman-cloud/pkg/api#S3Credentials)* | The credentials to use to upload data to S3 | | | | +| `azureCredentials` *[AzureCredentials](https://pkg.go.dev/github.com/cloudnative-pg/barman-cloud/pkg/api#AzureCredentials)* | The credentials to use to upload data to Azure Blob Storage | | | | +| `majorVersion` *integer* | The PostgreSQL major version that was running when the
backup was taken. | True | | | +| `endpointCA` *[SecretKeySelector](https://pkg.go.dev/github.com/cloudnative-pg/machinery/pkg/api#SecretKeySelector)* | EndpointCA store the CA bundle of the barman endpoint.
Useful when using self-signed certificates to avoid
errors with certificate issuer and barman-cloud-wal-archive. | | | | +| `endpointURL` *string* | Endpoint to be used to upload data to the cloud,
overriding the automatic endpoint discovery | | | | +| `destinationPath` *string* | The path where to store the backup (i.e. s3://bucket/path/to/folder)
this path, with different destination folders, will be used for WALs
and for data. This may not be populated in case of errors. | | | | +| `serverName` *string* | The server name on S3, the cluster name is used if this
parameter is omitted | | | | +| `encryption` *string* | Encryption method required to S3 API | | | | +| `backupId` *string* | The ID of the Barman backup | | | | +| `backupName` *string* | The Name of the Barman backup | | | | +| `phase` *[BackupPhase](#backupphase)* | The last backup status | | | | +| `startedAt` *[Time](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#time-v1-meta)* | When the backup execution was started by the backup tool | | | | +| `stoppedAt` *[Time](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#time-v1-meta)* | When the backup execution was terminated by the backup tool | | | | +| `reconciliationStartedAt` *[Time](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#time-v1-meta)* | When the backup process was started by the operator | | | | +| `reconciliationTerminatedAt` *[Time](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#time-v1-meta)* | When the reconciliation was terminated by the operator (either successfully or not) | | | | +| `beginWal` *string* | The starting WAL | | | | +| `endWal` *string* | The ending WAL | | | | +| `beginLSN` *string* | The starting xlog | | | | +| `endLSN` *string* | The ending xlog | | | | +| `error` *string* | The detected error | | | | +| `commandOutput` *string* | Unused. Retained for compatibility with old versions. | | | | +| `commandError` *string* | The backup command output in case of error | | | | +| `backupLabelFile` *integer array* | Backup label file content as returned by Postgres in case of online (hot) backups | | | | +| `tablespaceMapFile` *integer array* | Tablespace map file content as returned by Postgres in case of online (hot) backups | | | | +| `instanceID` *[InstanceID](#instanceid)* | Information to identify the instance where the backup has been taken from | | | | +| `snapshotBackupStatus` *[BackupSnapshotStatus](#backupsnapshotstatus)* | Status of the volumeSnapshot backup | | | | +| `method` *[BackupMethod](#backupmethod)* | The backup method being used | | | | +| `online` *boolean* | Whether the backup was online/hot (`true`) or offline/cold (`false`) | | | | +| `pluginMetadata` *object (keys:string, values:string)* | A map containing the plugin metadata | | | | + +#### BackupTarget + +*Underlying type:* *string* + +BackupTarget describes the preferred targets for a backup + +*Appears in:* + +- [BackupConfiguration](#backupconfiguration) +- [BackupSpec](#backupspec) +- [ScheduledBackupSpec](#scheduledbackupspec) + +#### BootstrapConfiguration + +BootstrapConfiguration contains information about how to create the PostgreSQL +cluster. Only a single bootstrap method can be defined among the supported +ones. `initdb` will be used as the bootstrap method if left +unspecified. Refer to the Bootstrap page of the documentation for more +information. + +*Appears in:* + +- [ClusterSpec](#clusterspec) + +| Field | Description | Required | Default | Validation | +| ----------------------------------------------------------------- | --------------------------------------------------------------------------------------------- | -------- | ------- | ---------- | +| `initdb` *[BootstrapInitDB](#bootstrapinitdb)* | Bootstrap the cluster via initdb | | | | +| `recovery` *[BootstrapRecovery](#bootstraprecovery)* | Bootstrap the cluster from a backup | | | | +| `pg_basebackup` *[BootstrapPgBaseBackup](#bootstrappgbasebackup)* | Bootstrap the cluster taking a physical backup of another compatible
PostgreSQL instance | | | | + +#### BootstrapInitDB + +BootstrapInitDB is the configuration of the bootstrap process when +initdb is used +Refer to the Bootstrap page of the documentation for more information. + +*Appears in:* + +- [BootstrapConfiguration](#bootstrapconfiguration) + +| Field | Description | Required | Default | Validation | +| ---------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ------------------------------------- | +| `database` *string* | Name of the database used by the application. Default: `app`. | | | | +| `owner` *string* | Name of the owner of the database in the instance to be used
by applications. Defaults to the value of the `database` key. | | | | +| `secret` *[LocalObjectReference](https://pkg.go.dev/github.com/cloudnative-pg/machinery/pkg/api#LocalObjectReference)* | Name of the secret containing the initial credentials for the
owner of the user database. If empty a new secret will be
created from scratch | | | | +| `redwood` *boolean* | If we need to enable/disable Redwood compatibility. Requires
EPAS and for EPAS defaults to true | | | | +| `options` *string array* | The list of options that must be passed to initdb when creating the cluster.
Deprecated: This could lead to inconsistent configurations,
please use the explicit provided parameters instead.
If defined, explicit values will be ignored. | | | | +| `dataChecksums` *boolean* | Whether the `-k` option should be passed to initdb,
enabling checksums on data pages (default: `false`) | | | | +| `encoding` *string* | The value to be passed as option `--encoding` for initdb (default:`UTF8`) | | | | +| `localeCollate` *string* | The value to be passed as option `--lc-collate` for initdb (default:`C`) | | | | +| `localeCType` *string* | The value to be passed as option `--lc-ctype` for initdb (default:`C`) | | | | +| `locale` *string* | Sets the default collation order and character classification in the new database. | | | | +| `localeProvider` *string* | This option sets the locale provider for databases created in the new cluster.
Available from PostgreSQL 16. | | | | +| `icuLocale` *string* | Specifies the ICU locale when the ICU provider is used.
This option requires `localeProvider` to be set to `icu`.
Available from PostgreSQL 15. | | | | +| `icuRules` *string* | Specifies additional collation rules to customize the behavior of the default collation.
This option requires `localeProvider` to be set to `icu`.
Available from PostgreSQL 16. | | | | +| `builtinLocale` *string* | Specifies the locale name when the builtin provider is used.
This option requires `localeProvider` to be set to `builtin`.
Available from PostgreSQL 17. | | | | +| `walSegmentSize` *integer* | The value in megabytes (1 to 1024) to be passed to the `--wal-segsize`
option for initdb (default: empty, resulting in PostgreSQL default: 16MB) | | | Maximum: 1024
Minimum: 1
| +| `postInitSQL` *string array* | List of SQL queries to be executed as a superuser in the `postgres`
database right after the cluster has been created - to be used with extreme care
(by default empty) | | | | +| `postInitApplicationSQL` *string array* | List of SQL queries to be executed as a superuser in the application
database right after the cluster has been created - to be used with extreme care
(by default empty) | | | | +| `postInitTemplateSQL` *string array* | List of SQL queries to be executed as a superuser in the `template1`
database right after the cluster has been created - to be used with extreme care
(by default empty) | | | | +| `import` *[Import](#import)* | Bootstraps the new cluster by importing data from an existing PostgreSQL
instance using logical backup (`pg_dump` and `pg_restore`) | | | | +| `postInitApplicationSQLRefs` *[SQLRefs](#sqlrefs)* | List of references to ConfigMaps or Secrets containing SQL files
to be executed as a superuser in the application database right after
the cluster has been created. The references are processed in a specific order:
first, all Secrets are processed, followed by all ConfigMaps.
Within each group, the processing order follows the sequence specified
in their respective arrays.
(by default empty) | | | | +| `postInitTemplateSQLRefs` *[SQLRefs](#sqlrefs)* | List of references to ConfigMaps or Secrets containing SQL files
to be executed as a superuser in the `template1` database right after
the cluster has been created. The references are processed in a specific order:
first, all Secrets are processed, followed by all ConfigMaps.
Within each group, the processing order follows the sequence specified
in their respective arrays.
(by default empty) | | | | +| `postInitSQLRefs` *[SQLRefs](#sqlrefs)* | List of references to ConfigMaps or Secrets containing SQL files
to be executed as a superuser in the `postgres` database right after
the cluster has been created. The references are processed in a specific order:
first, all Secrets are processed, followed by all ConfigMaps.
Within each group, the processing order follows the sequence specified
in their respective arrays.
(by default empty) | | | | + +#### BootstrapPgBaseBackup + +BootstrapPgBaseBackup contains the configuration required to take +a physical backup of an existing PostgreSQL cluster + +*Appears in:* + +- [BootstrapConfiguration](#bootstrapconfiguration) + +| Field | Description | Required | Default | Validation | +| ---------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | -------- | ------- | ------------------- | +| `source` *string* | The name of the server of which we need to take a physical backup | True | | MinLength: 1
| +| `database` *string* | Name of the database used by the application. Default: `app`. | | | | +| `owner` *string* | Name of the owner of the database in the instance to be used
by applications. Defaults to the value of the `database` key. | | | | +| `secret` *[LocalObjectReference](https://pkg.go.dev/github.com/cloudnative-pg/machinery/pkg/api#LocalObjectReference)* | Name of the secret containing the initial credentials for the
owner of the user database. If empty a new secret will be
created from scratch | | | | + +#### BootstrapRecovery + +BootstrapRecovery contains the configuration required to restore +from an existing cluster using 3 methodologies: external cluster, +volume snapshots or backup objects. Full recovery and Point-In-Time +Recovery are supported. +The method can be also be used to create clusters in continuous recovery +(replica clusters), also supporting cascading replication when `instances` > + +1. Once the cluster exits recovery, the password for the superuser + will be changed through the provided secret. + Refer to the Bootstrap page of the documentation for more information. + +*Appears in:* + +- [BootstrapConfiguration](#bootstrapconfiguration) + +| Field | Description | Required | Default | Validation | +| ---------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ---------- | +| `backup` *[BackupSource](#backupsource)* | The backup object containing the physical base backup from which to
initiate the recovery procedure.
Mutually exclusive with `source` and `volumeSnapshots`. | | | | +| `source` *string* | The external cluster whose backup we will restore. This is also
used as the name of the folder under which the backup is stored,
so it must be set to the name of the source cluster
Mutually exclusive with `backup`. | | | | +| `volumeSnapshots` *[DataSource](#datasource)* | The static PVC data source(s) from which to initiate the
recovery procedure. Currently supporting `VolumeSnapshot`
and `PersistentVolumeClaim` resources that map an existing
PVC group, compatible with {{name.ln}}, and taken with
a cold backup copy on a fenced Postgres instance (limitation
which will be removed in the future when online backup
will be implemented).
Mutually exclusive with `backup`. | | | | +| `recoveryTarget` *[RecoveryTarget](#recoverytarget)* | By default, the recovery process applies all the available
WAL files in the archive (full recovery). However, you can also
end the recovery as soon as a consistent state is reached or
recover to a point-in-time (PITR) by specifying a `RecoveryTarget` object,
as expected by PostgreSQL (i.e., timestamp, transaction Id, LSN, ...).
More info: | | | | +| `database` *string* | Name of the database used by the application. Default: `app`. | | | | +| `owner` *string* | Name of the owner of the database in the instance to be used
by applications. Defaults to the value of the `database` key. | | | | +| `secret` *[LocalObjectReference](https://pkg.go.dev/github.com/cloudnative-pg/machinery/pkg/api#LocalObjectReference)* | Name of the secret containing the initial credentials for the
owner of the user database. If empty a new secret will be
created from scratch | | | | + +#### CatalogComponentImage + +CatalogComponentImage is a named image entry for a non-PostgreSQL component. + +*Appears in:* + +- [ImageCatalogSpec](#imagecatalogspec) + +| Field | Description | Required | Default | Validation | +| ---------------- | --------------------------------------------------------------- | -------- | ------- | --------------------------------------------------------------------- | +| `key` *string* | Key is the unique identifier for this image within the catalog. | True | | MaxLength: 63
Pattern: `^[a-z0-9]([-a-z0-9]*[a-z0-9])?$`
| +| `image` *string* | Image is the container image reference. | True | | | + +#### CatalogImage + +CatalogImage defines the image and major version + +*Appears in:* + +- [ImageCatalogSpec](#imagecatalogspec) + +| Field | Description | Required | Default | Validation | +| ---------------------------------------------------------------------- | ----------------------------------------------------------------------------- | -------- | ------- | ------------------ | +| `image` *string* | The image reference | True | | | +| `major` *integer* | The PostgreSQL major version of the image. Must be unique within the catalog. | True | | Minimum: 10
| +| `extensions` *[ExtensionConfiguration](#extensionconfiguration) array* | The configuration of the extensions to be added | | | | + +#### CertificatesConfiguration + +CertificatesConfiguration contains the needed configurations to handle server certificates. + +*Appears in:* + +- [CertificatesStatus](#certificatesstatus) +- [ClusterSpec](#clusterspec) + +| Field | Description | Required | Default | Validation | +| ---------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ---------- | +| `serverCASecret` *string* | The secret containing the Server CA certificate. If not defined, a new secret will be created
with a self-signed CA and will be used to generate the TLS certificate ServerTLSSecret.

Contains:

- `ca.crt`: CA that should be used to validate the server certificate,
used as `sslrootcert` in client connection strings.
- `ca.key`: key used to generate Server SSL certs, if ServerTLSSecret is provided,
this can be omitted.
| | | | +| `serverTLSSecret` *string* | The secret of type kubernetes.io/tls containing the server TLS certificate and key that will be set as
`ssl_cert_file` and `ssl_key_file` so that clients can connect to postgres securely.
If not defined, ServerCASecret must provide also `ca.key` and a new secret will be
created using the provided CA. | | | | +| `replicationTLSSecret` *string* | The secret of type kubernetes.io/tls containing the client certificate to authenticate as
the `streaming_replica` user.
If not defined, ClientCASecret must provide also `ca.key`, and a new secret will be
created using the provided CA. | | | | +| `clientCASecret` *string* | The secret containing the Client CA certificate. If not defined, a new secret will be created
with a self-signed CA and will be used to generate all the client certificates.

Contains:

- `ca.crt`: CA that should be used to validate the client certificates,
used as `ssl_ca_file` of all the instances.
- `ca.key`: key used to generate client certificates, if ReplicationTLSSecret is provided,
this can be omitted.
| | | | +| `serverAltDNSNames` *string array* | The list of the server alternative DNS names to be added to the generated server TLS certificates, when required. | | | | + +#### CertificatesStatus + +CertificatesStatus contains configuration certificates and related expiration dates. + +*Appears in:* + +- [ClusterStatus](#clusterstatus) + +| Field | Description | Required | Default | Validation | +| --------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ---------- | +| `serverCASecret` *string* | The secret containing the Server CA certificate. If not defined, a new secret will be created
with a self-signed CA and will be used to generate the TLS certificate ServerTLSSecret.

Contains:

- `ca.crt`: CA that should be used to validate the server certificate,
used as `sslrootcert` in client connection strings.
- `ca.key`: key used to generate Server SSL certs, if ServerTLSSecret is provided,
this can be omitted.
| | | | +| `serverTLSSecret` *string* | The secret of type kubernetes.io/tls containing the server TLS certificate and key that will be set as
`ssl_cert_file` and `ssl_key_file` so that clients can connect to postgres securely.
If not defined, ServerCASecret must provide also `ca.key` and a new secret will be
created using the provided CA. | | | | +| `replicationTLSSecret` *string* | The secret of type kubernetes.io/tls containing the client certificate to authenticate as
the `streaming_replica` user.
If not defined, ClientCASecret must provide also `ca.key`, and a new secret will be
created using the provided CA. | | | | +| `clientCASecret` *string* | The secret containing the Client CA certificate. If not defined, a new secret will be created
with a self-signed CA and will be used to generate all the client certificates.

Contains:

- `ca.crt`: CA that should be used to validate the client certificates,
used as `ssl_ca_file` of all the instances.
- `ca.key`: key used to generate client certificates, if ReplicationTLSSecret is provided,
this can be omitted.
| | | | +| `serverAltDNSNames` *string array* | The list of the server alternative DNS names to be added to the generated server TLS certificates, when required. | | | | +| `expirations` *object (keys:string, values:string)* | Expiration dates for all certificates. | | | | + +#### ClientCertificateConfiguration + +ClientCertificateConfiguration configures operator-managed issuance of a TLS +client certificate for a DatabaseRole. + +*Appears in:* + +- [DatabaseRoleSpec](#databaserolespec) + +| Field | Description | Required | Default | Validation | +| ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ---------- | +| `enabled` *boolean* | Enabled turns on client certificate issuance for this role. When true,
the role must have login enabled. Defaults to true when the block is present. | | true | | + +#### ClientCertificateState + +ClientCertificateState holds the observed state of the generated TLS client certificate. + +*Appears in:* + +- [DatabaseRoleStatus](#databaserolestatus) + +| Field | Description | Required | Default | Validation | +| --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ---------- | +| `expiration` *string* | Expiration is the expiration time of the generated client certificate, in RFC3339 format. | | | | +| `message` *string* | Message contains a human-readable explanation of the current certificate status,
such as why issuance was skipped or why an existing Secret was left untouched. | | | | + +#### Cluster + +Cluster defines the API schema for a highly available PostgreSQL database cluster +managed by {{name.ln}}. + +| Field | Description | Required | Default | Validation | +| ------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ---------- | +| `apiVersion` *string* | `postgresql.k8s.enterprisedb.io/v1` | True | | | +| `kind` *string* | `Cluster` | True | | | +| `metadata` *[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#objectmeta-v1-meta)* | Refer to Kubernetes API documentation for fields of `metadata`. | True | | | +| `spec` *[ClusterSpec](#clusterspec)* | Specification of the desired behavior of the cluster.
More info: | True | | | +| `status` *[ClusterStatus](#clusterstatus)* | Most recently observed status of the cluster. This data may not be up
to date. Populated by the system. Read-only.
More info: | | | | + +#### ClusterImageCatalog + +ClusterImageCatalog is the Schema for the clusterimagecatalogs API + +| Field | Description | Required | Default | Validation | +| ------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ---------- | +| `apiVersion` *string* | `postgresql.k8s.enterprisedb.io/v1` | True | | | +| `kind` *string* | `ClusterImageCatalog` | True | | | +| `metadata` *[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#objectmeta-v1-meta)* | Refer to Kubernetes API documentation for fields of `metadata`. | True | | | +| `spec` *[ImageCatalogSpec](#imagecatalogspec)* | Specification of the desired behavior of the ClusterImageCatalog.
More info: | True | | | + +#### ClusterMonitoringTLSConfiguration + +ClusterMonitoringTLSConfiguration is the type containing the TLS configuration +for the cluster's monitoring + +*Appears in:* + +- [MonitoringConfiguration](#monitoringconfiguration) + +| Field | Description | Required | Default | Validation | +| ------------------- | -------------------------------------------------------------------------------------------------------- | -------- | ------- | ---------- | +| `enabled` *boolean* | Enable TLS for the monitoring endpoint.
Changing this option will force a rollout of all instances. | | false | | + +#### ClusterSpec + +ClusterSpec defines the desired state of a PostgreSQL cluster managed by +{{name.ln}}. + +*Appears in:* + +- [Cluster](#cluster) + +| Field | Description | Required | Default | Validation | +| --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------------ | ---------------------------------------------------------------------- | +| `description` *string* | Description of this PostgreSQL cluster | | | | +| `inheritedMetadata` *[EmbeddedObjectMetadata](#embeddedobjectmetadata)* | Metadata that will be inherited by all objects related to the Cluster | | | | +| `imageName` *string* | Name of the container image, supporting both tags (`:`)
and digests for deterministic and repeatable deployments
(`:@sha256:`) | | | | +| `imageCatalogRef` *[ImageCatalogRef](#imagecatalogref)* | Defines the major PostgreSQL version we want to use within an ImageCatalog | | | | +| `imagePullPolicy` *[PullPolicy](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#pullpolicy-v1-core)* | Image pull policy.
One of `Always`, `Never` or `IfNotPresent`.
If not defined, it defaults to `IfNotPresent`.
Cannot be updated.
More info: | | | | +| `schedulerName` *string* | If specified, the pod will be dispatched by specified Kubernetes
scheduler. If not specified, the pod will be dispatched by the default
scheduler. More info:
| | | | +| `postgresUID` *integer* | The UID of the `postgres` user inside the image, defaults to `26` | | 26 | | +| `postgresGID` *integer* | The GID of the `postgres` user inside the image, defaults to `26` | | 26 | | +| `instances` *integer* | Number of instances required in the cluster | True | 1 | Minimum: 1
| +| `minSyncReplicas` *integer* | Minimum number of instances required in synchronous replication with the
primary. Undefined or 0 allow writes to complete when no standby is
available. | | 0 | Minimum: 0
| +| `maxSyncReplicas` *integer* | The target value for the synchronous replication quorum, that can be
decreased if the number of ready standbys is lower than this.
Undefined or 0 disable synchronous replication. | | 0 | Minimum: 0
| +| `postgresql` *[PostgresConfiguration](#postgresconfiguration)* | Configuration of the PostgreSQL server | | | | +| `podSelectorRefs` *[PodSelectorRef](#podselectorref) array* | PodSelectorRefs defines named pod label selectors that can be referenced
in pg_hba rules using the ${podselector:NAME} syntax in the address field.
The operator resolves matching pod IPs and the instance manager expands
pg_hba lines accordingly. Only pods in the Cluster's own namespace are considered. | | | | +| `replicationSlots` *[ReplicationSlotsConfiguration](#replicationslotsconfiguration)* | Replication slots management configuration | | | | +| `bootstrap` *[BootstrapConfiguration](#bootstrapconfiguration)* | Instructions to bootstrap this cluster | | | | +| `replica` *[ReplicaClusterConfiguration](#replicaclusterconfiguration)* | Replica cluster configuration | | | | +| `superuserSecret` *[LocalObjectReference](https://pkg.go.dev/github.com/cloudnative-pg/machinery/pkg/api#LocalObjectReference)* | The secret containing the superuser password. If not defined a new
secret will be created with a randomly generated password | | | | +| `enableSuperuserAccess` *boolean* | When this option is enabled, the operator will use the `SuperuserSecret`
to update the `postgres` user password (if the secret is
not present, the operator will automatically create one). When this
option is disabled, the operator will ignore the `SuperuserSecret` content, delete
it when automatically created, and then blank the password of the `postgres`
user by setting it to `NULL`. Disabled by default. | | | | +| `certificates` *[CertificatesConfiguration](#certificatesconfiguration)* | The configuration for the CA and related certificates | | | | +| `imagePullSecrets` *[LocalObjectReference](https://pkg.go.dev/github.com/cloudnative-pg/machinery/pkg/api#LocalObjectReference) array* | The list of pull secrets to be used to pull the images. If the license key
contains a pull secret that secret will be automatically included. | | | | +| `storage` *[StorageConfiguration](#storageconfiguration)* | Configuration of the storage of the instances | | | | +| `serviceAccountTemplate` *[ServiceAccountTemplate](#serviceaccounttemplate)* | Configure the generation of the service account | | | | +| `serviceAccountName` *string* | Name of an existing ServiceAccount in the same namespace to use for the cluster.
When specified, the operator will not create a new ServiceAccount
but will use the provided one. This is useful for sharing a single
ServiceAccount across multiple clusters (e.g., for cloud IAM configurations).
If not specified, a ServiceAccount will be created with the cluster name.
Mutually exclusive with ServiceAccountTemplate. | | | MaxLength: 253
Pattern: `^[a-z0-9]([-a-z0-9]*[a-z0-9])?$`
| +| `walStorage` *[StorageConfiguration](#storageconfiguration)* | Configuration of the storage for PostgreSQL WAL (Write-Ahead Log) | | | | +| `ephemeralVolumeSource` *[EphemeralVolumeSource](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#ephemeralvolumesource-v1-core)* | EphemeralVolumeSource allows the user to configure the source of ephemeral volumes. | | | | +| `startDelay` *integer* | The time in seconds that is allowed for a PostgreSQL instance to
successfully start up (default 3600).
The startup probe failure threshold is derived from this value using the formula:
ceiling(startDelay / 10). | | 3600 | | +| `stopDelay` *integer* | The time in seconds that is allowed for a PostgreSQL instance to
gracefully shutdown (default 1800) | | 1800 | | +| `smartStopDelay` *integer* | Deprecated: please use SmartShutdownTimeout instead | | | | +| `smartShutdownTimeout` *integer* | The time in seconds that controls the window of time reserved for the smart shutdown of Postgres to complete.
Make sure you reserve enough time for the operator to request a fast shutdown of Postgres
(that is: `stopDelay` - `smartShutdownTimeout`). Default is 180 seconds. | | 180 | | +| `switchoverDelay` *integer* | The time in seconds that is allowed for a primary PostgreSQL instance
to gracefully shutdown during a switchover.
Default value is 3600 seconds (1 hour). | | 3600 | | +| `failoverDelay` *integer* | The amount of time (in seconds) to wait before triggering a failover
after the primary PostgreSQL instance in the cluster was detected
to be unhealthy | | 0 | | +| `livenessProbeTimeout` *integer* | LivenessProbeTimeout is the time (in seconds) that is allowed for a PostgreSQL instance
to successfully respond to the liveness probe (default 30).
The Liveness probe failure threshold is derived from this value using the formula:
ceiling(livenessProbe / 10). | | | | +| `affinity` *[AffinityConfiguration](#affinityconfiguration)* | Affinity/Anti-affinity rules for Pods | | | | +| `topologySpreadConstraints` *[TopologySpreadConstraint](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#topologyspreadconstraint-v1-core) array* | TopologySpreadConstraints specifies how to spread matching pods among the given topology.
More info:
| | | | +| `resources` *[ResourceRequirements](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#resourcerequirements-v1-core)* | Resources requirements of every generated Pod. Please refer to

for more information. | | | | +| `ephemeralVolumesSizeLimit` *[EphemeralVolumesSizeLimitConfiguration](#ephemeralvolumessizelimitconfiguration)* | EphemeralVolumesSizeLimit allows the user to set the limits for the ephemeral
volumes | | | | +| `priorityClassName` *string* | Name of the priority class which will be used in every generated Pod, if the PriorityClass
specified does not exist, the pod will not be able to schedule. Please refer to

for more information | | | | +| `primaryUpdateStrategy` *[PrimaryUpdateStrategy](#primaryupdatestrategy)* | Deployment strategy to follow to upgrade the primary server during a rolling
update procedure, after all replicas have been successfully updated:
it can be automated (`unsupervised` - default) or manual (`supervised`) | | unsupervised | Enum: [unsupervised supervised]
| +| `primaryUpdateMethod` *[PrimaryUpdateMethod](#primaryupdatemethod)* | Method to follow to upgrade the primary server during a rolling
update procedure, after all replicas have been successfully updated:
it can be with a switchover (`switchover`) or in-place (`restart` - default).
Note: when using `switchover`, the operator will reject updates that change both
the image name and PostgreSQL configuration parameters simultaneously to avoid
configuration mismatches during the switchover process. | | | Enum: [switchover restart]
| +| `backup` *[BackupConfiguration](#backupconfiguration)* | The configuration to be used for backups | | | | +| `nodeMaintenanceWindow` *[NodeMaintenanceWindow](#nodemaintenancewindow)* | Define a maintenance window for the Kubernetes nodes | | | | +| `licenseKey` *string* | The license key of the cluster. When empty, the cluster operates in
trial mode and after the expiry date (default 30 days) the operator
will cease any reconciliation attempt. For details, please refer to
the license agreement that comes with the operator. | | | | +| `licenseKeySecret` *[SecretKeySelector](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#secretkeyselector-v1-core)* | The reference to the license key. When this is set it take precedence over LicenseKey. | | | | +| `monitoring` *[MonitoringConfiguration](#monitoringconfiguration)* | The configuration of the monitoring infrastructure of this cluster | | | | +| `externalClusters` *[ExternalCluster](#externalcluster) array* | The list of external clusters which are used in the configuration | | | | +| `logLevel` *string* | The instances' log level, one of the following values: error, warning, info (default), debug, trace | | info | Enum: [error warning info debug trace]
| +| `projectedVolumeTemplate` *[ProjectedVolumeSource](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#projectedvolumesource-v1-core)* | Template to be used to define projected volumes, projected volumes will be mounted
under `/projected` base folder | | | | +| `env` *[EnvVar](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#envvar-v1-core) array* | Env follows the Env format to pass environment variables
to the pods created in the cluster | | | | +| `envFrom` *[EnvFromSource](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#envfromsource-v1-core) array* | EnvFrom follows the EnvFrom format to pass environment variables
sources to the pods to be used by Env | | | | +| `managed` *[ManagedConfiguration](#managedconfiguration)* | The configuration that is used by the portions of PostgreSQL that are managed by the instance manager | | | | +| `seccompProfile` *[SeccompProfile](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#seccompprofile-v1-core)* | The SeccompProfile applied to every Pod and Container.
Defaults to: `RuntimeDefault` | | | | +| `podSecurityContext` *[PodSecurityContext](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#podsecuritycontext-v1-core)* | Override the PodSecurityContext applied to every Pod of the cluster.
When set, this overrides the operator's default PodSecurityContext for the cluster.
If omitted, the operator defaults are used.
This field doesn't have any effect if SecurityContextConstraints are present. | | | | +| `securityContext` *[SecurityContext](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#securitycontext-v1-core)* | Override the SecurityContext applied to every Container in the Pod of the cluster.
When set, this overrides the operator's default Container SecurityContext.
If omitted, the operator defaults are used. | | | | +| `tablespaces` *[TablespaceConfiguration](#tablespaceconfiguration) array* | The tablespaces configuration | | | | +| `enablePDB` *boolean* | Manage the `PodDisruptionBudget` resources within the cluster. When
configured as `true` (default setting), the pod disruption budgets
will safeguard the primary node from being terminated. Conversely,
setting it to `false` will result in the absence of any
`PodDisruptionBudget` resource, permitting the shutdown of all nodes
hosting the PostgreSQL cluster. This latter configuration is
advisable for any PostgreSQL cluster employed for
development/staging purposes. | | true | | +| `plugins` *[PluginConfiguration](#pluginconfiguration) array* | The plugins configuration, containing
any plugin to be loaded with the corresponding configuration | | | | +| `probes` *[ProbesConfiguration](#probesconfiguration)* | The configuration of the probes to be injected
in the PostgreSQL Pods. | | | | +| `primaryLease` *[PrimaryLeaseConfiguration](#primaryleaseconfiguration)* | Configuration of the Kubernetes `Lease` used to coordinate safe primary
election within the cluster. When omitted, the operator applies built-in
defaults; tune these values only if you understand the consequences for
failover timing. | | | | + +#### ClusterStatus + +ClusterStatus defines the observed state of a PostgreSQL cluster managed by +{{name.ln}}. + +*Appears in:* + +- [Cluster](#cluster) + +| Field | Description | Required | Default | Validation | +| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ---------- | +| `instances` *integer* | The total number of PVC Groups detected in the cluster. It may differ from the number of existing instance pods. | | | | +| `readyInstances` *integer* | The total number of ready instances in the cluster. It is equal to the number of ready instance pods. | | | | +| `selector` *string* | Selector is the serialized form of the label selector that identifies
the pods managed by this cluster. Populated by the operator and exposed
through the scale sub-resource so an autoscaler (such as HPA or VPA)
can discover the managed instance pods. | | | | +| `instancesStatus` *object (keys:[PodStatus](#podstatus), values:string array)* | InstancesStatus indicates in which status the instances are | | | | +| `instancesReportedState` *object (keys:[PodName](#podname), values:[InstanceReportedState](#instancereportedstate))* | The reported state of the instances during the last reconciliation loop | | | | +| `managedRolesStatus` *[ManagedRoles](#managedroles)* | ManagedRolesStatus reports the state of the managed roles in the cluster | | | | +| `tablespacesStatus` *[TablespaceState](#tablespacestate) array* | TablespacesStatus reports the state of the declarative tablespaces in the cluster | | | | +| `podSelectorRefs` *[PodSelectorRefStatus](#podselectorrefstatus) array* | PodSelectorRefs contains the resolved pod IPs for each named selector
defined in spec.podSelectorRefs. | | | | +| `timelineID` *integer* | The timeline of the Postgres cluster | | | | +| `topology` *[Topology](#topology)* | Instances topology. | | | | +| `latestGeneratedNode` *integer* | ID of the latest generated node (used to avoid node name clashing)
Deprecated: this field is not set anymore | | | | +| `currentPrimary` *string* | Current primary instance | | | | +| `targetPrimary` *string* | Target primary instance, this is different from the previous one
during a switchover or a failover | | | | +| `lastPromotionToken` *string* | LastPromotionToken is the last verified promotion token that
was used to promote a replica cluster | | | | +| `pvcCount` *integer* | How many PVCs have been created by this cluster | | | | +| `jobCount` *integer* | How many Jobs have been created by this cluster | | | | +| `danglingPVC` *string array* | List of all the PVCs created by this cluster and still available
which are not attached to a Pod | | | | +| `resizingPVC` *string array* | List of all the PVCs that have ResizingPVC condition. | | | | +| `initializingPVC` *string array* | List of all the PVCs that are being initialized by this cluster | | | | +| `healthyPVC` *string array* | List of all the PVCs not dangling nor initializing | | | | +| `unusablePVC` *string array* | List of all the PVCs that are unusable because another PVC is missing | | | | +| `licenseStatus` *[Status](#status)* | Status of the license | | | | +| `writeService` *string* | Current write pod | | | | +| `readService` *string* | Current list of read pods | | | | +| `phase` *string* | Current phase of the cluster | | | | +| `phaseReason` *string* | Reason for the current phase | | | | +| `secretsResourceVersion` *[SecretsResourceVersion](#secretsresourceversion)* | The list of resource versions of the secrets
managed by the operator. Every change here is done in the
interest of the instance manager, which will refresh the
secret data | | | | +| `configMapResourceVersion` *[ConfigMapResourceVersion](#configmapresourceversion)* | The list of resource versions of the configmaps,
managed by the operator. Every change here is done in the
interest of the instance manager, which will refresh the
configmap data | | | | +| `certificates` *[CertificatesStatus](#certificatesstatus)* | The configuration for the CA and related certificates, initialized with defaults. | | | | +| `firstRecoverabilityPoint` *string* | The first recoverability point, stored as a date in RFC3339 format.
This field is calculated from the content of FirstRecoverabilityPointByMethod.
Deprecated: the field is not set for backup plugins. | | | | +| `firstRecoverabilityPointByMethod` *object (keys:[BackupMethod](#backupmethod), values:[Time](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#time-v1-meta))* | The first recoverability point, stored as a date in RFC3339 format, per backup method type.
Deprecated: the field is not set for backup plugins. | | | | +| `lastSuccessfulBackup` *string* | Last successful backup, stored as a date in RFC3339 format.
This field is calculated from the content of LastSuccessfulBackupByMethod.
Deprecated: the field is not set for backup plugins. | | | | +| `lastSuccessfulBackupByMethod` *object (keys:[BackupMethod](#backupmethod), values:[Time](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#time-v1-meta))* | Last successful backup, stored as a date in RFC3339 format, per backup method type.
Deprecated: the field is not set for backup plugins. | | | | +| `lastFailedBackup` *string* | Last failed backup, stored as a date in RFC3339 format.
Deprecated: the field is not set for backup plugins. | | | | +| `cloudNativePostgresqlCommitHash` *string* | The commit hash number of which this operator running | | | | +| `currentPrimaryTimestamp` *string* | The timestamp when the last actual promotion to primary has occurred | | | | +| `currentPrimaryFailingSinceTimestamp` *string* | The timestamp when the primary was detected to be unhealthy
This field is reported when `.spec.failoverDelay` is populated or during online upgrades | | | | +| `targetPrimaryTimestamp` *string* | The timestamp when the last request for a new primary has occurred | | | | +| `poolerIntegrations` *[PoolerIntegrations](#poolerintegrations)* | The integration needed by poolers referencing the cluster | | | | +| `cloudNativePostgresqlOperatorHash` *string* | The hash of the binary of the operator | | | | +| `operatorCertificateFingerprint` *string* | OperatorCertificateFingerprint is the SHA256 fingerprint of the operator's
in-memory client certificate public key. The instance manager pins this
fingerprint to authenticate requests from the operator. | | | | +| `availableArchitectures` *[AvailableArchitecture](#availablearchitecture) array* | AvailableArchitectures reports the available architectures of a cluster | | | | +| `conditions` *[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#condition-v1-meta) array* | Conditions for cluster object | | | | +| `instanceNames` *string array* | List of instance names in the cluster | | | | +| `onlineUpdateEnabled` *boolean* | OnlineUpdateEnabled shows if the online upgrade is enabled inside the cluster | | | | +| `image` *string* | Image contains the image name used by the pods | | | | +| `pgDataImageInfo` *[ImageInfo](#imageinfo)* | PGDataImageInfo contains the details of the latest image that has run on the current data directory. | | | | +| `targetPgDataImageInfo` *[ImageInfo](#imageinfo)* | TargetPGDataImageInfo contains the details of the target image for an
in-progress major upgrade. It is set before the upgrade Job is created,
and cleared on successful completion or when the upgrade is rolled back. | | | | +| `pluginStatus` *[PluginStatus](#pluginstatus) array* | PluginStatus is the status of the loaded plugins | | | | +| `switchReplicaClusterStatus` *[SwitchReplicaClusterStatus](#switchreplicaclusterstatus)* | SwitchReplicaClusterStatus is the status of the switch to replica cluster | | | | +| `demotionToken` *string* | DemotionToken is a JSON token containing the information
from pg_controldata such as Database system identifier, Latest checkpoint's
TimeLineID, Latest checkpoint's REDO location, Latest checkpoint's REDO
WAL file, and Time of latest checkpoint | | | | +| `systemID` *string* | SystemID is the latest detected PostgreSQL SystemID | | | | + +#### ConfigMapResourceVersion + +ConfigMapResourceVersion is the resource versions of the secrets +managed by the operator + +*Appears in:* + +- [ClusterStatus](#clusterstatus) + +| Field | Description | Required | Default | Validation | +| ----------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ---------- | +| `metrics` *object (keys:string, values:string)* | A map with the versions of all the config maps used to pass metrics.
Map keys are the config map names, map values are the versions | | | | + +#### DataDurabilityLevel + +*Underlying type:* *string* + +DataDurabilityLevel specifies how strictly to enforce synchronous replication +when cluster instances are unavailable. Options are `required` or `preferred`. + +*Appears in:* + +- [SynchronousReplicaConfiguration](#synchronousreplicaconfiguration) + +| Field | Description | +| ----------- | ----------------------------------------------------------------------------------------------------------------------- | +| `required` | DataDurabilityLevelRequired means that data durability is strictly enforced
| +| `preferred` | DataDurabilityLevelPreferred means that data durability is enforced
only when healthy replicas are available
| + +#### DataSource + +DataSource contains the configuration required to bootstrap a +PostgreSQL cluster from an existing storage + +*Appears in:* + +- [BootstrapRecovery](#bootstraprecovery) + +| Field | Description | Required | Default | Validation | +| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------- | -------- | ------- | ---------- | +| `storage` *[TypedLocalObjectReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#typedlocalobjectreference-v1-core)* | Configuration of the storage of the instances | True | | | +| `walStorage` *[TypedLocalObjectReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#typedlocalobjectreference-v1-core)* | Configuration of the storage for PostgreSQL WAL (Write-Ahead Log) | | | | +| `tablespaceStorage` *object (keys:string, values:[TypedLocalObjectReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#typedlocalobjectreference-v1-core))* | Configuration of the storage for PostgreSQL tablespaces | | | | + +#### Database + +Database is the Schema for the databases API + +| Field | Description | Required | Default | Validation | +| ------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ---------- | +| `apiVersion` *string* | `postgresql.k8s.enterprisedb.io/v1` | True | | | +| `kind` *string* | `Database` | True | | | +| `metadata` *[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#objectmeta-v1-meta)* | Refer to Kubernetes API documentation for fields of `metadata`. | True | | | +| `spec` *[DatabaseSpec](#databasespec)* | Specification of the desired Database.
More info: | True | | | +| `status` *[DatabaseStatus](#databasestatus)* | Most recently observed status of the Database. This data may not be up to
date. Populated by the system. Read-only.
More info: | | | | + +#### DatabaseObjectSpec + +DatabaseObjectSpec contains the fields which are common to every +database object + +*Appears in:* + +- [ExtensionSpec](#extensionspec) +- [FDWSpec](#fdwspec) +- [SchemaSpec](#schemaspec) +- [ServerSpec](#serverspec) + +| Field | Description | Required | Default | Validation | +| ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ----------------------------- | +| `name` *string* | Name of the object (extension, schema, FDW, server) | True | | | +| `ensure` *[EnsureOption](#ensureoption)* | Specifies whether an object (e.g schema) should be present or absent
in the database. If set to `present`, the object will be created if
it does not exist. If set to `absent`, the extension/schema will be
removed if it exists. | | present | Enum: [present absent]
| + +#### DatabaseObjectStatus + +DatabaseObjectStatus is the status of the managed database objects + +*Appears in:* + +- [DatabaseStatus](#databasestatus) + +| Field | Description | Required | Default | Validation | +| ------------------- | ----------------------------------------------------------------------- | -------- | ------- | ---------- | +| `name` *string* | The name of the object | True | | | +| `applied` *boolean* | True of the object has been installed successfully in
the database | True | | | +| `message` *string* | Message is the object reconciliation message | | | | + +#### DatabaseReclaimPolicy + +*Underlying type:* *string* + +DatabaseReclaimPolicy describes a policy for end-of-life maintenance of databases. + +*Appears in:* + +- [DatabaseSpec](#databasespec) + +| Field | Description | +| -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `delete` | DatabaseReclaimDelete means the database will be deleted from its PostgreSQL Cluster on release
from its claim.
| +| `retain` | DatabaseReclaimRetain means the database will be left in its current phase for manual
reclamation by the administrator. The default policy is Retain.
| + +#### DatabaseRole + +DatabaseRole is the Schema for the databaseroles API + +*Appears in:* + +- [DatabaseRoleList](#databaserolelist) + +| Field | Description | Required | Default | Validation | +| ------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ---------- | +| `apiVersion` *string* | `postgresql.k8s.enterprisedb.io/v1` | True | | | +| `kind` *string* | `DatabaseRole` | True | | | +| `metadata` *[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#objectmeta-v1-meta)* | Refer to Kubernetes API documentation for fields of `metadata`. | True | | | +| `spec` *[DatabaseRoleSpec](#databaserolespec)* | Specification of the desired DatabaseRole.
More info: | True | | | +| `status` *[DatabaseRoleStatus](#databaserolestatus)* | Most recently observed status of the DatabaseRole. This data may not be up
to date. Populated by the system. Read-only.
More info: | | | | + +#### DatabaseRoleList + +DatabaseRoleList contains a list of DatabaseRoles + +| Field | Description | Required | Default | Validation | +| -------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------- | -------- | ------- | ---------- | +| `apiVersion` *string* | `postgresql.k8s.enterprisedb.io/v1` | True | | | +| `kind` *string* | `DatabaseRoleList` | True | | | +| `metadata` *[ListMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#listmeta-v1-meta)* | Refer to Kubernetes API documentation for fields of `metadata`. | True | | | +| `items` *[DatabaseRole](#databaserole) array* | | True | | | + +#### DatabaseRoleReclaimPolicy + +*Underlying type:* *string* + +DatabaseRoleReclaimPolicy describes a policy for end-of-life maintenance of Roles. + +*Appears in:* + +- [DatabaseRoleSpec](#databaserolespec) + +| Field | Description | +| -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `delete` | DatabaseRoleReclaimDelete means the Role will be deleted from Kubernetes on release
from its claim.
| +| `retain` | DatabaseRoleReclaimRetain means the Role will be left in its current phase for manual
reclamation by the administrator. The default policy is Retain.
| + +#### DatabaseRoleRef + +DatabaseRoleRef is a reference an a role available inside PostgreSQL + +*Appears in:* + +- [TablespaceConfiguration](#tablespaceconfiguration) + +| Field | Description | Required | Default | Validation | +| --------------- | ----------- | -------- | ------- | ---------- | +| `name` *string* | | | | | + +#### DatabaseRoleSpec + +DatabaseRoleSpec represents a role in Postgres + +*Appears in:* + +- [DatabaseRole](#databaserole) + +| Field | Description | Required | Default | Validation | +| ------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ----------------------------- | +| `name` *string* | Name of the role | True | | | +| `comment` *string* | Description of the role | | | | +| `ensure` *[EnsureOption](#ensureoption)* | Ensure the role is `present` or `absent` - defaults to "present" | | present | Enum: [present absent]
| +| `passwordSecret` *[LocalObjectReference](https://pkg.go.dev/github.com/cloudnative-pg/machinery/pkg/api#LocalObjectReference)* | Secret containing the password of the role (if present).
If null, the password will be ignored unless DisablePassword is set.
When set, the secret must follow the `kubernetes.io/basic-auth` format
and contain both a `username` and a `password` field. | | | | +| `connectionLimit` *integer* | If the role can log in, this specifies how many concurrent
connections the role can make. `-1` (the default) means no limit. | | -1 | | +| `validUntil` *[Time](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#time-v1-meta)* | Date and time after which the role's password is no longer valid.
When omitted, the password will never expire (default). | | | | +| `inRoles` *string array* | List of one or more existing roles to which this role will be
immediately added as a new member. Default empty.
Changes to the list are applied to an existing role through
`GRANT` and `REVOKE` statements, not only at role creation. | | | | +| `inherit` *boolean* | Whether a role "inherits" the privileges of roles it is a member of.
Default is `true`. | | true | | +| `disablePassword` *boolean* | DisablePassword indicates that a role's password should be set to NULL in Postgres | | | | +| `superuser` *boolean* | Whether the role is a `superuser` who can override all access
restrictions within the database - superuser status is dangerous and
should be used only when really needed. You must yourself be a
superuser to create a new superuser. Defaults is `false`. | | | | +| `createdb` *boolean* | When set to `true`, the role being defined will be allowed to create
new databases. Specifying `false` (default) will deny a role the
ability to create databases. | | | | +| `createrole` *boolean* | Whether the role will be permitted to create, alter, drop, comment
on, change the security label for, and grant or revoke membership in
other roles. Default is `false`. | | | | +| `login` *boolean* | Whether the role is allowed to log in. A role having the `login`
attribute can be thought of as a user. Roles without this attribute
are useful for managing database privileges, but are not users in
the usual sense of the word. Default is `false`. | | | | +| `replication` *boolean* | Whether a role is a replication role. A role must have this
attribute (or be a superuser) in order to be able to connect to the
server in replication mode (physical or logical replication) and in
order to be able to create or drop replication slots. A role having
the `replication` attribute is a very highly privileged role, and
should only be used on roles actually used for replication. Default
is `false`. | | | | +| `bypassrls` *boolean* | Whether a role bypasses every row-level security (RLS) policy.
Default is `false`. | | | | +| `cluster` *[LocalObjectReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#localobjectreference-v1-core)* | The corresponding cluster | True | | | +| `databaseRoleReclaimPolicy` *[DatabaseRoleReclaimPolicy](#databaserolereclaimpolicy)* | The policy for end-of-life maintenance of this role | | retain | Enum: [delete retain]
| +| `clientCertificate` *[ClientCertificateConfiguration](#clientcertificateconfiguration)* | ClientCertificate configures the operator to generate and renew a TLS client
certificate for this role, signed by the cluster's client CA. The certificate
is stored in a Secret named `-client-cert`.
Requires login to be true. | | | | + +#### DatabaseRoleStatus + +DatabaseRoleStatus defines the observed state of a DatabaseRole + +*Appears in:* + +- [DatabaseRole](#databaserole) + +| Field | Description | Required | Default | Validation | +| ------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ---------- | +| `observedGeneration` *integer* | A sequence number representing the latest
desired state that was synchronized | | | | +| `applied` *boolean* | Applied is true if the role was reconciled correctly | | | | +| `message` *string* | Message is the reconciliation error message | | | | +| `secretResourceVersion` *string* | SecretResourceVersion is the resource version of the password secret
last applied to the role; a change to it triggers reconciliation. | | | | +| `clientCertificate` *[ClientCertificateState](#clientcertificatestate)* | ClientCertificate holds the observed state of the generated TLS client
certificate, when client certificate issuance is enabled. | | | | +| `conditions` *[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#condition-v1-meta) array* | Conditions for the DatabaseRole object | | | | + +#### DatabaseSpec + +DatabaseSpec is the specification of a Postgresql Database, built around the +`CREATE DATABASE`, `ALTER DATABASE`, and `DROP DATABASE` SQL commands of +PostgreSQL. + +*Appears in:* + +- [Database](#database) + +| Field | Description | Required | Default | Validation | +| ------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ----------------------------- | +| `cluster` *[LocalObjectReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#localobjectreference-v1-core)* | The name of the PostgreSQL cluster hosting the database. | True | | | +| `ensure` *[EnsureOption](#ensureoption)* | Ensure the PostgreSQL database is `present` or `absent` - defaults to "present". | | present | Enum: [present absent]
| +| `name` *string* | The name of the database to create inside PostgreSQL. This setting cannot be changed. | True | | | +| `owner` *string* | Maps to the `OWNER` parameter of `CREATE DATABASE`.
Maps to the `OWNER TO` command of `ALTER DATABASE`.
The role name of the user who owns the database inside PostgreSQL. | True | | | +| `template` *string* | Maps to the `TEMPLATE` parameter of `CREATE DATABASE`. This setting
cannot be changed. The name of the template from which to create
this database. | | | | +| `encoding` *string* | Maps to the `ENCODING` parameter of `CREATE DATABASE`. This setting
cannot be changed. Character set encoding to use in the database. | | | | +| `locale` *string* | Maps to the `LOCALE` parameter of `CREATE DATABASE`. This setting
cannot be changed. Sets the default collation order and character
classification in the new database. | | | | +| `localeProvider` *string* | Maps to the `LOCALE_PROVIDER` parameter of `CREATE DATABASE`. This
setting cannot be changed. This option sets the locale provider for
databases created in the new cluster. Available from PostgreSQL 16. | | | | +| `localeCollate` *string* | Maps to the `LC_COLLATE` parameter of `CREATE DATABASE`. This
setting cannot be changed. | | | | +| `localeCType` *string* | Maps to the `LC_CTYPE` parameter of `CREATE DATABASE`. This setting
cannot be changed. | | | | +| `icuLocale` *string* | Maps to the `ICU_LOCALE` parameter of `CREATE DATABASE`. This
setting cannot be changed. Specifies the ICU locale when the ICU
provider is used. This option requires `localeProvider` to be set to
`icu`. Available from PostgreSQL 15. | | | | +| `icuRules` *string* | Maps to the `ICU_RULES` parameter of `CREATE DATABASE`. This setting
cannot be changed. Specifies additional collation rules to customize
the behavior of the default collation. This option requires
`localeProvider` to be set to `icu`. Available from PostgreSQL 16. | | | | +| `builtinLocale` *string* | Maps to the `BUILTIN_LOCALE` parameter of `CREATE DATABASE`. This
setting cannot be changed. Specifies the locale name when the
builtin provider is used. This option requires `localeProvider` to
be set to `builtin`. Available from PostgreSQL 17. | | | | +| `collationVersion` *string* | Maps to the `COLLATION_VERSION` parameter of `CREATE DATABASE`. This
setting cannot be changed. | | | | +| `isTemplate` *boolean* | Maps to the `IS_TEMPLATE` parameter of `CREATE DATABASE` and `ALTER
DATABASE`. If true, this database is considered a template and can
be cloned by any user with `CREATEDB` privileges. | | | | +| `allowConnections` *boolean* | Maps to the `ALLOW_CONNECTIONS` parameter of `CREATE DATABASE` and
`ALTER DATABASE`. If false then no one can connect to this database. | | | | +| `connectionLimit` *integer* | Maps to the `CONNECTION LIMIT` clause of `CREATE DATABASE` and
`ALTER DATABASE`. How many concurrent connections can be made to
this database. -1 (the default) means no limit. | | | | +| `tablespace` *string* | Maps to the `TABLESPACE` parameter of `CREATE DATABASE`.
Maps to the `SET TABLESPACE` command of `ALTER DATABASE`.
The name of the tablespace (in PostgreSQL) that will be associated
with the new database. This tablespace will be the default
tablespace used for objects created in this database. | | | | +| `databaseReclaimPolicy` *[DatabaseReclaimPolicy](#databasereclaimpolicy)* | The policy for end-of-life maintenance of this database. | | retain | Enum: [delete retain]
| +| `schemas` *[SchemaSpec](#schemaspec) array* | The list of schemas to be managed in the database | | | | +| `extensions` *[ExtensionSpec](#extensionspec) array* | The list of extensions to be managed in the database | | | | +| `fdws` *[FDWSpec](#fdwspec) array* | The list of foreign data wrappers to be managed in the database | | | | +| `servers` *[ServerSpec](#serverspec) array* | The list of foreign servers to be managed in the database | | | | + +#### DatabaseStatus + +DatabaseStatus defines the observed state of Database + +*Appears in:* + +- [Database](#database) + +| Field | Description | Required | Default | Validation | +| ------------------------------------------------------------------ | ---------------------------------------------------------------------------------- | -------- | ------- | ---------- | +| `observedGeneration` *integer* | A sequence number representing the latest
desired state that was synchronized | | | | +| `applied` *boolean* | Applied is true if the database was reconciled correctly | | | | +| `message` *string* | Message is the reconciliation output message | | | | +| `schemas` *[DatabaseObjectStatus](#databaseobjectstatus) array* | Schemas is the status of the managed schemas | | | | +| `extensions` *[DatabaseObjectStatus](#databaseobjectstatus) array* | Extensions is the status of the managed extensions | | | | +| `fdws` *[DatabaseObjectStatus](#databaseobjectstatus) array* | FDWs is the status of the managed FDWs | | | | +| `servers` *[DatabaseObjectStatus](#databaseobjectstatus) array* | Servers is the status of the managed servers | | | | + +#### EPASConfiguration + +EPASConfiguration contains EDB Postgres Advanced Server specific configurations + +*Appears in:* + +- [PostgresConfiguration](#postgresconfiguration) + +| Field | Description | Required | Default | Validation | +| --------------------------------------------- | --------------------------------- | -------- | ------- | ---------- | +| `audit` *boolean* | If true enables edb_audit logging | | | | +| `tde` *[TDEConfiguration](#tdeconfiguration)* | TDE configuration | | | | + +#### EmbeddedObjectMetadata + +EmbeddedObjectMetadata contains metadata to be inherited by all resources related to a Cluster + +*Appears in:* + +- [ClusterSpec](#clusterspec) + +| Field | Description | Required | Default | Validation | +| --------------------------------------------------- | ----------- | -------- | ------- | ---------- | +| `labels` *object (keys:string, values:string)* | | | | | +| `annotations` *object (keys:string, values:string)* | | | | | + +#### EnsureOption + +*Underlying type:* *string* + +EnsureOption represents whether we should enforce the presence or absence of +a Role in a PostgreSQL instance + +*Appears in:* + +- [DatabaseObjectSpec](#databaseobjectspec) +- [DatabaseRoleSpec](#databaserolespec) +- [DatabaseSpec](#databasespec) +- [ExtensionSpec](#extensionspec) +- [FDWSpec](#fdwspec) +- [OptionSpec](#optionspec) +- [RoleConfiguration](#roleconfiguration) +- [SchemaSpec](#schemaspec) +- [ServerSpec](#serverspec) + +| Field | Description | +| --------- | ----------- | +| `present` | | +| `absent` | | + +#### EphemeralVolumesSizeLimitConfiguration + +EphemeralVolumesSizeLimitConfiguration contains the configuration of the ephemeral +storage + +*Appears in:* + +- [ClusterSpec](#clusterspec) + +| Field | Description | Required | Default | Validation | +| ------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------ | -------- | ------- | ---------- | +| `shm` *[Quantity](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#quantity-resource-api)* | Shm is the size limit of the shared memory volume | | | | +| `temporaryData` *[Quantity](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#quantity-resource-api)* | TemporaryData is the size limit of the temporary data volume | | | | + +#### ExtensionConfiguration + +ExtensionConfiguration is the configuration used to add +PostgreSQL extensions to the Cluster. + +*Appears in:* + +- [CatalogImage](#catalogimage) +- [ImageInfo](#imageinfo) +- [PostgresConfiguration](#postgresconfiguration) + +| Field | Description | Required | Default | Validation | +| ----------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ----------------------------------------------------------------------------------------- | +| `name` *string* | The name of the extension, required. The limit of 59 characters
leaves room for the prefix the operator adds when deriving the
extension's Kubernetes Volume name (capped at 63 characters). | True | | MaxLength: 59
MinLength: 1
Pattern: `^[a-z0-9]([-a-z0-9_]*[a-z0-9])?$`
| +| `image` *[ImageVolumeSource](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#imagevolumesource-v1-core)* | The image containing the extension. | | | | +| `extension_control_path` *string array* | The list of directories inside the image which should be added to extension_control_path.
If not defined, defaults to "/share". | | | | +| `dynamic_library_path` *string array* | The list of directories inside the image which should be added to dynamic_library_path.
If not defined, defaults to "/lib". | | | | +| `ld_library_path` *string array* | The list of directories inside the image which should be added to ld_library_path. | | | | +| `bin_path` *string array* | A list of directories within the image to be appended to the
PostgreSQL process's `PATH` environment variable. | | | | +| `env` *[ExtensionEnvVar](#extensionenvvar) array* | Env is a list of custom environment variables to be set in the
PostgreSQL process for this extension. It is the responsibility of the
cluster administrator to ensure the variables are correct for the
specific extension. Note that changes to these variables require
a manual cluster restart to take effect. | | | | + +#### ExtensionEnvVar + +ExtensionEnvVar defines an environment variable for a specific extension +image volume. + +*Appears in:* + +- [ExtensionConfiguration](#extensionconfiguration) + +| Field | Description | Required | Default | Validation | +| ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ------------------------------------------------------------- | +| `name` *string* | Name of the environment variable to be injected into the
PostgreSQL process. | True | | MinLength: 1
Pattern: `^[a-zA-Z_][a-zA-Z0-9_]*$`
| +| `value` *string* | Value of the environment variable. {{name.ln}} performs a direct
replacement of this value, with support for placeholder expansion.
The ${`image_root`} placeholder resolves to the absolute mount path
of the extension's volume (e.g., `/extensions/my-extension`). This
is particularly useful for allowing applications or libraries to
locate specific directories within the mounted image.
Unrecognized placeholders are rejected. To include a literal ${...}
in the value, escape it as $${...}. | True | | MinLength: 1
| + +#### ExtensionSpec + +ExtensionSpec configures an extension in a database + +*Appears in:* + +- [DatabaseSpec](#databasespec) + +| Field | Description | Required | Default | Validation | +| ---------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ----------------------------- | +| `name` *string* | Name of the object (extension, schema, FDW, server) | True | | | +| `ensure` *[EnsureOption](#ensureoption)* | Specifies whether an object (e.g schema) should be present or absent
in the database. If set to `present`, the object will be created if
it does not exist. If set to `absent`, the extension/schema will be
removed if it exists. | | present | Enum: [present absent]
| +| `version` *string* | The version of the extension to install. If empty, the operator will
install the default version (whatever is specified in the
extension's control file) | True | | | +| `schema` *string* | The name of the schema in which to install the extension's objects,
in case the extension allows its contents to be relocated. If not
specified (default), and the extension's control file does not
specify a schema either, the current default object creation schema
is used. | True | | | + +#### ExternalCluster + +ExternalCluster represents the connection parameters to an +external cluster which is used in the other sections of the configuration + +*Appears in:* + +- [ClusterSpec](#clusterspec) + +| Field | Description | Required | Default | Validation | +| -------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ---------- | +| `name` *string* | The server name, required | True | | | +| `connectionParameters` *object (keys:string, values:string)* | The list of connection parameters, such as dbname, host, username, etc | | | | +| `sslCert` *[SecretKeySelector](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#secretkeyselector-v1-core)* | The reference to an SSL certificate to be used to connect to this
instance | | | | +| `sslKey` *[SecretKeySelector](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#secretkeyselector-v1-core)* | The reference to an SSL private key to be used to connect to this
instance | | | | +| `sslRootCert` *[SecretKeySelector](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#secretkeyselector-v1-core)* | The reference to an SSL CA public key to be used to connect to this
instance | | | | +| `password` *[SecretKeySelector](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#secretkeyselector-v1-core)* | The reference to the password to be used to connect to the server.
If a password is provided, {{name.ln}} creates a PostgreSQL
passfile at `/controller/external/NAME/pass` (where "NAME" is the
cluster's name). This passfile is automatically referenced in the
connection string when establishing a connection to the remote
PostgreSQL server from the current PostgreSQL `Cluster`. This ensures
secure and efficient password management for external clusters. | | | | +| `barmanObjectStore` *[BarmanObjectStoreConfiguration](https://pkg.go.dev/github.com/cloudnative-pg/barman-cloud/pkg/api#BarmanObjectStoreConfiguration)* | The configuration for the barman-cloud tool suite | | | | +| `plugin` *[PluginConfiguration](#pluginconfiguration)* | The configuration of the plugin that is taking care
of WAL archiving and backups for this external cluster | True | | | + +#### FDWSpec + +FDWSpec configures an Foreign Data Wrapper in a database + +*Appears in:* + +- [DatabaseSpec](#databasespec) + +| Field | Description | Required | Default | Validation | +| ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ----------------------------- | +| `name` *string* | Name of the object (extension, schema, FDW, server) | True | | | +| `ensure` *[EnsureOption](#ensureoption)* | Specifies whether an object (e.g schema) should be present or absent
in the database. If set to `present`, the object will be created if
it does not exist. If set to `absent`, the extension/schema will be
removed if it exists. | | present | Enum: [present absent]
| +| `handler` *string* | Name of the handler function (e.g., "postgres_fdw_handler").
This will be empty if no handler is specified. In that case,
the default handler is registered when the FDW extension is created. | | | | +| `validator` *string* | Name of the validator function (e.g., "postgres_fdw_validator").
This will be empty if no validator is specified. In that case,
the default validator is registered when the FDW extension is created. | | | | +| `owner` *string* | Owner specifies the database role that will own the Foreign Data Wrapper.
The role must have superuser privileges in the target database. | | | | +| `options` *[OptionSpec](#optionspec) array* | Options specifies the configuration options for the FDW. | | | | +| `usage` *[UsageSpec](#usagespec) array* | List of roles for which `USAGE` privileges on the FDW are granted or revoked. | | | | + +#### FailoverQuorum + +FailoverQuorum contains the information about the current failover +quorum status of a PG cluster. It is updated by the instance manager +of the primary node and reset to zero by the operator to trigger +an update. + +| Field | Description | Required | Default | Validation | +| ------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------- | -------- | ------- | ---------- | +| `apiVersion` *string* | `postgresql.k8s.enterprisedb.io/v1` | True | | | +| `kind` *string* | `FailoverQuorum` | True | | | +| `metadata` *[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#objectmeta-v1-meta)* | Refer to Kubernetes API documentation for fields of `metadata`. | True | | | +| `status` *[FailoverQuorumStatus](#failoverquorumstatus)* | Most recently observed status of the failover quorum. | | | | + +#### FailoverQuorumStatus + +FailoverQuorumStatus is the latest observed status of the failover +quorum of the PG cluster. + +*Appears in:* + +- [FailoverQuorum](#failoverquorum) + +| Field | Description | Required | Default | Validation | +| ----------------------------- | --------------------------------------------------------------------------------------------------------- | -------- | ------- | ---------- | +| `method` *string* | Contains the latest reported Method value. | | | | +| `standbyNames` *string array* | StandbyNames is the list of potentially synchronous
instance names. | | | | +| `standbyNumber` *integer* | StandbyNumber is the number of synchronous standbys that transactions
need to wait for replies from. | | | | +| `primary` *string* | Primary is the name of the primary instance that updated
this object the latest time. | | | | + +#### ImageCatalog + +ImageCatalog is the Schema for the imagecatalogs API + +| Field | Description | Required | Default | Validation | +| ------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ---------- | +| `apiVersion` *string* | `postgresql.k8s.enterprisedb.io/v1` | True | | | +| `kind` *string* | `ImageCatalog` | True | | | +| `metadata` *[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#objectmeta-v1-meta)* | Refer to Kubernetes API documentation for fields of `metadata`. | True | | | +| `spec` *[ImageCatalogSpec](#imagecatalogspec)* | Specification of the desired behavior of the ImageCatalog.
More info: | True | | | + +#### ImageCatalogComponentRef + +ImageCatalogComponentRef identifies a named image within the componentImages list of an +ImageCatalog or ClusterImageCatalog. + +*Appears in:* + +- [PgBouncerSpec](#pgbouncerspec) + +| Field | Description | Required | Default | Validation | +| ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | --------------------------------------------------------------------- | +| `apiGroup` *string* | APIGroup is the group for the resource being referenced.
If APIGroup is not specified, the specified Kind must be in the core API group.
For any other third-party types, APIGroup is required. | | | | +| `kind` *string* | Kind is the type of resource being referenced | True | | | +| `name` *string* | Name is the name of resource being referenced | True | | | +| `key` *string* | Key identifies the entry within the catalog's componentImages list. | True | | MaxLength: 63
Pattern: `^[a-z0-9]([-a-z0-9]*[a-z0-9])?$`
| + +#### ImageCatalogRef + +ImageCatalogRef defines the reference to a major version in an ImageCatalog + +*Appears in:* + +- [ClusterSpec](#clusterspec) + +| Field | Description | Required | Default | Validation | +| ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ---------- | +| `apiGroup` *string* | APIGroup is the group for the resource being referenced.
If APIGroup is not specified, the specified Kind must be in the core API group.
For any other third-party types, APIGroup is required. | | | | +| `kind` *string* | Kind is the type of resource being referenced | True | | | +| `name` *string* | Name is the name of resource being referenced | True | | | +| `major` *integer* | The major version of PostgreSQL we want to use from the ImageCatalog | True | | | + +#### ImageCatalogSpec + +ImageCatalogSpec defines the desired ImageCatalog + +*Appears in:* + +- [ClusterImageCatalog](#clusterimagecatalog) +- [ImageCatalog](#imagecatalog) + +| Field | Description | Required | Default | Validation | +| ------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ------------------------------------ | +| `images` *[CatalogImage](#catalogimage) array* | List of CatalogImages available in the catalog | True | | MaxItems: 8
MinItems: 1
| +| `componentImages` *[CatalogComponentImage](#catalogcomponentimage) array* | ComponentImages is a list of named images for components other than PostgreSQL
(e.g. pgbouncer). Keys must be unique within a catalog. | | | MaxItems: 32
| + +#### ImageInfo + +ImageInfo contains the information about a PostgreSQL image + +*Appears in:* + +- [ClusterStatus](#clusterstatus) + +| Field | Description | Required | Default | Validation | +| ---------------------------------------------------------------------- | ---------------------------------------------------------------------------------- | -------- | ------- | ---------- | +| `image` *string* | Image is the image name | True | | | +| `majorVersion` *integer* | MajorVersion is the major version of the image | True | | | +| `extensions` *[ExtensionConfiguration](#extensionconfiguration) array* | Extensions contains the container image extensions available for the current Image | | | | + +#### Import + +Import contains the configuration to init a database from a logic snapshot of an externalCluster + +*Appears in:* + +- [BootstrapInitDB](#bootstrapinitdb) + +| Field | Description | Required | Default | Validation | +| ----------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ------------------------------------ | +| `source` *[ImportSource](#importsource)* | The source of the import | True | | | +| `type` *[SnapshotType](#snapshottype)* | The import type. Can be `microservice` or `monolith`. | True | | Enum: [microservice monolith]
| +| `databases` *string array* | The databases to import | True | | | +| `roles` *string array* | The roles to import | | | | +| `postImportApplicationSQL` *string array* | List of SQL queries to be executed as a superuser in the application
database right after is imported - to be used with extreme care
(by default empty). Only available in microservice type. | | | | +| `schemaOnly` *boolean* | When set to true, only the `pre-data` and `post-data` sections of
`pg_restore` are invoked, avoiding data import. Default: `false`. | | | | +| `pgDumpExtraOptions` *string array* | List of custom options to pass to the `pg_dump` command.
IMPORTANT: Use with caution. The operator does not validate these options,
and certain flags may interfere with its intended functionality or design.
You are responsible for ensuring that the provided options are compatible
with your environment and desired behavior. | | | | +| `pgRestoreExtraOptions` *string array* | List of custom options to pass to the `pg_restore` command.
IMPORTANT: Use with caution. The operator does not validate these options,
and certain flags may interfere with its intended functionality or design.
You are responsible for ensuring that the provided options are compatible
with your environment and desired behavior. | | | | +| `pgRestorePredataOptions` *string array* | Custom options to pass to the `pg_restore` command during the `pre-data`
section. This setting overrides the generic `pgRestoreExtraOptions` value.
IMPORTANT: Use with caution. The operator does not validate these options,
and certain flags may interfere with its intended functionality or design.
You are responsible for ensuring that the provided options are compatible
with your environment and desired behavior. | | | | +| `pgRestoreDataOptions` *string array* | Custom options to pass to the `pg_restore` command during the `data`
section. This setting overrides the generic `pgRestoreExtraOptions` value.
IMPORTANT: Use with caution. The operator does not validate these options,
and certain flags may interfere with its intended functionality or design.
You are responsible for ensuring that the provided options are compatible
with your environment and desired behavior. | | | | +| `pgRestorePostdataOptions` *string array* | Custom options to pass to the `pg_restore` command during the `post-data`
section. This setting overrides the generic `pgRestoreExtraOptions` value.
IMPORTANT: Use with caution. The operator does not validate these options,
and certain flags may interfere with its intended functionality or design.
You are responsible for ensuring that the provided options are compatible
with your environment and desired behavior. | | | | + +#### ImportSource + +ImportSource describes the source for the logical snapshot + +*Appears in:* + +- [Import](#import) + +| Field | Description | Required | Default | Validation | +| -------------------------- | ----------------------------------------------- | -------- | ------- | ---------- | +| `externalCluster` *string* | The name of the externalCluster used for import | True | | | + +#### InstanceID + +InstanceID contains the information to identify an instance + +*Appears in:* + +- [BackupStatus](#backupstatus) + +| Field | Description | Required | Default | Validation | +| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ---------- | +| `podName` *string* | The pod name | | | | +| `ContainerID` *string* | The container ID | | | | +| `sessionID` *string* | The instance manager session ID. This is a unique identifier generated at instance manager
startup and changes on every restart (including container reboots). Used to detect if
the instance manager was restarted during long-running operations like backups, which
would terminate any running backup process. | | | | + +#### InstanceReportedState + +InstanceReportedState describes the last reported state of an instance during a reconciliation loop + +*Appears in:* + +- [ClusterStatus](#clusterstatus) + +| Field | Description | Required | Default | Validation | +| ---------------------- | --------------------------------------------- | -------- | ------- | ---------- | +| `isPrimary` *boolean* | indicates if an instance is the primary one | True | | | +| `timeLineID` *integer* | indicates on which TimelineId the instance is | | | | +| `ip` *string* | IP address of the instance | True | | | + +#### IsolationCheckConfiguration + +IsolationCheckConfiguration contains the configuration for the isolation check +functionality in the liveness probe + +*Appears in:* + +- [LivenessProbe](#livenessprobe) + +| Field | Description | Required | Default | Validation | +| ----------------------------- | -------------------------------------------------------------------------- | -------- | ------- | ---------- | +| `enabled` *boolean* | Whether primary isolation checking is enabled for the liveness probe | | true | | +| `requestTimeout` *integer* | Timeout in milliseconds for requests during the primary isolation check | | 1000 | | +| `connectionTimeout` *integer* | Timeout in milliseconds for connections during the primary isolation check | | 1000 | | + +#### LDAPBindAsAuth + +LDAPBindAsAuth provides the required fields to use the +bind authentication for LDAP + +*Appears in:* + +- [LDAPConfig](#ldapconfig) + +| Field | Description | Required | Default | Validation | +| ----------------- | ----------------------------------------- | -------- | ------- | ---------- | +| `prefix` *string* | Prefix for the bind authentication option | | | | +| `suffix` *string* | Suffix for the bind authentication option | | | | + +#### LDAPBindSearchAuth + +LDAPBindSearchAuth provides the required fields to use +the bind+search LDAP authentication process + +*Appears in:* + +- [LDAPConfig](#ldapconfig) + +| Field | Description | Required | Default | Validation | +| ------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------- | -------- | ------- | ---------- | +| `baseDN` *string* | Root DN to begin the user search | | | | +| `bindDN` *string* | DN of the user to bind to the directory | | | | +| `bindPassword` *[SecretKeySelector](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#secretkeyselector-v1-core)* | Secret with the password for the user to bind to the directory | | | | +| `searchAttribute` *string* | Attribute to match against the username | | | | +| `searchFilter` *string* | Search filter to use when doing the search+bind authentication | | | | + +#### LDAPConfig + +LDAPConfig contains the parameters needed for LDAP authentication + +*Appears in:* + +- [PostgresConfiguration](#postgresconfiguration) + +| Field | Description | Required | Default | Validation | +| ------------------------------------------------------------ | --------------------------------------------------------------- | -------- | ------- | ------------------------- | +| `server` *string* | LDAP hostname or IP address | | | | +| `port` *integer* | LDAP server port | | | | +| `scheme` *[LDAPScheme](#ldapscheme)* | LDAP schema to be used, possible options are `ldap` and `ldaps` | | | Enum: [ldap ldaps]
| +| `bindAsAuth` *[LDAPBindAsAuth](#ldapbindasauth)* | Bind as authentication configuration | | | | +| `bindSearchAuth` *[LDAPBindSearchAuth](#ldapbindsearchauth)* | Bind+Search authentication configuration | | | | +| `tls` *boolean* | Set to 'true' to enable LDAP over TLS. 'false' is default | | | | + +#### LDAPScheme + +*Underlying type:* *string* + +LDAPScheme defines the possible schemes for LDAP + +*Appears in:* + +- [LDAPConfig](#ldapconfig) + +| Field | Description | +| ------- | ----------- | +| `ldap` | | +| `ldaps` | | + +#### LivenessProbe + +LivenessProbe is the configuration of the liveness probe + +*Appears in:* + +- [ProbesConfiguration](#probesconfiguration) + +| Field | Description | Required | Default | Validation | +| ------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ---------- | +| `initialDelaySeconds` *integer* | Number of seconds after the container has started before liveness probes are initiated.
More info: | | | | +| `timeoutSeconds` *integer* | Number of seconds after which the probe times out.
Defaults to 1 second. Minimum value is 1.
More info: | | | | +| `periodSeconds` *integer* | How often (in seconds) to perform the probe.
Default to 10 seconds. Minimum value is 1. | | | | +| `successThreshold` *integer* | Minimum consecutive successes for the probe to be considered successful after having failed.
Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. | | | | +| `failureThreshold` *integer* | Minimum consecutive failures for the probe to be considered failed after having succeeded.
Defaults to 3. Minimum value is 1. | | | | +| `terminationGracePeriodSeconds` *integer* | Optional duration in seconds the pod needs to terminate gracefully upon probe failure.
The grace period is the duration in seconds after the processes running in the pod are sent
a termination signal and the time when the processes are forcibly halted with a kill signal.
Set this value longer than the expected cleanup time for your process.
If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this
value overrides the value provided by the pod spec.
Value must be non-negative integer. The value zero indicates stop immediately via
the kill signal (no opportunity to shut down).
This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate.
Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. | | | | +| `isolationCheck` *[IsolationCheckConfiguration](#isolationcheckconfiguration)* | Configure the feature that extends the liveness probe for a primary
instance. In addition to the basic checks, this verifies whether the
primary is isolated from the Kubernetes API server and from its
replicas, ensuring that it can be safely shut down if network
partition or API unavailability is detected. Enabled by default. | | | | + +#### ManagedConfiguration + +ManagedConfiguration represents the portions of PostgreSQL that are managed +by the instance manager + +*Appears in:* + +- [ClusterSpec](#clusterspec) + +| Field | Description | Required | Default | Validation | +| ------------------------------------------------------- | --------------------------------------- | -------- | ------- | ---------- | +| `roles` *[RoleConfiguration](#roleconfiguration) array* | Database roles managed by the `Cluster` | | | | +| `services` *[ManagedServices](#managedservices)* | Services roles managed by the `Cluster` | | | | + +#### ManagedRoles + +ManagedRoles tracks the status of a cluster's managed roles + +*Appears in:* + +- [ClusterStatus](#clusterstatus) + +| Field | Description | Required | Default | Validation | +| ------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ---------- | +| `byStatus` *object (keys:[RoleStatus](#rolestatus), values:string array)* | ByStatus gives the list of roles in each state | | | | +| `cannotReconcile` *object (keys:string, values:string array)* | CannotReconcile lists roles that cannot be reconciled, with an
explanation of the cause. Failures may originate in PostgreSQL
(e.g. dropping a role that owns objects) or in Kubernetes (e.g.
the referenced password Secret cannot be fetched). | | | | +| `passwordStatus` *object (keys:string, values:[PasswordState](#passwordstate))* | PasswordStatus gives the last transaction id and password secret version for each managed role | | | | + +#### ManagedService + +ManagedService represents a specific service managed by the cluster. +It includes the type of service and its associated template specification. + +*Appears in:* + +- [ManagedServices](#managedservices) + +| Field | Description | Required | Default | Validation | +| ------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ---------------------------- | +| `selectorType` *[ServiceSelectorType](#serviceselectortype)* | SelectorType specifies the type of selectors that the service will have.
Valid values are "rw", "r", and "ro", representing read-write, read, and read-only services. | True | | Enum: [rw r ro]
| +| `updateStrategy` *[ServiceUpdateStrategy](#serviceupdatestrategy)* | UpdateStrategy describes how the service differences should be reconciled | | patch | Enum: [patch replace]
| +| `serviceTemplate` *[ServiceTemplateSpec](#servicetemplatespec)* | ServiceTemplate is the template specification for the service. | True | | | + +#### ManagedServices + +ManagedServices represents the services managed by the cluster. + +*Appears in:* + +- [ManagedConfiguration](#managedconfiguration) + +| Field | Description | Required | Default | Validation | +| ----------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ---------------------- | +| `disabledDefaultServices` *[ServiceSelectorType](#serviceselectortype) array* | DisabledDefaultServices is a list of service types that are disabled by default.
Valid values are "r", and "ro", representing read, and read-only services. | | | Enum: [rw r ro]
| +| `additional` *[ManagedService](#managedservice) array* | Additional is a list of additional managed services specified by the user. | | | | + +#### Metadata + +Metadata is a structure similar to the metav1.ObjectMeta, but still +parseable by controller-gen to create a suitable CRD for the user. +The comment of PodTemplateSpec has an explanation of why we are +not using the core data types. + +*Appears in:* + +- [PodTemplateSpec](#podtemplatespec) +- [ServiceAccountTemplate](#serviceaccounttemplate) +- [ServiceTemplateSpec](#servicetemplatespec) + +| Field | Description | Required | Default | Validation | +| --------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ---------- | +| `name` *string* | The name of the resource. Only supported for certain types | | | | +| `labels` *object (keys:string, values:string)* | Map of string keys and values that can be used to organize and categorize
(scope and select) objects. May match selectors of replication controllers
and services.
More info: | | | | +| `annotations` *object (keys:string, values:string)* | Annotations is an unstructured key value map stored with a resource that may be
set by external tools to store and retrieve arbitrary metadata. They are not
queryable and should be preserved when modifying objects.
More info: | | | | + +#### MonitoringConfiguration + +MonitoringConfiguration is the type containing all the monitoring +configuration for a certain cluster + +*Appears in:* + +- [ClusterSpec](#clusterspec) + +| Field | Description | Required | Default | Validation | +| ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ---------- | +| `disableDefaultQueries` *boolean* | Whether the default queries should be injected.
Set it to `true` if you don't want to inject default queries into the cluster.
Default: false. | | false | | +| `customQueriesConfigMap` *[ConfigMapKeySelector](https://pkg.go.dev/github.com/cloudnative-pg/machinery/pkg/api#ConfigMapKeySelector) array* | The list of config maps containing the custom queries | | | | +| `customQueriesSecret` *[SecretKeySelector](https://pkg.go.dev/github.com/cloudnative-pg/machinery/pkg/api#SecretKeySelector) array* | The list of secrets containing the custom queries | | | | +| `enablePodMonitor` *boolean* | Enable or disable the `PodMonitor`
Deprecated: This feature will be removed in an upcoming release. If
you need this functionality, you can create a PodMonitor manually. | | false | | +| `tls` *[ClusterMonitoringTLSConfiguration](#clustermonitoringtlsconfiguration)* | Configure TLS communication for the metrics endpoint.
Changing tls.enabled option will force a rollout of all instances. | | | | +| `podMonitorMetricRelabelings` *[RelabelConfig](https://pkg.go.dev/github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1#RelabelConfig) array* | The list of metric relabelings for the `PodMonitor`. Applied to samples before ingestion.
Deprecated: This feature will be removed in an upcoming release. If
you need this functionality, you can create a PodMonitor manually. | | | | +| `podMonitorRelabelings` *[RelabelConfig](https://pkg.go.dev/github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1#RelabelConfig) array* | The list of relabelings for the `PodMonitor`. Applied to samples before scraping.
Deprecated: This feature will be removed in an upcoming release. If
you need this functionality, you can create a PodMonitor manually. | | | | +| `metricsQueriesTTL` *[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#duration-v1-meta)* | The interval during which metrics computed from queries are considered current.
Once it is exceeded, a new scrape will trigger a rerun
of the queries.
If not set, defaults to 30 seconds, in line with Prometheus scraping defaults.
Setting this to zero disables the caching mechanism and can cause heavy load on the PostgreSQL server. | | | | + +#### NodeMaintenanceWindow + +NodeMaintenanceWindow contains information that the operator +will use while upgrading the underlying node. + +This option is only useful when the chosen storage prevents the Pods +from being freely moved across nodes. + +*Appears in:* + +- [ClusterSpec](#clusterspec) + +| Field | Description | Required | Default | Validation | +| ---------------------- | --------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ---------- | +| `reusePVC` *boolean* | Reuse the existing PVC (wait for the node to come
up again) or not (recreate it elsewhere - when `instances` >1) | | true | | +| `inProgress` *boolean* | Is there a node maintenance activity in progress? | | false | | + +#### OnlineConfiguration + +OnlineConfiguration contains the configuration parameters for the online volume snapshot + +*Appears in:* + +- [BackupSpec](#backupspec) +- [ScheduledBackupSpec](#scheduledbackupspec) +- [VolumeSnapshotConfiguration](#volumesnapshotconfiguration) + +| Field | Description | Required | Default | Validation | +| ------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ---------- | +| `waitForArchive` *boolean* | If false, the function will return immediately after the backup is completed,
without waiting for WAL to be archived.
This behavior is only useful with backup software that independently monitors WAL archiving.
Otherwise, WAL required to make the backup consistent might be missing and make the backup useless.
By default, or when this parameter is true, pg_backup_stop will wait for WAL to be archived when archiving is
enabled.
On a standby, this means that it will wait only when archive_mode = always.
If write activity on the primary is low, it may be useful to run pg_switch_wal on the primary in order to trigger
an immediate segment switch. | | true | | +| `immediateCheckpoint` *boolean* | Control whether the I/O workload for the backup initial checkpoint will
be limited, according to the `checkpoint_completion_target` setting on
the PostgreSQL server. If set to true, an immediate checkpoint will be
used, meaning PostgreSQL will complete the checkpoint as soon as
possible. `false` by default. | | | | + +#### OptionSpec + +OptionSpec holds the name, value and the ensure field for an option + +*Appears in:* + +- [FDWSpec](#fdwspec) +- [ServerSpec](#serverspec) + +| Field | Description | Required | Default | Validation | +| ---------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ----------------------------- | +| `name` *string* | Name of the option | True | | | +| `value` *string* | Value of the option | True | | | +| `ensure` *[EnsureOption](#ensureoption)* | Specifies whether an option should be present or absent in
the database. If set to `present`, the option will be
created if it does not exist. If set to `absent`, the
option will be removed if it exists. | | present | Enum: [present absent]
| + +#### PasswordState + +PasswordState represents the state of the password of a managed RoleConfiguration + +*Appears in:* + +- [ManagedRoles](#managedroles) + +| Field | Description | Required | Default | Validation | +| -------------------------- | ------------------------------------------------------------------- | -------- | ------- | ---------- | +| `transactionID` *integer* | the last transaction ID to affect the role definition in PostgreSQL | | | | +| `resourceVersion` *string* | the resource version of the password secret | | | | + +#### PgBouncerIntegrationStatus + +PgBouncerIntegrationStatus encapsulates the needed integration for the pgbouncer poolers referencing the cluster + +*Appears in:* + +- [PoolerIntegrations](#poolerintegrations) + +| Field | Description | Required | Default | Validation | +| ------------------------ | ----------- | -------- | ------- | ---------- | +| `secrets` *string array* | | | | | + +#### PgBouncerPoolMode + +*Underlying type:* *string* + +PgBouncerPoolMode is the mode of PgBouncer + +*Validation:* + +- Enum: [session transaction] + +*Appears in:* + +- [PgBouncerSpec](#pgbouncerspec) + +#### PgBouncerSecrets + +PgBouncerSecrets contains the versions of the secrets used +by pgbouncer + +*Appears in:* + +- [PoolerSecrets](#poolersecrets) + +| Field | Description | Required | Default | Validation | +| --------------------------------------------- | ----------------------------- | -------- | ------- | ---------- | +| `authQuery` *[SecretVersion](#secretversion)* | The auth query secret version | | | | + +#### PgBouncerSpec + +PgBouncerSpec defines how to configure PgBouncer + +*Appears in:* + +- [PoolerSpec](#poolerspec) + +| Field | Description | Required | Default | Validation | +| ------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ---------------------------------- | +| `poolMode` *[PgBouncerPoolMode](#pgbouncerpoolmode)* | The pool mode. Default: `session`. | | session | Enum: [session transaction]
| +| `serverTLSSecret` *[LocalObjectReference](https://pkg.go.dev/github.com/cloudnative-pg/machinery/pkg/api#LocalObjectReference)* | ServerTLSSecret, when pointing to a TLS secret, provides pgbouncer's
`server_tls_key_file` and `server_tls_cert_file`, used when
authenticating against PostgreSQL. | | | | +| `serverCASecret` *[LocalObjectReference](https://pkg.go.dev/github.com/cloudnative-pg/machinery/pkg/api#LocalObjectReference)* | ServerCASecret provides PgBouncer’s server_tls_ca_file, the root
CA for validating PostgreSQL certificates | | | | +| `clientCASecret` *[LocalObjectReference](https://pkg.go.dev/github.com/cloudnative-pg/machinery/pkg/api#LocalObjectReference)* | ClientCASecret provides PgBouncer’s client_tls_ca_file, the root
CA for validating client certificates | | | | +| `clientTLSSecret` *[LocalObjectReference](https://pkg.go.dev/github.com/cloudnative-pg/machinery/pkg/api#LocalObjectReference)* | ClientTLSSecret provides PgBouncer’s client_tls_key_file (private key)
and client_tls_cert_file (certificate) used to accept client connections | | | | +| `authQuerySecret` *[LocalObjectReference](https://pkg.go.dev/github.com/cloudnative-pg/machinery/pkg/api#LocalObjectReference)* | The credentials of the user that need to be used for the authentication
query. In case it is specified, also an AuthQuery
(e.g. "SELECT usename, passwd FROM pg_catalog.pg_shadow WHERE usename=$1")
has to be specified and no automatic CNP Cluster integration will be triggered.
Deprecated. | | | | +| `authQuery` *string* | The query that will be used to download the hash of the password
of a certain user. Default: "SELECT usename, passwd FROM public.user_search($1)".
In case it is specified, also an AuthQuerySecret has to be specified and
no automatic CNP Cluster integration will be triggered. | | | | +| `parameters` *object (keys:string, values:string)* | Additional parameters to be passed to PgBouncer - please check
the CNP documentation for a list of options you can configure | | | | +| `pg_hba` *string array* | PostgreSQL Host Based Authentication rules (lines to be appended
to the pg_hba.conf file) | | | | +| `paused` *boolean* | When set to `true`, PgBouncer will disconnect from the PostgreSQL
server, first waiting for all queries to complete, and pause all new
client connections until this value is set to `false` (default). Internally,
the operator calls PgBouncer's `PAUSE` and `RESUME` commands. | | false | | +| `image` *string* | Image is the pgbouncer container image to use. When set, it takes
precedence over ImageCatalogRef and the operator default, but is
overridden by an explicit image set in the pod template. | | | | +| `imageCatalogRef` *[ImageCatalogComponentRef](#imagecatalogcomponentref)* | ImageCatalogRef points to an entry in an ImageCatalog or ClusterImageCatalog.
Mutually exclusive with Image. | | | | + +#### PluginConfiguration + +PluginConfiguration specifies a plugin that need to be loaded for this +cluster to be reconciled + +*Appears in:* + +- [ClusterSpec](#clusterspec) +- [ExternalCluster](#externalcluster) + +| Field | Description | Required | Default | Validation | +| -------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------- | ------- | ---------- | +| `name` *string* | Name is the plugin name | True | | | +| `enabled` *boolean* | Enabled is true if this plugin will be used | | true | | +| `isWALArchiver` *boolean* | Marks the plugin as the WAL archiver. At most one plugin can be
designated as a WAL archiver. This cannot be enabled if the
`.spec.backup.barmanObjectStore` configuration is present. | | false | | +| `parameters` *object (keys:string, values:string)* | Parameters is the configuration of the plugin | | | | + +#### PluginStatus + +PluginStatus is the status of a loaded plugin + +*Appears in:* + +- [ClusterStatus](#clusterstatus) + +| Field | Description | Required | Default | Validation | +| ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ | -------- | ------- | ---------- | +| `name` *string* | Name is the name of the plugin | True | | | +| `version` *string* | Version is the version of the plugin loaded by the
latest reconciliation loop | True | | | +| `capabilities` *string array* | Capabilities are the list of capabilities of the
plugin | | | | +| `operatorCapabilities` *string array* | OperatorCapabilities are the list of capabilities of the
plugin regarding the reconciler | | | | +| `walCapabilities` *string array* | WALCapabilities are the list of capabilities of the
plugin regarding the WAL management | | | | +| `backupCapabilities` *string array* | BackupCapabilities are the list of capabilities of the
plugin regarding the Backup management | | | | +| `restoreJobHookCapabilities` *string array* | RestoreJobHookCapabilities are the list of capabilities of the
plugin regarding the RestoreJobHook management | | | | +| `status` *string* | Status contain the status reported by the plugin through the SetStatusInCluster interface | | | | + +#### PodName + +*Underlying type:* *string* + +PodName is the name of a Pod + +*Appears in:* + +- [ClusterStatus](#clusterstatus) +- [Topology](#topology) + +#### PodSelectorRef + +PodSelectorRef defines a named pod label selector for use in pg_hba rules. +Pods matching the selector in the Cluster's namespace will have their IPs +resolved and made available for pg_hba address expansion via the +`${podselector:NAME}` syntax. + +*Appears in:* + +- [ClusterSpec](#clusterspec) + +| Field | Description | Required | Default | Validation | +| ------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ------------------------------------------------------------------ | +| `name` *string* | Name is the identifier used to reference this selector in pg_hba rules
via the ${podselector:NAME} syntax in the address field. | True | | MinLength: 1
Pattern: `^[a-z]([a-z0-9_-]*[a-z0-9])?$`
| +| `selector` *[LabelSelector](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#labelselector-v1-meta)* | Selector is a label selector that identifies the pods whose IPs
should be resolved. Only pods in the Cluster's namespace are considered. | True | | | + +#### PodSelectorRefStatus + +PodSelectorRefStatus contains the resolved pod IPs for a named selector. + +*Appears in:* + +- [ClusterStatus](#clusterstatus) + +| Field | Description | Required | Default | Validation | +| -------------------- | ------------------------------------------------------------------------------------------------------ | -------- | ------- | ---------- | +| `name` *string* | Name corresponds to the name in the spec's PodSelectorRef. | True | | | +| `ips` *string array* | IPs is the list of pod IPs matching the selector.
Each IP is a single address (no CIDR notation). | | | | + +#### PodStatus + +*Underlying type:* *string* + +PodStatus represent the possible status of pods + +*Appears in:* + +- [ClusterStatus](#clusterstatus) + +#### PodTemplateSpec + +PodTemplateSpec is a structure allowing the user to set +a template for Pod generation. + +Unfortunately we can't use the corev1.PodTemplateSpec +type because the generated CRD won't have the field for the +metadata section. + +References: + + + + +*Appears in:* + +- [PoolerSpec](#poolerspec) + +| Field | Description | Required | Default | Validation | +| -------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ---------- | +| `metadata` *[Metadata](#metadata)* | Refer to Kubernetes API documentation for fields of `metadata`. | | | | +| `spec` *[PodSpec](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#podspec-v1-core)* | Specification of the desired behavior of the pod.
More info: | | | | + +#### PodTopologyLabels + +*Underlying type:* *object* + +PodTopologyLabels represent the topology of a Pod. map[labelName]labelValue + +*Appears in:* + +- [Topology](#topology) + +#### Pooler + +Pooler is the Schema for the poolers API + +| Field | Description | Required | Default | Validation | +| ------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ---------- | +| `apiVersion` *string* | `postgresql.k8s.enterprisedb.io/v1` | True | | | +| `kind` *string* | `Pooler` | True | | | +| `metadata` *[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#objectmeta-v1-meta)* | Refer to Kubernetes API documentation for fields of `metadata`. | True | | | +| `spec` *[PoolerSpec](#poolerspec)* | Specification of the desired behavior of the Pooler.
More info: | True | | | +| `status` *[PoolerStatus](#poolerstatus)* | Most recently observed status of the Pooler. This data may not be up to
date. Populated by the system. Read-only.
More info: | | | | + +#### PoolerIntegrations + +PoolerIntegrations encapsulates the needed integration for the poolers referencing the cluster + +*Appears in:* + +- [ClusterStatus](#clusterstatus) + +| Field | Description | Required | Default | Validation | +| ---------------------------------------------------------------------------------- | ----------- | -------- | ------- | ---------- | +| `pgBouncerIntegration` *[PgBouncerIntegrationStatus](#pgbouncerintegrationstatus)* | | | | | + +#### PoolerMonitoringConfiguration + +PoolerMonitoringConfiguration is the type containing all the monitoring +configuration for a certain Pooler. + +Mirrors the Cluster's MonitoringConfiguration but without the custom queries +part for now. + +*Appears in:* + +- [PoolerSpec](#poolerspec) + +| Field | Description | Required | Default | Validation | +| ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------- | ------- | ---------- | +| `enablePodMonitor` *boolean* | Enable or disable the `PodMonitor`
Deprecated: This feature will be removed in an upcoming release. If
you need this functionality, you can create a PodMonitor manually. | | false | | +| `podMonitorMetricRelabelings` *[RelabelConfig](https://pkg.go.dev/github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1#RelabelConfig) array* | The list of metric relabelings for the `PodMonitor`. Applied to samples before ingestion.
Deprecated: This feature will be removed in an upcoming release. If
you need this functionality, you can create a PodMonitor manually. | | | | +| `podMonitorRelabelings` *[RelabelConfig](https://pkg.go.dev/github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1#RelabelConfig) array* | The list of relabelings for the `PodMonitor`. Applied to samples before scraping.
Deprecated: This feature will be removed in an upcoming release. If
you need this functionality, you can create a PodMonitor manually. | | | | +| `tls` *[PoolerMonitoringTLSConfiguration](#poolermonitoringtlsconfiguration)* | Configure TLS communication for the metrics endpoint.
Changing tls.enabled option will force a rollout of all instances. | | | | + +#### PoolerMonitoringTLSConfiguration + +PoolerMonitoringTLSConfiguration is the type containing the TLS configuration +for the pooler monitoring + +*Appears in:* + +- [PoolerMonitoringConfiguration](#poolermonitoringconfiguration) + +| Field | Description | Required | Default | Validation | +| ------------------- | -------------------------------------------------------------------------------------------------------- | -------- | ------- | ---------- | +| `enabled` *boolean* | Enable TLS for the monitoring endpoint.
Changing this option will force a rollout of all instances. | | false | | + +#### PoolerPhase + +*Underlying type:* *string* + +PoolerPhase represents the lifecycle phase of a Pooler. + +*Validation:* + +- Enum: [active paused inactive failed] + +*Appears in:* + +- [PoolerStatus](#poolerstatus) + +| Field | Description | +| ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `active` | PoolerPhaseActive means the pooler is running normally and serving traffic.
| +| `paused` | PoolerPhasePaused means PgBouncer is up and running but holding new client
connections in the queue because spec.pgbouncer.paused is true. The Deployment
keeps reconciling; lifting the pause transitions back to Active.
| +| `inactive` | PoolerPhaseInactive means the pooler cannot make progress because a
prerequisite resource is missing (cluster, secret, certificate). The
controller retries periodically until the prerequisite shows up. Check
status.phaseReason for the specific cause.
| +| `failed` | PoolerPhaseFailed means the pooler cannot be reconciled due to a
configuration error. Check status.phaseReason for details.
| + +#### PoolerSecrets + +PoolerSecrets contains the versions of all the secrets used + +*Appears in:* + +- [PoolerStatus](#poolerstatus) + +| Field | Description | Required | Default | Validation | +| ---------------------------------------------------------- | -------------------------------------------- | -------- | ------- | ---------- | +| `clientTLS` *[SecretVersion](#secretversion)* | The client TLS secret version | | | | +| `serverTLS` *[SecretVersion](#secretversion)* | The server TLS secret version | | | | +| `serverCA` *[SecretVersion](#secretversion)* | The server CA secret version | | | | +| `clientCA` *[SecretVersion](#secretversion)* | The client CA secret version | | | | +| `pgBouncerSecrets` *[PgBouncerSecrets](#pgbouncersecrets)* | The version of the secrets used by PgBouncer | | | | + +#### PoolerSpec + +PoolerSpec defines the desired state of Pooler + +*Appears in:* + +- [Pooler](#pooler) + +| Field | Description | Required | Default | Validation | +| -------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ---------------------------------------------------------------------- | +| `cluster` *[LocalObjectReference](https://pkg.go.dev/github.com/cloudnative-pg/machinery/pkg/api#LocalObjectReference)* | This is the cluster reference on which the Pooler will work.
Pooler name should never match with any cluster name within the same namespace. | True | | | +| `type` *[PoolerType](#poolertype)* | Type of service to forward traffic to. Default: `rw`. | | rw | Enum: [rw ro r]
| +| `instances` *integer* | The number of replicas we want. Default: 1. | | 1 | | +| `template` *[PodTemplateSpec](#podtemplatespec)* | The template of the Pod to be created | | | | +| `pgbouncer` *[PgBouncerSpec](#pgbouncerspec)* | The PgBouncer configuration | True | | | +| `deploymentStrategy` *[DeploymentStrategy](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#deploymentstrategy-v1-apps)* | The deployment strategy to use for pgbouncer to replace existing pods with new ones | | | | +| `monitoring` *[PoolerMonitoringConfiguration](#poolermonitoringconfiguration)* | The configuration of the monitoring infrastructure of this pooler. | | | | +| `serviceTemplate` *[ServiceTemplateSpec](#servicetemplatespec)* | Template for the Service to be created | | | | +| `serviceAccountName` *string* | Name of an existing ServiceAccount in the same namespace to use for the pooler.
When specified, the operator will not create a new ServiceAccount
but will use the provided one. This is useful for sharing a single
ServiceAccount across multiple poolers (e.g., for cloud IAM configurations).
If not specified, a ServiceAccount will be created with the pooler name. | | | MaxLength: 253
Pattern: `^[a-z0-9]([-a-z0-9]*[a-z0-9])?$`
| + +#### PoolerStatus + +PoolerStatus defines the observed state of Pooler + +*Appears in:* + +- [Pooler](#pooler) + +| Field | Description | Required | Default | Validation | +| ------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | -------------------------------------------- | +| `secrets` *[PoolerSecrets](#poolersecrets)* | The resource version of the config object | | | | +| `instances` *integer* | The number of pods trying to be scheduled | | | | +| `phase` *[PoolerPhase](#poolerphase)* | Phase summarizes the overall lifecycle state of the Pooler. | | | Enum: [active paused inactive failed]
| +| `phaseReason` *string* | PhaseReason is a human-readable explanation of the current Phase. | | | | +| `image` *string* | Image is the resolved pgbouncer container image that the operator is
using for this Pooler, including any override coming from spec.template.
While Phase is Active or Paused this field reflects what the Deployment
actually runs; while Phase is Inactive or Failed it may carry the last
successfully resolved value (or be empty if the Pooler has never reconciled
successfully). | | | | +| `error` *string* | Error is the latest admission validation error | | | | + +#### PoolerType + +*Underlying type:* *string* + +PoolerType is the type of the connection pool, meaning the service +we are targeting. Allowed values are `rw` and `ro`. + +*Validation:* + +- Enum: [rw ro r] + +*Appears in:* + +- [PoolerSpec](#poolerspec) + +#### PostgresConfiguration + +PostgresConfiguration defines the PostgreSQL configuration + +*Appears in:* + +- [ClusterSpec](#clusterspec) + +| Field | Description | Required | Default | Validation | +| --------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ---------- | +| `parameters` *object (keys:string, values:string)* | PostgreSQL configuration options (postgresql.conf) | | | | +| `synchronous` *[SynchronousReplicaConfiguration](#synchronousreplicaconfiguration)* | Configuration of the PostgreSQL synchronous replication feature | | | | +| `pg_hba` *string array* | PostgreSQL Host Based Authentication rules (lines to be appended
to the pg_hba.conf file).
Use the ${podselector:NAME} syntax to reference a pod selector;
the rule will be expanded for each Pod IP matching that selector. | | | | +| `pg_ident` *string array* | PostgreSQL User Name Maps rules (lines to be appended
to the pg_ident.conf file) | | | | +| `epas` *[EPASConfiguration](#epasconfiguration)* | EDB Postgres Advanced Server specific configurations | | | | +| `syncReplicaElectionConstraint` *[SyncReplicaElectionConstraints](#syncreplicaelectionconstraints)* | Requirements to be met by sync replicas. This will affect how the "synchronous_standby_names" parameter will be
set up. | | | | +| `shared_preload_libraries` *string array* | Lists of shared preload libraries to add to the default ones | | | | +| `ldap` *[LDAPConfig](#ldapconfig)* | Options to specify LDAP configuration | | | | +| `promotionTimeout` *integer* | Specifies the maximum number of seconds to wait when promoting an instance to primary.
Default value is 40000000, greater than one year in seconds,
big enough to simulate an infinite timeout | | | | +| `enableAlterSystem` *boolean* | If this parameter is true, the user will be able to invoke `ALTER SYSTEM`
on this {{name.ln}} Cluster.
This should only be used for debugging and troubleshooting.
Defaults to false. | | | | +| `extensions` *[ExtensionConfiguration](#extensionconfiguration) array* | The configuration of the extensions to be added | | | | + +#### PrimaryLeaseConfiguration + +PrimaryLeaseConfiguration configures the timings of the Kubernetes `Lease` +that the primary instance holds and renews to coordinate a safe primary +election. These values map directly onto the underlying Kubernetes +leader-election parameters. + +*Appears in:* + +- [ClusterSpec](#clusterspec) + +| Field | Description | Required | Default | Validation | +| ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ----------------- | +| `leaseDurationSeconds` *integer* | How long, in seconds, the primary lease is considered valid before it
expires and another instance may acquire it. It must be greater than
`renewDeadlineSeconds`.
Defaults to 15. | | 15 | Minimum: 1
| +| `renewDeadlineSeconds` *integer* | How long, in seconds, the current primary keeps retrying to renew the
lease before giving up and stopping. It must be smaller than
`leaseDurationSeconds`.
Defaults to 10. | | 10 | Minimum: 1
| +| `retryPeriodSeconds` *integer* | How frequently, in seconds, a non-holder instance retries acquiring or
renewing the lease.
Defaults to 2. | | 2 | Minimum: 1
| +| `releasedLeaseDurationSeconds` *integer* | The TTL, in seconds, written when the primary explicitly releases the
lease on a clean shutdown, allowing a replica to promote without waiting
for the full lease duration to expire.
Defaults to 1. | | 1 | Minimum: 1
| + +#### PrimaryUpdateMethod + +*Underlying type:* *string* + +PrimaryUpdateMethod defines the method to use when upgrading +the primary instance of the cluster as part of rolling updates. +The default method is "restart" + +*Appears in:* + +- [ClusterSpec](#clusterspec) + +| Field | Description | +| ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `switchover` | PrimaryUpdateMethodSwitchover means that the operator will switchover to another updated
replica when it needs to upgrade the primary instance.
Note: when using this method, the operator will reject updates that change both
the image name and PostgreSQL configuration parameters simultaneously to avoid
configuration mismatches during the switchover process.
| +| `restart` | PrimaryUpdateMethodRestart means that the operator will restart the primary instance in-place
when it needs to upgrade it
| + +#### PrimaryUpdateStrategy + +*Underlying type:* *string* + +PrimaryUpdateStrategy contains the strategy to follow when upgrading +the primary server of the cluster as part of rolling updates + +*Appears in:* + +- [ClusterSpec](#clusterspec) + +| Field | Description | +| -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `supervised` | PrimaryUpdateStrategySupervised means that the operator need to wait for the
user to manually issue a switchover request before updating the primary
server (`supervised`)
| +| `unsupervised` | PrimaryUpdateStrategyUnsupervised means that the operator will proceed with the
selected PrimaryUpdateMethod to another updated replica and then automatically update
the primary server (`unsupervised`, default)
| + +#### Probe + +Probe describes a health check to be performed against a container to determine whether it is +alive or ready to receive traffic. + +*Appears in:* + +- [LivenessProbe](#livenessprobe) +- [ProbeWithStrategy](#probewithstrategy) + +| Field | Description | Required | Default | Validation | +| ----------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ---------- | +| `initialDelaySeconds` *integer* | Number of seconds after the container has started before liveness probes are initiated.
More info: | | | | +| `timeoutSeconds` *integer* | Number of seconds after which the probe times out.
Defaults to 1 second. Minimum value is 1.
More info: | | | | +| `periodSeconds` *integer* | How often (in seconds) to perform the probe.
Default to 10 seconds. Minimum value is 1. | | | | +| `successThreshold` *integer* | Minimum consecutive successes for the probe to be considered successful after having failed.
Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. | | | | +| `failureThreshold` *integer* | Minimum consecutive failures for the probe to be considered failed after having succeeded.
Defaults to 3. Minimum value is 1. | | | | +| `terminationGracePeriodSeconds` *integer* | Optional duration in seconds the pod needs to terminate gracefully upon probe failure.
The grace period is the duration in seconds after the processes running in the pod are sent
a termination signal and the time when the processes are forcibly halted with a kill signal.
Set this value longer than the expected cleanup time for your process.
If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this
value overrides the value provided by the pod spec.
Value must be non-negative integer. The value zero indicates stop immediately via
the kill signal (no opportunity to shut down).
This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate.
Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. | | | | + +#### ProbeStrategyType + +*Underlying type:* *string* + +ProbeStrategyType is the type of the strategy used to declare a PostgreSQL instance +ready + +*Appears in:* + +- [ProbeWithStrategy](#probewithstrategy) + +| Field | Description | +| ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `pg_isready` | ProbeStrategyPgIsReady means that the pg_isready tool is used to determine
whether PostgreSQL is started up
| +| `streaming` | ProbeStrategyStreaming means that pg_isready is positive and the replica is
connected via streaming replication to the current primary and the lag is, if specified,
within the limit.
| +| `query` | ProbeStrategyQuery means that the server is able to connect to the superuser database
and able to execute a simple query like "-- ping"
| + +#### ProbeWithStrategy + +ProbeWithStrategy is the configuration of the startup probe + +*Appears in:* + +- [ProbesConfiguration](#probesconfiguration) + +| Field | Description | Required | Default | Validation | +| --------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ----------------------------------------- | +| `initialDelaySeconds` *integer* | Number of seconds after the container has started before liveness probes are initiated.
More info: | | | | +| `timeoutSeconds` *integer* | Number of seconds after which the probe times out.
Defaults to 1 second. Minimum value is 1.
More info: | | | | +| `periodSeconds` *integer* | How often (in seconds) to perform the probe.
Default to 10 seconds. Minimum value is 1. | | | | +| `successThreshold` *integer* | Minimum consecutive successes for the probe to be considered successful after having failed.
Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. | | | | +| `failureThreshold` *integer* | Minimum consecutive failures for the probe to be considered failed after having succeeded.
Defaults to 3. Minimum value is 1. | | | | +| `terminationGracePeriodSeconds` *integer* | Optional duration in seconds the pod needs to terminate gracefully upon probe failure.
The grace period is the duration in seconds after the processes running in the pod are sent
a termination signal and the time when the processes are forcibly halted with a kill signal.
Set this value longer than the expected cleanup time for your process.
If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this
value overrides the value provided by the pod spec.
Value must be non-negative integer. The value zero indicates stop immediately via
the kill signal (no opportunity to shut down).
This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate.
Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. | | | | +| `type` *[ProbeStrategyType](#probestrategytype)* | The probe strategy | | | Enum: [pg_isready streaming query]
| +| `maximumLag` *[Quantity](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#quantity-resource-api)* | Lag limit. Used only for `streaming` strategy | | | | + +#### ProbesConfiguration + +ProbesConfiguration represent the configuration for the probes +to be injected in the PostgreSQL Pods + +*Appears in:* + +- [ClusterSpec](#clusterspec) + +| Field | Description | Required | Default | Validation | +| ----------------------------------------------------- | --------------------------------- | -------- | ------- | ---------- | +| `startup` *[ProbeWithStrategy](#probewithstrategy)* | The startup probe configuration | True | | | +| `liveness` *[LivenessProbe](#livenessprobe)* | The liveness probe configuration | True | | | +| `readiness` *[ProbeWithStrategy](#probewithstrategy)* | The readiness probe configuration | True | | | + +#### Publication + +Publication is the Schema for the publications API + +| Field | Description | Required | Default | Validation | +| ------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------- | -------- | ------- | ---------- | +| `apiVersion` *string* | `postgresql.k8s.enterprisedb.io/v1` | True | | | +| `kind` *string* | `Publication` | True | | | +| `metadata` *[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#objectmeta-v1-meta)* | Refer to Kubernetes API documentation for fields of `metadata`. | True | | | +| `spec` *[PublicationSpec](#publicationspec)* | | True | | | +| `status` *[PublicationStatus](#publicationstatus)* | | True | | | + +#### PublicationReclaimPolicy + +*Underlying type:* *string* + +PublicationReclaimPolicy defines a policy for end-of-life maintenance of Publications. + +*Appears in:* + +- [PublicationSpec](#publicationspec) + +| Field | Description | +| -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `delete` | PublicationReclaimDelete means the publication will be deleted from Kubernetes on release
from its claim.
| +| `retain` | PublicationReclaimRetain means the publication will be left in its current phase for manual
reclamation by the administrator. The default policy is Retain.
| + +#### PublicationSpec + +PublicationSpec defines the desired state of Publication + +*Appears in:* + +- [Publication](#publication) + +| Field | Description | Required | Default | Validation | +| ------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ | -------- | ------- | ---------------------------- | +| `cluster` *[LocalObjectReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#localobjectreference-v1-core)* | The name of the PostgreSQL cluster that identifies the "publisher" | True | | | +| `name` *string* | The name of the publication inside PostgreSQL | True | | | +| `dbname` *string* | The name of the database where the publication will be installed in
the "publisher" cluster | True | | | +| `parameters` *object (keys:string, values:string)* | Publication parameters part of the `WITH` clause as expected by
PostgreSQL `CREATE PUBLICATION` command | | | | +| `target` *[PublicationTarget](#publicationtarget)* | Target of the publication as expected by PostgreSQL `CREATE PUBLICATION` command | True | | | +| `publicationReclaimPolicy` *[PublicationReclaimPolicy](#publicationreclaimpolicy)* | The policy for end-of-life maintenance of this publication | | retain | Enum: [delete retain]
| + +#### PublicationStatus + +PublicationStatus defines the observed state of Publication + +*Appears in:* + +- [Publication](#publication) + +| Field | Description | Required | Default | Validation | +| ------------------------------ | ---------------------------------------------------------------------------------- | -------- | ------- | ---------- | +| `observedGeneration` *integer* | A sequence number representing the latest
desired state that was synchronized | | | | +| `applied` *boolean* | Applied is true if the publication was reconciled correctly | | | | +| `message` *string* | Message is the reconciliation output message | | | | + +#### PublicationTarget + +PublicationTarget is what this publication should publish + +*Appears in:* + +- [PublicationSpec](#publicationspec) + +| Field | Description | Required | Default | Validation | +| --------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ----------------------- | +| `allTables` *boolean* | Marks the publication as one that replicates changes for all tables
in the database, including tables created in the future.
Corresponding to `FOR ALL TABLES` in PostgreSQL. | | | | +| `objects` *[PublicationTargetObject](#publicationtargetobject) array* | Just the following schema objects | | | MaxItems: 100000
| + +#### PublicationTargetObject + +PublicationTargetObject is an object to publish + +*Appears in:* + +- [PublicationTarget](#publicationtarget) + +| Field | Description | Required | Default | Validation | +| ----------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ---------- | +| `tablesInSchema` *string* | Marks the publication as one that replicates changes for all tables
in the specified list of schemas, including tables created in the
future. Corresponding to `FOR TABLES IN SCHEMA` in PostgreSQL. | | | | +| `table` *[PublicationTargetTable](#publicationtargettable)* | Specifies a list of tables to add to the publication. Corresponding
to `FOR TABLE` in PostgreSQL. | | | | + +#### PublicationTargetTable + +PublicationTargetTable is a table to publish + +*Appears in:* + +- [PublicationTargetObject](#publicationtargetobject) + +| Field | Description | Required | Default | Validation | +| ------------------------ | ----------------------------------------------------------------- | -------- | ------- | ---------- | +| `only` *boolean* | Whether to limit to the table only or include all its descendants | | | | +| `name` *string* | The table name | True | | | +| `schema` *string* | The schema name | | | | +| `columns` *string array* | The columns to publish | | | | + +#### RecoveryTarget + +RecoveryTarget allows to configure the moment where the recovery process +will stop. All the target options except TargetTLI are mutually exclusive. + +*Appears in:* + +- [BootstrapRecovery](#bootstraprecovery) + +| Field | Description | Required | Default | Validation | +| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ---------- | +| `backupID` *string* | The ID of the backup from which to start the recovery process.
If empty (default) the operator will automatically detect the backup
based on targetTime or targetLSN if specified. Otherwise use the
latest available backup in chronological order. | | | | +| `targetTLI` *string* | The target timeline ("latest" or a positive integer) | | | | +| `targetXID` *string* | The target transaction ID | | | | +| `targetName` *string* | The target name (to be previously created
with `pg_create_restore_point`) | | | | +| `targetLSN` *string* | The target LSN (Log Sequence Number) | | | | +| `targetTime` *string* | The target time as a timestamp in RFC3339 format or PostgreSQL timestamp format.
Timestamps without an explicit timezone are interpreted as UTC. | | | | +| `targetImmediate` *boolean* | End recovery as soon as a consistent state is reached | | | | +| `exclusive` *boolean* | Set the target to be exclusive. If omitted, defaults to false, so that
in Postgres, `recovery_target_inclusive` will be true | | | | + +#### ReplicaClusterConfiguration + +ReplicaClusterConfiguration encapsulates the configuration of a replica +cluster + +*Appears in:* + +- [ClusterSpec](#clusterspec) + +| Field | Description | Required | Default | Validation | +| ------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ------------------- | +| `self` *string* | Self defines the name of this cluster. It is used to determine if this is a primary
or a replica cluster, comparing it with `primary` | | | | +| `primary` *string* | Primary defines which Cluster is defined to be the primary in the distributed PostgreSQL cluster, based on the
topology specified in externalClusters | | | | +| `source` *string* | The name of the external cluster which is the replication origin | True | | MinLength: 1
| +| `enabled` *boolean* | If replica mode is enabled, this cluster will be a replica of an
existing cluster. Replica cluster can be created from a recovery
object store or via streaming through pg_basebackup.
Refer to the Replica clusters page of the documentation for more information. | | | | +| `promotionToken` *string* | A demotion token generated by an external cluster used to
check if the promotion requirements are met. | | | | +| `minApplyDelay` *[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#duration-v1-meta)* | When replica mode is enabled, this parameter allows you to replay
transactions only when the system time is at least the configured
time past the commit time. This provides an opportunity to correct
data loss errors. Note that when this parameter is set, a promotion
token cannot be used. | | | | + +#### ReplicationSlotsConfiguration + +ReplicationSlotsConfiguration encapsulates the configuration +of replication slots + +*Appears in:* + +- [ClusterSpec](#clusterspec) + +| Field | Description | Required | Default | Validation | +| --------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- | -------- | ------- | ----------------- | +| `highAvailability` *[ReplicationSlotsHAConfiguration](#replicationslotshaconfiguration)* | Replication slots for high availability configuration | | | | +| `updateInterval` *integer* | Standby will update the status of the local replication slots
every `updateInterval` seconds (default 30). | | | Minimum: 1
| +| `synchronizeReplicas` *[SynchronizeReplicasConfiguration](#synchronizereplicasconfiguration)* | Configures the synchronization of the user defined physical replication slots | | | | + +#### ReplicationSlotsHAConfiguration + +ReplicationSlotsHAConfiguration encapsulates the configuration +of the replication slots that are automatically managed by +the operator to control the streaming replication connections +with the standby instances for high availability (HA) purposes. +Replication slots are a PostgreSQL feature that makes sure +that PostgreSQL automatically keeps WAL files in the primary +when a streaming client (in this specific case a replica that +is part of the HA cluster) gets disconnected. + +*Appears in:* + +- [ReplicationSlotsConfiguration](#replicationslotsconfiguration) + +| Field | Description | Required | Default | Validation | +| -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ------------------------------ | +| `enabled` *boolean* | If enabled (default), the operator will automatically manage replication slots
on the primary instance and use them in streaming replication
connections with all the standby instances that are part of the HA
cluster. If disabled, the operator will not take advantage
of replication slots in streaming connections with the replicas.
This feature also controls replication slots in replica cluster,
from the designated primary to its cascading replicas. | | | | +| `slotPrefix` *string* | Prefix for replication slots managed by the operator for HA.
It may only contain lower case letters, numbers, and the underscore character.
This can only be set at creation time. By default set to `_cnp_`. | | | Pattern: `^[0-9a-z_]*$`
| +| `synchronizeLogicalDecoding` *boolean* | When enabled, the operator automatically manages synchronization of logical
decoding (replication) slots across high-availability clusters.
Requires one of the following conditions:
- PostgreSQL version 17 or later
- PostgreSQL version < 17 with pg_failover_slots extension enabled | | | | + +#### RoleConfiguration + +RoleConfiguration is the representation, in Kubernetes, of a PostgreSQL role +with the additional field Ensure specifying whether to ensure the presence or +absence of the role in the database + +The defaults of the CREATE ROLE command are applied +Reference: + +*Appears in:* + +- [DatabaseRoleSpec](#databaserolespec) +- [ManagedConfiguration](#managedconfiguration) + +| Field | Description | Required | Default | Validation | +| ------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ----------------------------- | +| `name` *string* | Name of the role | True | | | +| `comment` *string* | Description of the role | | | | +| `ensure` *[EnsureOption](#ensureoption)* | Ensure the role is `present` or `absent` - defaults to "present" | | present | Enum: [present absent]
| +| `passwordSecret` *[LocalObjectReference](https://pkg.go.dev/github.com/cloudnative-pg/machinery/pkg/api#LocalObjectReference)* | Secret containing the password of the role (if present).
If null, the password will be ignored unless DisablePassword is set.
When set, the secret must follow the `kubernetes.io/basic-auth` format
and contain both a `username` and a `password` field. | | | | +| `connectionLimit` *integer* | If the role can log in, this specifies how many concurrent
connections the role can make. `-1` (the default) means no limit. | | -1 | | +| `validUntil` *[Time](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#time-v1-meta)* | Date and time after which the role's password is no longer valid.
When omitted, the password will never expire (default). | | | | +| `inRoles` *string array* | List of one or more existing roles to which this role will be
immediately added as a new member. Default empty.
Changes to the list are applied to an existing role through
`GRANT` and `REVOKE` statements, not only at role creation. | | | | +| `inherit` *boolean* | Whether a role "inherits" the privileges of roles it is a member of.
Default is `true`. | | true | | +| `disablePassword` *boolean* | DisablePassword indicates that a role's password should be set to NULL in Postgres | | | | +| `superuser` *boolean* | Whether the role is a `superuser` who can override all access
restrictions within the database - superuser status is dangerous and
should be used only when really needed. You must yourself be a
superuser to create a new superuser. Defaults is `false`. | | | | +| `createdb` *boolean* | When set to `true`, the role being defined will be allowed to create
new databases. Specifying `false` (default) will deny a role the
ability to create databases. | | | | +| `createrole` *boolean* | Whether the role will be permitted to create, alter, drop, comment
on, change the security label for, and grant or revoke membership in
other roles. Default is `false`. | | | | +| `login` *boolean* | Whether the role is allowed to log in. A role having the `login`
attribute can be thought of as a user. Roles without this attribute
are useful for managing database privileges, but are not users in
the usual sense of the word. Default is `false`. | | | | +| `replication` *boolean* | Whether a role is a replication role. A role must have this
attribute (or be a superuser) in order to be able to connect to the
server in replication mode (physical or logical replication) and in
order to be able to create or drop replication slots. A role having
the `replication` attribute is a very highly privileged role, and
should only be used on roles actually used for replication. Default
is `false`. | | | | +| `bypassrls` *boolean* | Whether a role bypasses every row-level security (RLS) policy.
Default is `false`. | | | | + +#### RoleStatus + +*Underlying type:* *string* + +RoleStatus represents the status of a managed role in the cluster + +*Appears in:* + +- [ManagedRoles](#managedroles) + +| Field | Description | +| ------------------------ | ----------------------------------------------------------------------------------------------------- | +| `reconciled` | RoleStatusReconciled indicates the role in DB matches the Spec
| +| `not-managed` | RoleStatusNotManaged indicates the role is not in the Spec, therefore not managed
| +| `pending-reconciliation` | RoleStatusPendingReconciliation indicates the role in Spec requires updated/creation in DB
| +| `reserved` | RoleStatusReserved indicates this is one of the roles reserved by the operator. E.g. `postgres`
| + +#### SQLRefs + +SQLRefs holds references to ConfigMaps or Secrets +containing SQL files. The references are processed in a specific order: +first, all Secrets are processed, followed by all ConfigMaps. +Within each group, the processing order follows the sequence specified +in their respective arrays. + +*Appears in:* + +- [BootstrapInitDB](#bootstrapinitdb) + +| Field | Description | Required | Default | Validation | +| ----------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------ | -------- | ------- | ---------- | +| `secretRefs` *[SecretKeySelector](https://pkg.go.dev/github.com/cloudnative-pg/machinery/pkg/api#SecretKeySelector) array* | SecretRefs holds a list of references to Secrets | | | | +| `configMapRefs` *[ConfigMapKeySelector](https://pkg.go.dev/github.com/cloudnative-pg/machinery/pkg/api#ConfigMapKeySelector) array* | ConfigMapRefs holds a list of references to ConfigMaps | | | | + +#### ScheduledBackup + +ScheduledBackup is the Schema for the scheduledbackups API + +| Field | Description | Required | Default | Validation | +| ------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ---------- | +| `apiVersion` *string* | `postgresql.k8s.enterprisedb.io/v1` | True | | | +| `kind` *string* | `ScheduledBackup` | True | | | +| `metadata` *[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#objectmeta-v1-meta)* | Refer to Kubernetes API documentation for fields of `metadata`. | True | | | +| `spec` *[ScheduledBackupSpec](#scheduledbackupspec)* | Specification of the desired behavior of the ScheduledBackup.
More info: | True | | | +| `status` *[ScheduledBackupStatus](#scheduledbackupstatus)* | Most recently observed status of the ScheduledBackup. This data may not be up
to date. Populated by the system. Read-only.
More info: | | | | + +#### ScheduledBackupSpec + +ScheduledBackupSpec defines the desired state of ScheduledBackup + +*Appears in:* + +- [ScheduledBackup](#scheduledbackup) + +| Field | Description | Required | Default | Validation | +| ----------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ----------------- | ------------------------------------------------------ | +| `suspend` *boolean* | If this backup is suspended or not | | | | +| `immediate` *boolean* | If the first backup has to be immediately start after creation or not | | | | +| `schedule` *string* | The schedule does not follow the same format used in Kubernetes CronJobs
as it includes an additional seconds specifier,
see | True | | | +| `cluster` *[LocalObjectReference](https://pkg.go.dev/github.com/cloudnative-pg/machinery/pkg/api#LocalObjectReference)* | The cluster to backup | True | | | +| `backupOwnerReference` *string* | Indicates which ownerReference should be put inside the created backup resources.
- none: no owner reference for created backup objects (same behavior as before the field was introduced)
- self: sets the Scheduled backup object as owner of the backup
- cluster: set the cluster as owner of the backup
| | none | Enum: [none self cluster]
| +| `target` *[BackupTarget](#backuptarget)* | The policy to decide which instance should perform this backup. If empty,
it defaults to `cluster.spec.backup.target`.
Available options are empty string, `primary` and `prefer-standby`.
`primary` to have backups run always on primary instances,
`prefer-standby` to have backups run preferably on the most updated
standby, if available. | | | Enum: [primary prefer-standby]
| +| `method` *[BackupMethod](#backupmethod)* | The backup method to be used, possible options are `barmanObjectStore`,
`volumeSnapshot` or `plugin`. Defaults to: `barmanObjectStore`. | | barmanObjectStore | Enum: [barmanObjectStore volumeSnapshot plugin]
| +| `pluginConfiguration` *[BackupPluginConfiguration](#backuppluginconfiguration)* | Configuration parameters passed to the plugin managing this backup | | | | +| `online` *boolean* | Whether the default type of backup with volume snapshots is
online/hot (`true`, default) or offline/cold (`false`)
Overrides the default setting specified in the cluster field '.spec.backup.volumeSnapshot.online' | | | | +| `onlineConfiguration` *[OnlineConfiguration](#onlineconfiguration)* | Configuration parameters to control the online/hot backup with volume snapshots
Overrides the default settings specified in the cluster '.backup.volumeSnapshot.onlineConfiguration' stanza | | | | + +#### ScheduledBackupStatus + +ScheduledBackupStatus defines the observed state of ScheduledBackup + +*Appears in:* + +- [ScheduledBackup](#scheduledbackup) + +| Field | Description | Required | Default | Validation | +| -------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------- | -------- | ------- | ---------- | +| `lastCheckTime` *[Time](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#time-v1-meta)* | The latest time the schedule | | | | +| `lastScheduleTime` *[Time](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#time-v1-meta)* | Information when was the last time that backup was successfully scheduled. | | | | +| `nextScheduleTime` *[Time](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#time-v1-meta)* | Next time we will run a backup | | | | +| `error` *string* | Error is the latest admission validation error | | | | + +#### SchemaSpec + +SchemaSpec configures a schema in a database + +*Appears in:* + +- [DatabaseSpec](#databasespec) + +| Field | Description | Required | Default | Validation | +| ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ----------------------------- | +| `name` *string* | Name of the object (extension, schema, FDW, server) | True | | | +| `ensure` *[EnsureOption](#ensureoption)* | Specifies whether an object (e.g schema) should be present or absent
in the database. If set to `present`, the object will be created if
it does not exist. If set to `absent`, the extension/schema will be
removed if it exists. | | present | Enum: [present absent]
| +| `owner` *string* | The role name of the user who owns the schema inside PostgreSQL.
It maps to the `AUTHORIZATION` parameter of `CREATE SCHEMA` and the
`OWNER TO` command of `ALTER SCHEMA`. | True | | | + +#### SecretVersion + +SecretVersion contains a secret name and its ResourceVersion + +*Appears in:* + +- [PgBouncerSecrets](#pgbouncersecrets) +- [PoolerSecrets](#poolersecrets) + +| Field | Description | Required | Default | Validation | +| ------------------ | --------------------------------- | -------- | ------- | ---------- | +| `name` *string* | The name of the secret | | | | +| `version` *string* | The ResourceVersion of the secret | | | | + +#### SecretsResourceVersion + +SecretsResourceVersion is the resource versions of the secrets +managed by the operator + +*Appears in:* + +- [ClusterStatus](#clusterstatus) + +| Field | Description | Required | Default | Validation | +| -------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ---------- | +| `superuserSecretVersion` *string* | The resource version of the "postgres" user secret | | | | +| `replicationSecretVersion` *string* | The resource version of the "streaming_replica" user secret | | | | +| `applicationSecretVersion` *string* | The resource version of the "app" user secret | | | | +| `managedRoleSecretVersion` *object (keys:string, values:string)* | The resource versions of the managed roles secrets | | | | +| `caSecretVersion` *string* | Unused. Retained for compatibility with old versions. | | | | +| `clientCaSecretVersion` *string* | The resource version of the PostgreSQL client-side CA secret version | | | | +| `serverCaSecretVersion` *string* | The resource version of the PostgreSQL server-side CA secret version | | | | +| `serverSecretVersion` *string* | The resource version of the PostgreSQL server-side secret version | | | | +| `barmanEndpointCA` *string* | The resource version of the Barman Endpoint CA if provided | | | | +| `externalClusterSecretVersion` *object (keys:string, values:string)* | The resource versions of the external cluster secrets | | | | +| `metrics` *object (keys:string, values:string)* | A map with the versions of all the secrets used to pass metrics.
Map keys are the secret names, map values are the versions | | | | + +#### ServerSpec + +ServerSpec configures a server of a foreign data wrapper + +*Appears in:* + +- [DatabaseSpec](#databasespec) + +| Field | Description | Required | Default | Validation | +| ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ----------------------------- | +| `name` *string* | Name of the object (extension, schema, FDW, server) | True | | | +| `ensure` *[EnsureOption](#ensureoption)* | Specifies whether an object (e.g schema) should be present or absent
in the database. If set to `present`, the object will be created if
it does not exist. If set to `absent`, the extension/schema will be
removed if it exists. | | present | Enum: [present absent]
| +| `fdw` *string* | The name of the Foreign Data Wrapper (FDW) | True | | | +| `options` *[OptionSpec](#optionspec) array* | Options specifies the configuration options for the server
(key is the option name, value is the option value). | | | | +| `usage` *[UsageSpec](#usagespec) array* | List of roles for which `USAGE` privileges on the server are granted or revoked. | | | | + +#### ServiceAccountTemplate + +ServiceAccountTemplate contains the template needed to generate the service accounts + +*Appears in:* + +- [ClusterSpec](#clusterspec) + +| Field | Description | Required | Default | Validation | +| ---------------------------------- | --------------------------------------------------------------- | -------- | ------- | ---------- | +| `metadata` *[Metadata](#metadata)* | Refer to Kubernetes API documentation for fields of `metadata`. | True | | | + +#### ServiceSelectorType + +*Underlying type:* *string* + +ServiceSelectorType describes a valid value for generating the service selectors. +It indicates which type of service the selector applies to, such as read-write, read, or read-only + +*Validation:* + +- Enum: [rw r ro] + +*Appears in:* + +- [ManagedService](#managedservice) +- [ManagedServices](#managedservices) + +| Field | Description | +| ----- | ----------------------------------------------------------- | +| `rw` | ServiceSelectorTypeRW selects the read-write service.
| +| `r` | ServiceSelectorTypeR selects the read service.
| +| `ro` | ServiceSelectorTypeRO selects the read-only service.
| + +#### ServiceTemplateSpec + +ServiceTemplateSpec is a structure allowing the user to set +a template for Service generation. + +*Appears in:* + +- [ManagedService](#managedservice) +- [PoolerSpec](#poolerspec) + +| Field | Description | Required | Default | Validation | +| ---------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ---------- | +| `metadata` *[Metadata](#metadata)* | Refer to Kubernetes API documentation for fields of `metadata`. | | | | +| `spec` *[ServiceSpec](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#servicespec-v1-core)* | Specification of the desired behavior of the service.
More info: | | | | + +#### ServiceUpdateStrategy + +*Underlying type:* *string* + +ServiceUpdateStrategy describes how the changes to the managed service should be handled + +*Validation:* + +- Enum: [patch replace] + +*Appears in:* + +- [ManagedService](#managedservice) + +#### SnapshotOwnerReference + +*Underlying type:* *string* + +SnapshotOwnerReference defines the reference type for the owner of the snapshot. +This specifies which owner the processed resources should relate to. + +*Appears in:* + +- [VolumeSnapshotConfiguration](#volumesnapshotconfiguration) + +| Field | Description | +| --------- | ------------------------------------------------------------------------------------------------- | +| `none` | SnapshotOwnerReferenceNone indicates that the snapshot does not have any owner reference.
| +| `backup` | SnapshotOwnerReferenceBackup indicates that the snapshot is owned by the backup resource.
| +| `cluster` | SnapshotOwnerReferenceCluster indicates that the snapshot is owned by the cluster resource.
| + +#### SnapshotType + +*Underlying type:* *string* + +SnapshotType is a type of allowed import + +*Appears in:* + +- [Import](#import) + +| Field | Description | +| -------------- | ----------------------------------------------------------------------------------- | +| `monolith` | MonolithSnapshotType indicates to execute the monolith clone typology
| +| `microservice` | MicroserviceSnapshotType indicates to execute the microservice clone typology
| + +#### StorageConfiguration + +StorageConfiguration is the configuration used to create and reconcile PVCs, +usable for WAL volumes, PGDATA volumes, or tablespaces + +*Appears in:* + +- [ClusterSpec](#clusterspec) +- [TablespaceConfiguration](#tablespaceconfiguration) + +| Field | Description | Required | Default | Validation | +| --------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ---------- | +| `storageClass` *string* | StorageClass to use for PVCs. Applied after
evaluating the PVC template, if available.
If not specified, the generated PVCs will use the
default storage class | | | | +| `size` *string* | Size of the storage. Required if not already specified in the PVC template.
Changes to this field are automatically reapplied to the created PVCs.
Size cannot be decreased. | | | | +| `resizeInUseVolumes` *boolean* | Resize existent PVCs, defaults to true | | true | | +| `pvcTemplate` *[PersistentVolumeClaimSpec](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#persistentvolumeclaimspec-v1-core)* | Template to be used to generate the Persistent Volume Claim | | | | + +#### Subscription + +Subscription is the Schema for the subscriptions API + +| Field | Description | Required | Default | Validation | +| ------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------- | -------- | ------- | ---------- | +| `apiVersion` *string* | `postgresql.k8s.enterprisedb.io/v1` | True | | | +| `kind` *string* | `Subscription` | True | | | +| `metadata` *[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#objectmeta-v1-meta)* | Refer to Kubernetes API documentation for fields of `metadata`. | True | | | +| `spec` *[SubscriptionSpec](#subscriptionspec)* | | True | | | +| `status` *[SubscriptionStatus](#subscriptionstatus)* | | True | | | + +#### SubscriptionReclaimPolicy + +*Underlying type:* *string* + +SubscriptionReclaimPolicy describes a policy for end-of-life maintenance of Subscriptions. + +*Appears in:* + +- [SubscriptionSpec](#subscriptionspec) + +| Field | Description | +| -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `delete` | SubscriptionReclaimDelete means the subscription will be deleted from Kubernetes on release
from its claim.
| +| `retain` | SubscriptionReclaimRetain means the subscription will be left in its current phase for manual
reclamation by the administrator. The default policy is Retain.
| + +#### SubscriptionSpec + +SubscriptionSpec defines the desired state of Subscription + +*Appears in:* + +- [Subscription](#subscription) + +| Field | Description | Required | Default | Validation | +| ------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ---------------------------- | +| `cluster` *[LocalObjectReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#localobjectreference-v1-core)* | The name of the PostgreSQL cluster that identifies the "subscriber" | True | | | +| `name` *string* | The name of the subscription inside PostgreSQL | True | | | +| `dbname` *string* | The name of the database where the publication will be installed in
the "subscriber" cluster | True | | | +| `parameters` *object (keys:string, values:string)* | Subscription parameters included in the `WITH` clause of the PostgreSQL
`CREATE SUBSCRIPTION` command. Most parameters cannot be changed
after the subscription is created and will be ignored if modified
later, except for a limited set documented at:
| | | | +| `publicationName` *string* | The name of the publication inside the PostgreSQL database in the
"publisher" | True | | | +| `publicationDBName` *string* | The name of the database containing the publication on the external
cluster. Defaults to the one in the external cluster definition. | | | | +| `externalClusterName` *string* | The name of the external cluster with the publication ("publisher") | True | | | +| `subscriptionReclaimPolicy` *[SubscriptionReclaimPolicy](#subscriptionreclaimpolicy)* | The policy for end-of-life maintenance of this subscription | | retain | Enum: [delete retain]
| + +#### SubscriptionStatus + +SubscriptionStatus defines the observed state of Subscription + +*Appears in:* + +- [Subscription](#subscription) + +| Field | Description | Required | Default | Validation | +| ------------------------------ | ---------------------------------------------------------------------------------- | -------- | ------- | ---------- | +| `observedGeneration` *integer* | A sequence number representing the latest
desired state that was synchronized | | | | +| `applied` *boolean* | Applied is true if the subscription was reconciled correctly | | | | +| `message` *string* | Message is the reconciliation output message | | | | + +#### SwitchReplicaClusterStatus + +SwitchReplicaClusterStatus contains all the statuses regarding the switch of a cluster to a replica cluster + +*Appears in:* + +- [ClusterStatus](#clusterstatus) + +| Field | Description | Required | Default | Validation | +| ---------------------- | -------------------------------------------------------------------------------------------------- | -------- | ------- | ---------- | +| `inProgress` *boolean* | InProgress indicates if there is an ongoing procedure of switching a cluster to a replica cluster. | | | | + +#### SyncReplicaElectionConstraints + +SyncReplicaElectionConstraints contains the constraints for sync replicas election. + +For anti-affinity parameters two instances are considered in the same location +if all the labels values match. + +In future synchronous replica election restriction by name will be supported. + +*Appears in:* + +- [PostgresConfiguration](#postgresconfiguration) + +| Field | Description | Required | Default | Validation | +| --------------------------------------- | -------------------------------------------------------------------------------------------------------------- | -------- | ------- | ---------- | +| `nodeLabelsAntiAffinity` *string array* | A list of node labels values to extract and compare to evaluate if the pods reside in the same topology or not | | | | +| `enabled` *boolean* | This flag enables the constraints for sync replicas | True | | | + +#### SynchronizeReplicasConfiguration + +SynchronizeReplicasConfiguration contains the configuration for the synchronization of user defined +physical replication slots + +*Appears in:* + +- [ReplicationSlotsConfiguration](#replicationslotsconfiguration) + +| Field | Description | Required | Default | Validation | +| -------------------------------- | ------------------------------------------------------------------------------------------------------------- | -------- | ------- | ---------- | +| `enabled` *boolean* | When set to true, every replication slot that is on the primary is synchronized on each standby | True | | | +| `excludePatterns` *string array* | List of regular expression patterns to match the names of replication slots to be excluded (by default empty) | | | | + +#### SynchronousReplicaConfiguration + +SynchronousReplicaConfiguration contains the configuration of the +PostgreSQL synchronous replication feature. +Important: at this moment, also `.spec.minSyncReplicas` and `.spec.maxSyncReplicas` +need to be considered. + +*Appears in:* + +- [PostgresConfiguration](#postgresconfiguration) + +| Field | Description | Required | Default | Validation | +| ------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | --------------------------------- | +| `method` *[SynchronousReplicaConfigurationMethod](#synchronousreplicaconfigurationmethod)* | Method to select synchronous replication standbys from the listed
servers, accepting 'any' (quorum-based synchronous replication) or
'first' (priority-based synchronous replication) as values. | True | | Enum: [any first]
| +| `number` *integer* | Specifies the number of synchronous standby servers that
transactions must wait for responses from. | True | | | +| `maxStandbyNamesFromCluster` *integer* | Specifies the maximum number of local cluster pods that can be
automatically included in the `synchronous_standby_names` option in
PostgreSQL. | | | | +| `standbyNamesPre` *string array* | A user-defined list of application names to be added to
`synchronous_standby_names` before local cluster pods (the order is
only useful for priority-based synchronous replication). | | | | +| `standbyNamesPost` *string array* | A user-defined list of application names to be added to
`synchronous_standby_names` after local cluster pods (the order is
only useful for priority-based synchronous replication). | | | | +| `dataDurability` *[DataDurabilityLevel](#datadurabilitylevel)* | If set to "required", data durability is strictly enforced. Write operations
with synchronous commit settings (`on`, `remote_write`, or `remote_apply`) will
block if there are insufficient healthy replicas, ensuring data persistence.
If set to "preferred", data durability is maintained when healthy replicas
are available, but the required number of instances will adjust dynamically
if replicas become unavailable. This setting relaxes strict durability enforcement
to allow for operational continuity. This setting is only applicable if both
`standbyNamesPre` and `standbyNamesPost` are unset (empty). | | | Enum: [required preferred]
| +| `failoverQuorum` *boolean* | FailoverQuorum enables a quorum-based check before failover, improving
data durability and safety during failover events in {{name.ln}}-managed
PostgreSQL clusters. | | | | + +#### SynchronousReplicaConfigurationMethod + +*Underlying type:* *string* + +SynchronousReplicaConfigurationMethod configures whether to use +quorum based replication or a priority list + +*Appears in:* + +- [SynchronousReplicaConfiguration](#synchronousreplicaconfiguration) + +#### TDEConfiguration + +TDEConfiguration contains the Transparent Data Encryption configuration + +*Appears in:* + +- [EPASConfiguration](#epasconfiguration) + +| Field | Description | Required | Default | Validation | +| ----------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ---------- | +| `enabled` *boolean* | True if we want to have TDE enabled | | | | +| `secretKeyRef` *[SecretKeySelector](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#secretkeyselector-v1-core)* | Reference to the secret that contains the encryption key | | | | +| `wrapCommand` *[SecretKeySelector](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#secretkeyselector-v1-core)* | WrapCommand is the encrypt command provided by the user | | | | +| `unwrapCommand` *[SecretKeySelector](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#secretkeyselector-v1-core)* | UnwrapCommand is the decryption command provided by the user | | | | +| `passphraseCommand` *[SecretKeySelector](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#secretkeyselector-v1-core)* | PassphraseCommand is the command executed to get the passphrase that will be
passed to the OpenSSL command to encrypt and decrypt | | | | + +#### TablespaceConfiguration + +TablespaceConfiguration is the configuration of a tablespace, and includes +the storage specification for the tablespace + +*Appears in:* + +- [ClusterSpec](#clusterspec) + +| Field | Description | Required | Default | Validation | +| --------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ---------- | +| `name` *string* | The name of the tablespace | True | | | +| `storage` *[StorageConfiguration](#storageconfiguration)* | The storage configuration for the tablespace | True | | | +| `owner` *[DatabaseRoleRef](#databaseroleref)* | Owner is the PostgreSQL user owning the tablespace | | | | +| `temporary` *boolean* | When set to true, the tablespace will be added as a `temp_tablespaces`
entry in PostgreSQL, and will be available to automatically house temp
database objects, or other temporary files. Please refer to PostgreSQL
documentation for more information on the `temp_tablespaces` GUC. | | false | | + +#### TablespaceState + +TablespaceState represents the state of a tablespace in a cluster + +*Appears in:* + +- [ClusterStatus](#clusterstatus) + +| Field | Description | Required | Default | Validation | +| ----------------------------------------------- | -------------------------------------------------- | -------- | ------- | ---------- | +| `name` *string* | Name is the name of the tablespace | True | | | +| `owner` *string* | Owner is the PostgreSQL user owning the tablespace | | | | +| `state` *[TablespaceStatus](#tablespacestatus)* | State is the latest reconciliation state | True | | | +| `error` *string* | Error is the reconciliation error, if any | | | | + +#### TablespaceStatus + +*Underlying type:* *string* + +TablespaceStatus represents the status of a tablespace in the cluster + +*Appears in:* + +- [TablespaceState](#tablespacestate) + +| Field | Description | +| ------------ | -------------------------------------------------------------------------------------------------------- | +| `reconciled` | TablespaceStatusReconciled indicates the tablespace in DB matches the Spec
| +| `pending` | TablespaceStatusPendingReconciliation indicates the tablespace in Spec requires creation in the DB
| + +#### Topology + +Topology contains the cluster topology + +*Appears in:* + +- [ClusterStatus](#clusterstatus) + +| Field | Description | Required | Default | Validation | +| ----------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ---------- | +| `instances` *object (keys:[PodName](#podname), values:[PodTopologyLabels](#podtopologylabels))* | Instances contains the pod topology of the instances | | | | +| `nodesUsed` *integer* | NodesUsed represents the count of distinct nodes accommodating the instances.
A value of '1' suggests that all instances are hosted on a single node,
implying the absence of High Availability (HA). Ideally, this value should
be the same as the number of instances in the Postgres HA cluster, implying
shared nothing architecture on the compute side. | | | | +| `successfullyExtracted` *boolean* | SuccessfullyExtracted indicates if the topology data was extract. It is useful to enact fallback behaviors
in synchronous replica election in case of failures | | | | + +#### UsageSpec + +UsageSpec configures a usage for a foreign data wrapper + +*Appears in:* + +- [FDWSpec](#fdwspec) +- [ServerSpec](#serverspec) + +| Field | Description | Required | Default | Validation | +| ---------------------------------------- | ----------------- | -------- | ------- | --------------------------- | +| `name` *string* | Name of the usage | True | | | +| `type` *[UsageSpecType](#usagespectype)* | The type of usage | | grant | Enum: [grant revoke]
| + +#### UsageSpecType + +*Underlying type:* *string* + +UsageSpecType describes the type of usage specified in the `usage` field of the +`Database` object. + +*Appears in:* + +- [UsageSpec](#usagespec) + +| Field | Description | +| -------- | -------------------------------------------------------------------------------------------------------- | +| `grant` | GrantUsageSpecType indicates a grant usage permission.
The default usage permission is grant.
| +| `revoke` | RevokeUsageSpecType indicates a revoke usage permission.
| + +#### VolumeSnapshotConfiguration + +VolumeSnapshotConfiguration represents the configuration for the execution of snapshot backups. + +*Appears in:* + +- [BackupConfiguration](#backupconfiguration) + +| Field | Description | Required | Default | Validation | +| ---------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------------------------------------------------- | ---------------------------------- | +| `labels` *object (keys:string, values:string)* | Labels are key-value pairs that will be added to .metadata.labels snapshot resources. | | | | +| `annotations` *object (keys:string, values:string)* | Annotations key-value pairs that will be added to .metadata.annotations snapshot resources. | | | | +| `className` *string* | ClassName specifies the Snapshot Class to be used for PG_DATA PersistentVolumeClaim.
It is the default class for the other types if no specific class is present | | | | +| `walClassName` *string* | WalClassName specifies the Snapshot Class to be used for the PG_WAL PersistentVolumeClaim. | | | | +| `tablespaceClassName` *object (keys:string, values:string)* | TablespaceClassName specifies the Snapshot Class to be used for the tablespaces.
defaults to the PGDATA Snapshot Class, if set | | | | +| `snapshotOwnerReference` *[SnapshotOwnerReference](#snapshotownerreference)* | SnapshotOwnerReference indicates the type of owner reference the snapshot should have | | none | Enum: [none cluster backup]
| +| `online` *boolean* | Whether the default type of backup with volume snapshots is
online/hot (`true`, default) or offline/cold (`false`) | | true | | +| `onlineConfiguration` *[OnlineConfiguration](#onlineconfiguration)* | Configuration parameters to control the online/hot backup with volume snapshots | | { immediateCheckpoint:false waitForArchive:true } | | diff --git a/product_docs/docs/postgres_for_kubernetes/1/postgres_upgrades.mdx b/product_docs/docs/postgres_for_kubernetes/1/postgres_upgrades.mdx index ada5d60639..905ebb68a7 100644 --- a/product_docs/docs/postgres_for_kubernetes/1/postgres_upgrades.mdx +++ b/product_docs/docs/postgres_for_kubernetes/1/postgres_upgrades.mdx @@ -7,15 +7,15 @@ originalFilePath: 'src/postgres_upgrades.md' PostgreSQL upgrades fall into two categories: -- [Minor version upgrades](#minor-version-upgrades) (e.g., from 17.0 to 17.1) -- [Major version upgrades](#major-version-upgrades) (e.g., from 16.x to 17.0) +- [Minor version upgrades](#minor-version-upgrades) (e.g., from 18.0 to 18.1) +- [Major version upgrades](#major-version-upgrades) (e.g., from 16.x to 18.0) ## Minor Version Upgrades PostgreSQL version numbers follow a `major.minor` format. For instance, in -version 17.1: +version 18.1: -- `17` is the major version +- `18` is the major version - `1` is the minor version Minor releases are fully compatible with earlier and later minor releases of @@ -68,7 +68,7 @@ operating system distribution. For example, if your previous version uses a There is a bug in PostgreSQL 17.0 through 17.5 that prevents successful upgrades if the `max_slot_wal_keep_size` parameter is set to any value other than `-1`. The upgrade process will fail with an error related to replication slot configuration. -This issue has been [fixed in PostgreSQL 17.6 and 18beta2 or later versions](https://github.com/postgres/postgres/commit/f36e5774). +This issue has been [fixed in PostgreSQL 17.6 and 18 or later versions](https://github.com/postgres/postgres/commit/f36e5774). If you are using PostgreSQL 17.0 through 17.5, ensure that you upgrade to at least PostgreSQL 17.6 before attempting a major upgrade, or make sure to temporarily set the `max_slot_wal_keep_size` parameter to `-1` in your cluster configuration. @@ -156,6 +156,62 @@ usually possible, without having to perform a full recovery from a backup. Ensure you monitor the process closely and take corrective action if needed. !!! +#### Extensions during a major upgrade + +When a cluster declares image-volume extensions, the upgrade `Job` mounts both +the source-version and the target-version extension images side by side. +Source-version extensions are needed so the old server can start with its +existing shared libraries already in place. +Target-version extensions (built for the new PostgreSQL major) must also be +present so that `pg_upgrade` can properly perform the upgrade to the new major: + +- Source-version extensions are mounted at `/extensions/` (the + steady-state path), so `dynamic_library_path` and `extension_control_path` + GUCs in the old `PGDATA` keep the existing values. + This ensures that, in case of major upgrade failure, a revert to the old + major version will work seamlessly. +- Target-version extensions are temporarily mounted at `/new-extensions/` + just during the upgrade job, and `dynamic_library_path` and `extension_control_path` + are configured accordingly for the `PGDATA` of the new major. + +`LD_LIBRARY_PATH` and `PATH` are extended with both sets, so binaries and +shared objects from either version are reachable. +Environment variables declared via `extensions[].env` obey the rules +described in [Precedence and Conflict Resolution](imagevolume_extensions.md#precedence-and-conflict-resolution). + +!!!note + +Target-version entries are applied **after** source-version entries. When the +same variable is defined for both, the target-version value takes precedence. +!!! + +#### When `pg_upgrade` emits `update_extensions.sql` + +`pg_upgrade` emits an `update_extensions.sql` script inside the `PGDATA` +when a target cluster contains extensions whose `default_version` is +newer than the version `pg_upgrade` left installed. Until that script is +applied, the SQL-level extension metadata in `pg_catalog` lags the +shared libraries actually loaded by the running server. + +The script lives inside the primary pod's `PGDATA`. +You can execute it using the database superuser (`postgres`) to +update those extensions in all databases: + +```sh +PRIMARY=$(kubectl get cluster -o jsonpath='{.status.currentPrimary}') +SCRIPT=/var/lib/postgresql/data/pgdata/update_extensions.sql + +kubectl exec -i "$PRIMARY" -- psql -f "$SCRIPT" +``` + +!!!note + +The script path above assumes the default `PGDATA` location used by the +{{name.ln}} operand images. The operator also logs the resolved path when +`pg_upgrade` emits the script, so check the operator logs if your operand image +uses a different `PGDATA`. +!!! + ### Backup and WAL Archive Considerations When performing a major upgrade, `pg_upgrade` creates a new database system @@ -190,7 +246,7 @@ Before upgrade (PostgreSQL 16): ```yaml spec: - imageName: docker.enterprisedb.com/k8s_enterprise/postgresql:16-minimal-ubi9 + imageName: docker.enterprisedb.com/k8s/postgresql:16-minimal-ubi9 plugins: - name: plugin-barman-cloud enabled: true @@ -203,18 +259,18 @@ To trigger the upgrade, change both `imageName` and `serverName` together: ```yaml spec: - imageName: docker.enterprisedb.com/k8s_enterprise/postgresql:17-minimal-ubi9 + imageName: docker.enterprisedb.com/k8s/postgresql:18-minimal-ubi9 plugins: - name: plugin-barman-cloud enabled: true parameters: destinationPath: s3://my-bucket/ - serverName: cluster-example-pg17 + serverName: cluster-example-pg18 ``` With this configuration, the old archive at `cluster-example-pg16` remains intact for pre-upgrade recovery, while the upgraded cluster writes to -`cluster-example-pg17`. +`cluster-example-pg18`. !!!info The deprecated in-tree `barmanObjectStore` implementation also requires manual @@ -249,8 +305,8 @@ This will return output similar to: PostgreSQL 16.x ... ``` -To upgrade the cluster to version 17, update the `imageName` field by changing -the major version tag from `16` to `17`: +To upgrade the cluster to version 18, update the `imageName` field by changing +the major version tag from `16` to `18`: ```yaml apiVersion: postgresql.k8s.enterprisedb.io/v1 @@ -258,7 +314,7 @@ kind: Cluster metadata: name: cluster-example spec: - imageName: docker.enterprisedb.com/k8s/postgresql:17-minimal-ubi9 + imageName: docker.enterprisedb.com/k8s/postgresql:18-minimal-ubi9 instances: 3 storage: size: 1Gi @@ -275,7 +331,7 @@ spec: - The PVC groups of the replicas (`cluster-example-2` and `cluster-example-3`) are removed. - The primary pod is restarted. - - Two new replicas (`cluster-example-4` and `cluster-example-5`) are + - Two new replicas (`cluster-example-2` and `cluster-example-3`) are re-cloned from the upgraded primary. Once the upgrade is complete, you can verify the new major version by running @@ -288,7 +344,7 @@ kubectl cnp psql cluster-example -- -qAt -c 'SELECT version()' This should now return output similar to: ```console -PostgreSQL 17.x ... +PostgreSQL 18.x ... ``` You can now update the statistics by running `ANALYZE` on the `app` database: diff --git a/product_docs/docs/postgres_for_kubernetes/1/preview_version.mdx b/product_docs/docs/postgres_for_kubernetes/1/preview_version.mdx index 8d9e2a2480..eace89098e 100644 --- a/product_docs/docs/postgres_for_kubernetes/1/preview_version.mdx +++ b/product_docs/docs/postgres_for_kubernetes/1/preview_version.mdx @@ -72,7 +72,7 @@ non-production environment: - **Report Issues:** **Immediately report any issues or unexpected behavior** by opening a GitHub issue and clearly marking it with a **`Release Candidate`** tag or label, along with the RC version number - (e.g., `1.29.0-rc1`). + (e.g., `1.31.0-rc1`). ## Usage Advisory diff --git a/product_docs/docs/postgres_for_kubernetes/1/rel_notes/src/1.28.4_rel_notes.yml b/product_docs/docs/postgres_for_kubernetes/1/rel_notes/src/1.28.4_rel_notes.yml new file mode 100644 index 0000000000..90d0536ab9 --- /dev/null +++ b/product_docs/docs/postgres_for_kubernetes/1/rel_notes/src/1.28.4_rel_notes.yml @@ -0,0 +1,400 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/EnterpriseDB/docs/refs/heads/develop/tools/automation/generators/relgen/relnote-schema.json +product: EDB CloudNativePG Cluster +version: 1.28.4 +date: 29 June 2026 +intro: | + This release of EDB Postgres® AI for CloudNativePG™ Cluster includes the following: +components: + "Operator": 1.28.4 + "CNP plugin": 1.28.4 + upstream-merge: Upstream [1.28.4](https://cloudnative-pg.io/docs/1.28/release_notes/v1.28/) +highlights: | + The `cluster` reference is now immutable on the `Database`, `Pooler`, + `Publication`, `Subscription`, and `ScheduledBackup` resources. Pointing one + of these objects at a different cluster has no well-defined semantics and + previously left the controllers in an inconsistent state; the update is now + rejected at the API server via a CEL validation rule. + ([#10743](https://github.com/cloudnative-pg/cloudnative-pg/pull/10743)) +relnotes: +- relnote: | + Added a label selector to the `Cluster` scale subresource (`status.selector`), + making a `Cluster` a valid `targetRef` for the Vertical Pod Autoscaler (VPA) + and Horizontal Pod Autoscaler (HPA), which can now map a `Cluster` to its + instance pods. + details: | + Contributed by @sebv004. + jira: + addresses: #8996 + type: Enhancement + impact: High + +- relnote: | + The operator now emits a `Warning` `PrimaryStatusCheckFailed` event on the + `Cluster` when the primary pod is `Ready` from the kubelet perspective but the + operator's `/pg/status` check fails and failover is deferred, giving users + visibility into the deferral via `kubectl describe cluster`. + jira: + addresses: #10509 + type: Enhancement + impact: High + +- relnote: | + The operator now reloads a CNPG-i plugin automatically when its pods are + rolled: it watches the `EndpointSlices` backing plugin `Services` and + re-enqueues every cluster using the plugin once the new pods become `Ready`, + so an upgraded plugin is picked up without waiting for the next resync. + jira: + addresses: #10836 + type: Enhancement + impact: High + +- relnote: | + `search_path` pinning on operator-issued connections + details: | + a database owner could plant overloaded built-in operators in the `public` + schema and alter the `search_path` so that operator introspection probes, + running as the cluster superuser, resolved those overloads before + `pg_catalog`, a `CWE-426` privilege-escalation chain (same class as + `CVE-2018-1058`) that could lead to in-pod RCE via `COPY ... FROM PROGRAM`. + The operator now pins `search_path = pg_catalog, public, pg_temp` on every + pooled connection so it ships in the startup message and takes precedence over + tenant-controlled defaults. + jira: + addresses: #10774 + type: Security + impact: High + +- relnote: | + Operator-side SCRAM-SHA-256 password encoding + details: | + the operator now SCRAM-SHA-256 encodes cleartext role passwords before issuing + `CREATE`/`ALTER ROLE ... PASSWORD`, so the literal PostgreSQL parses (and that + extensions such as `pg_stat_statements` or `pgaudit` may capture) is the SCRAM + verifier rather than the cleartext secret. Pre-hashed (MD5 or SCRAM) values + are forwarded unchanged, and the per-Secret annotation + `k8s.enterprisedb.io/passwordPassthrough: "enabled"` opts out. + jira: + addresses: #10724 + type: Security + impact: High + +- relnote: | + Added support for Kubernetes 1.35 and enabled unit tests on Kubernetes 1.36. + jira: + addresses: #10900 + type: Change + impact: High + +- relnote: | + Updated the default PostgreSQL version to 18.4. + jira: + addresses: #10719 + type: Change + impact: High + +- relnote: | + Updated the Kubernetes versions used to test the operator on public cloud + providers. + jira: + addresses: #10720, #10563 + type: Change + impact: High + +- relnote: | + Fixed `spec.postgresql.parameters` accepting keys that are not valid + PostgreSQL parameter names, which could inject arbitrary directives into + `postgresql.conf`; key names are now validated by the webhook. + jira: + addresses: #11029 + type: Bug Fix + impact: High + +- relnote: | + Fixed declarative `Database`, `Publication`, and `Subscription` objects + reporting a stale primary-side status forever after their cluster was demoted + to a replica; the controller now re-checks the replica condition and watches + the `Cluster` so a demotion is detected promptly. + jira: + addresses: #10871 + type: Bug Fix + impact: High + +- relnote: | + Fixed non-sequential pod names (for example `-1`, `-3`) caused by the instance + serial counter being advanced before the corresponding `Job` and PVCs were + created; the bump is now persisted only after those resources exist. + jira: + addresses: #10491 + type: Bug Fix + impact: High + +- relnote: | + Fixed a switchover deadlock when a WAL-archiver plugin was enabled on an + existing cluster: with `primaryUpdateMethod: switchover` the primary could not + be rolled out because a clean demotion needs the archiver sidecar that is + still missing. + details: | + The operator now recreates the primary Pod in place so the sidecar is injected + and archiving resumes. + jira: + addresses: #11032 + type: Bug Fix + impact: High + +- relnote: | + Fixed a cluster staying in `Setting up primary` indefinitely when the + instance-creation Job exhausted its backoff limit; the operator now detects + the terminal Job failure and marks the cluster unrecoverable, naming the + failed Job and pointing to its logs. + jira: + addresses: #11035 + type: Bug Fix + impact: High + +- relnote: | + Fixed deletion of a `Database`, `Publication`, or `Subscription` getting stuck + in `Terminating` on a replica cluster, where the replica gate ran before the + finalizer reconciler and the finalizer was never released. + details: | + On a replica the PostgreSQL object is left to the primary cluster. + jira: + addresses: #10853 + type: Bug Fix + impact: High + +- relnote: | + Fixed a conflicting duplicate `Database` or `Subscription` with a `delete` + reclaim policy dropping the PostgreSQL object owned by the surviving CR; the + drop is now gated on a recorded reconciliation. + jira: + addresses: #10870 + type: Bug Fix + impact: High + +- relnote: | + Fixed the `postgres` superuser being left locked out after superuser access + was disabled and then re-enabled, because the cached secret version was not + invalidated and the password was never re-applied. + details: | + Diagnosed by @mhartmann-jaconi. + jira: + addresses: #10834 + type: Bug Fix + impact: High + +- relnote: | + Fixed backups getting stuck in the `started` phase when the instance manager + running them was restarted (for example by the in-place upgrade following an + operator upgrade) before the backup reached `running`; the reconciliation is + now rescheduled so the lost session is detected. + jira: + addresses: #10859 + type: Bug Fix + impact: High + +- relnote: | + Fixed resource leaks when concurrent `Backup` objects raced: backups now run + in strict creation-time order, so an already-executing backup is never + preempted by a newer one and its replication slot and PostgreSQL session are + no longer orphaned on the primary. + details: | + Contributed by @GabriFedi97. + jira: + addresses: #10747 + type: Bug Fix + impact: High + +- relnote: | + Fixed role reconciliation clearing the password on a PostgreSQL role when the + referenced Secret could not be fetched; the role is now left untouched until + the Secret becomes available, and per-action errors are aggregated for better + visibility. + jira: + addresses: #10053 + type: Bug Fix + impact: High + +- relnote: | + Fixed a bootstrap failure where a metrics-exporter setup error (commonly a + duplicate-key race with the controller) rolled back `streaming_replica` + creation and wedged replica joins. + details: | + The metrics-exporter step now runs in a separate transaction. Contributed by + @BlaiseAntony. + jira: + addresses: #10749 + type: Bug Fix + impact: High + +- relnote: | + Fixed a `ScheduledBackup` controller loop that occurred when a `Backup` was + created but its status patch never landed; the controller now adopts an + existing `Backup` for the next iteration instead of looping on + `AlreadyExists`. + jira: + addresses: #10612 + type: Bug Fix + impact: High + +- relnote: | + Fixed a nil-pointer panic when reconciling a `Pooler` whose `Cluster` has been + deleted. + jira: + addresses: #10667 + type: Bug Fix + impact: High + +- relnote: | + Fixed bootstrap log handling so that all named log pipes (`postgres`, + `postgres.csv`, and `postgres.json`) get consumers during + `WithActiveInstance`, preventing regular files from being created in place of + the named pipes. + jira: + addresses: #10043 + type: Bug Fix + impact: High + +- relnote: | + Fixed generation of invalid IPv6 URLs by wrapping the address in square + brackets. + details: | + Contributed by @Infinoid. + jira: + addresses: #10682 + type: Bug Fix + impact: High + +- relnote: | + Fixed an external cluster plugin still being treated as active when its + configuration set `enabled: false`. + jira: + addresses: #10932 + type: Bug Fix + impact: High + +- relnote: | + Fixed a race during bootstrap recovery from an object store where the restore + job could read a stale `Cluster` (primary not yet recorded and timeline still + unset) and have its `.history` files rejected by the split-brain guard. + details: | + When this happened, recovery stopped at the base backup's timeline and + silently dropped transactions committed on later timelines. History files are + now allowed while the cluster timeline is unset. Contributed by @dennispidun. + jira: + addresses: #10818 + type: Bug Fix + impact: High + +- relnote: | + Fixed a cache race during cluster creation when the server and client CA + resolve to the same Secret (the default): a stale informer cache triggered a + redundant `Create` that failed with `AlreadyExists` and could leave the + cluster stuck in `Unable to create required cluster objects`. + details: | + The operator now reuses the already-fetched CA Secret when the names match. + jira: + addresses: #10989 + type: Bug Fix + impact: High + +- relnote: | + Fixed the `pg_basebackup` bootstrap path overwriting or failing on a + pre-existing `PGDATA` (for example after a replica Pod restart) by enforcing + the same pre-flight directory check already applied by the other bootstrap + methods; this also protects statically provisioned PVCs from being silently + overwritten. + jira: + addresses: #11006 + type: Bug Fix + impact: High + +- relnote: | + Fixed the `Cluster` phase flapping between `Healthy` and a plugin-failure + phase when a post-reconcile plugin hook returned an error; the `Healthy` phase + is now registered as the last step of a successful reconciliation, so a loop + that ends in a plugin error never reports `Healthy`. + details: | + Contributed by @GabriFedi97. + jira: + addresses: #10421 + type: Bug Fix + impact: High + +- relnote: | + Fixed stale certificate data and partial reads after an external server's + Secret was rotated (for example a CA bundle shrinking from two certificates to + one): the file is now written atomically, so libpq always reads either the old + or the new value, never a mix. + details: | + Contributed by @Anand-240. + jira: + addresses: #10975 + type: Bug Fix + impact: High + +- relnote: | + Fixed plugin connectivity to use the plugin `Service` FQDN instead of its + short name, avoiding failures when a cluster-level proxy is automatically + injected into pods. + details: | + Contributed by @kdautrey. + jira: + addresses: #10921 + type: Bug Fix + impact: High + +- relnote: | + Fixed excessive operator log noise from the per-request `Cluster` + create/update validation webhook messages, now logged at `debug` instead of + `info`. + jira: + addresses: #10984 + type: Bug Fix + impact: High + +- relnote: | + Fixed a first-primary bootstrap deadlock where a status-patch conflict after + the data PVC was created but before the initialization Job was started left + the orphan Pending PVC counted as an instance, blocking the bootstrap gate; + the PVC-state reconciler now recreates the bootstrap Job reusing the assigned + serial. + jira: + addresses: #11039 + type: Bug Fix + impact: High + +- relnote: | + Fixed external cluster names and secret selector references being joined into + filesystem paths without validation, letting a `..` component or path + separator escape the external secrets directory when the instance manager + dumps connection material; these values are now rejected at the validating + webhook and re-checked at the write site. + details: | + Reported by @r0binak. + jira: + addresses: #11045 + type: Bug Fix + impact: High + +- relnote: | + Fixed `kubectl cnp psql` on Windows, where execution relied on a Unix-only + system call and failed with "not supported by windows"; Windows now launches + `kubectl exec` as a child process. + details: | + Contributed by @Utkarsh-sharma47. + jira: + addresses: #10972 + type: Bug Fix + impact: High + +- relnote: | + Fixed an unbounded memory leak in `kubectl cnp logs -f` on busy clusters, + where a per-log-group timer was never released; timers are now reused across + iterations. + details: | + Contributed by @Anand-240. + jira: + addresses: #10976 + type: Bug Fix + impact: High + diff --git a/product_docs/docs/postgres_for_kubernetes/1/rel_notes/src/1.29.2_rel_notes.yml b/product_docs/docs/postgres_for_kubernetes/1/rel_notes/src/1.29.2_rel_notes.yml new file mode 100644 index 0000000000..ce848b8a7f --- /dev/null +++ b/product_docs/docs/postgres_for_kubernetes/1/rel_notes/src/1.29.2_rel_notes.yml @@ -0,0 +1,424 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/EnterpriseDB/docs/refs/heads/develop/tools/automation/generators/relgen/relnote-schema.json +product: EDB CloudNativePG Cluster +version: 1.29.2 +date: 29 June 2026 +intro: | + This release of EDB Postgres® AI for CloudNativePG™ Cluster includes the following: +components: + "Operator": 1.29.2 + "CNP plugin": 1.29.2 + upstream-merge: Upstream [1.29.2](https://cloudnative-pg.io/docs/1.29/release_notes/v1.29/) +highlights: | + The `cluster` reference is now immutable on the `Database`, `Pooler`, + `Publication`, `Subscription`, and `ScheduledBackup` resources. Pointing one + of these objects at a different cluster has no well-defined semantics and + previously left the controllers in an inconsistent state; the update is now + rejected at the API server via a CEL validation rule. + ([#10743](https://github.com/cloudnative-pg/cloudnative-pg/pull/10743)) +relnotes: +- relnote: | + Enabled `pg_upgrade` in-place major upgrades to PostgreSQL 19 or later for + clusters that use Image Volume extensions, building on the extension-path + support added to `pg_upgrade` in PostgreSQL 19. + details: | + During the upgrade `Job`, the source- and target-version extension images are + mounted side by side, so the old server keeps its libraries and a failed + upgrade reverts cleanly. + jira: + addresses: #10366 + type: Enhancement + impact: High + +- relnote: | + Added a label selector to the `Cluster` scale subresource (`status.selector`), + making a `Cluster` a valid `targetRef` for the Vertical Pod Autoscaler (VPA) + and Horizontal Pod Autoscaler (HPA), which can now map a `Cluster` to its + instance pods. + details: | + Contributed by @sebv004. + jira: + addresses: #8996 + type: Enhancement + impact: High + +- relnote: | + The operator now emits a `Warning` `PrimaryStatusCheckFailed` event on the + `Cluster` when the primary pod is `Ready` from the kubelet perspective but the + operator's `/pg/status` check fails and failover is deferred, giving users + visibility into the deferral via `kubectl describe cluster`. + jira: + addresses: #10509 + type: Enhancement + impact: High + +- relnote: | + The operator now reloads a CNPG-i plugin automatically when its pods are + rolled: it watches the `EndpointSlices` backing plugin `Services` and + re-enqueues every cluster using the plugin once the new pods become `Ready`, + so an upgraded plugin is picked up without waiting for the next resync. + jira: + addresses: #10836 + type: Enhancement + impact: High + +- relnote: | + `search_path` pinning on operator-issued connections + details: | + a database owner could plant overloaded built-in operators in the `public` + schema and alter the `search_path` so that operator introspection probes, + running as the cluster superuser, resolved those overloads before + `pg_catalog`, a `CWE-426` privilege-escalation chain (same class as + `CVE-2018-1058`) that could lead to in-pod RCE via `COPY ... FROM PROGRAM`. + The operator now pins `search_path = pg_catalog, public, pg_temp` on every + pooled connection so it ships in the startup message and takes precedence over + tenant-controlled defaults. + jira: + addresses: #10774 + type: Security + impact: High + +- relnote: | + Operator-side SCRAM-SHA-256 password encoding + details: | + the operator now SCRAM-SHA-256 encodes cleartext role passwords before issuing + `CREATE`/`ALTER ROLE ... PASSWORD`, so the literal PostgreSQL parses (and that + extensions such as `pg_stat_statements` or `pgaudit` may capture) is the SCRAM + verifier rather than the cleartext secret. Pre-hashed (MD5 or SCRAM) values + are forwarded unchanged, and the per-Secret annotation + `k8s.enterprisedb.io/passwordPassthrough: "enabled"` opts out. + jira: + addresses: #10724 + type: Security + impact: High + +- relnote: | + Added support for Kubernetes 1.36. + jira: + addresses: #10900 + type: Change + impact: High + +- relnote: | + Updated the default PostgreSQL version to 18.4. + jira: + addresses: #10719 + type: Change + impact: High + +- relnote: | + Updated the Kubernetes versions used to test the operator on public cloud + providers. + jira: + addresses: #10720, #10563 + type: Change + impact: High + +- relnote: | + Fixed `spec.postgresql.parameters` accepting keys that are not valid + PostgreSQL parameter names, which could inject arbitrary directives into + `postgresql.conf`; key names are now validated by the webhook. + jira: + addresses: #11029 + type: Bug Fix + impact: High + +- relnote: | + Fixed declarative `Database`, `Publication`, and `Subscription` objects + reporting a stale primary-side status forever after their cluster was demoted + to a replica; the controller now re-checks the replica condition and watches + the `Cluster` so a demotion is detected promptly. + jira: + addresses: #10871 + type: Bug Fix + impact: High + +- relnote: | + Fixed non-sequential pod names (for example `-1`, `-3`) caused by the instance + serial counter being advanced before the corresponding `Job` and PVCs were + created; the bump is now persisted only after those resources exist. + jira: + addresses: #10491 + type: Bug Fix + impact: High + +- relnote: | + Fixed a switchover deadlock when a WAL-archiver plugin was enabled on an + existing cluster: with `primaryUpdateMethod: switchover` the primary could not + be rolled out because a clean demotion needs the archiver sidecar that is + still missing. + details: | + The operator now recreates the primary Pod in place so the sidecar is injected + and archiving resumes. + jira: + addresses: #11032 + type: Bug Fix + impact: High + +- relnote: | + Fixed a cluster staying in `Setting up primary` indefinitely when the + instance-creation Job exhausted its backoff limit; the operator now detects + the terminal Job failure and marks the cluster unrecoverable, naming the + failed Job and pointing to its logs. + jira: + addresses: #11035 + type: Bug Fix + impact: High + +- relnote: | + Fixed deletion of a `Database`, `Publication`, or `Subscription` getting stuck + in `Terminating` on a replica cluster, where the replica gate ran before the + finalizer reconciler and the finalizer was never released. + details: | + On a replica the PostgreSQL object is left to the primary cluster. + jira: + addresses: #10853 + type: Bug Fix + impact: High + +- relnote: | + Fixed a conflicting duplicate `Database` or `Subscription` with a `delete` + reclaim policy dropping the PostgreSQL object owned by the surviving CR; the + drop is now gated on a recorded reconciliation. + jira: + addresses: #10870 + type: Bug Fix + impact: High + +- relnote: | + Fixed the `postgres` superuser being left locked out after superuser access + was disabled and then re-enabled, because the cached secret version was not + invalidated and the password was never re-applied. + details: | + Diagnosed by @mhartmann-jaconi. + jira: + addresses: #10834 + type: Bug Fix + impact: High + +- relnote: | + Fixed backups getting stuck in the `started` phase when the instance manager + running them was restarted (for example by the in-place upgrade following an + operator upgrade) before the backup reached `running`; the reconciliation is + now rescheduled so the lost session is detected. + jira: + addresses: #10859 + type: Bug Fix + impact: High + +- relnote: | + Fixed `exec`/`attach` streaming to negotiate WebSocket with a SPDY fallback, + restoring compatibility both with Kubernetes versions that have removed SPDY + and with platforms such as OpenShift that reject WebSocket exec upgrades. + details: | + Contributed by @bartscheers. + jira: + addresses: #10876, #10933 + type: Bug Fix + impact: High + +- relnote: | + Fixed resource leaks when concurrent `Backup` objects raced: backups now run + in strict creation-time order, so an already-executing backup is never + preempted by a newer one and its replication slot and PostgreSQL session are + no longer orphaned on the primary. + details: | + Contributed by @GabriFedi97. + jira: + addresses: #10747 + type: Bug Fix + impact: High + +- relnote: | + Fixed role reconciliation clearing the password on a PostgreSQL role when the + referenced Secret could not be fetched; the role is now left untouched until + the Secret becomes available, and per-action errors are aggregated for better + visibility. + jira: + addresses: #10053 + type: Bug Fix + impact: High + +- relnote: | + Fixed a bootstrap failure where a metrics-exporter setup error (commonly a + duplicate-key race with the controller) rolled back `streaming_replica` + creation and wedged replica joins. + details: | + The metrics-exporter step now runs in a separate transaction. Contributed by + @BlaiseAntony. + jira: + addresses: #10749 + type: Bug Fix + impact: High + +- relnote: | + Fixed a `ScheduledBackup` controller loop that occurred when a `Backup` was + created but its status patch never landed; the controller now adopts an + existing `Backup` for the next iteration instead of looping on + `AlreadyExists`. + jira: + addresses: #10612 + type: Bug Fix + impact: High + +- relnote: | + Fixed a nil-pointer panic when reconciling a `Pooler` whose `Cluster` has been + deleted. + jira: + addresses: #10667 + type: Bug Fix + impact: High + +- relnote: | + Fixed bootstrap log handling so that all named log pipes (`postgres`, + `postgres.csv`, and `postgres.json`) get consumers during + `WithActiveInstance`, preventing regular files from being created in place of + the named pipes. + jira: + addresses: #10043 + type: Bug Fix + impact: High + +- relnote: | + Fixed generation of invalid IPv6 URLs by wrapping the address in square + brackets. + details: | + Contributed by @Infinoid. + jira: + addresses: #10682 + type: Bug Fix + impact: High + +- relnote: | + Fixed an external cluster plugin still being treated as active when its + configuration set `enabled: false`. + jira: + addresses: #10932 + type: Bug Fix + impact: High + +- relnote: | + Fixed a race during bootstrap recovery from an object store where the restore + job could read a stale `Cluster` (primary not yet recorded and timeline still + unset) and have its `.history` files rejected by the split-brain guard. + details: | + When this happened, recovery stopped at the base backup's timeline and + silently dropped transactions committed on later timelines. History files are + now allowed while the cluster timeline is unset. Contributed by @dennispidun. + jira: + addresses: #10818 + type: Bug Fix + impact: High + +- relnote: | + Fixed a cache race during cluster creation when the server and client CA + resolve to the same Secret (the default): a stale informer cache triggered a + redundant `Create` that failed with `AlreadyExists` and could leave the + cluster stuck in `Unable to create required cluster objects`. + details: | + The operator now reuses the already-fetched CA Secret when the names match. + jira: + addresses: #10989 + type: Bug Fix + impact: High + +- relnote: | + Fixed the `pg_basebackup` bootstrap path overwriting or failing on a + pre-existing `PGDATA` (for example after a replica Pod restart) by enforcing + the same pre-flight directory check already applied by the other bootstrap + methods; this also protects statically provisioned PVCs from being silently + overwritten. + jira: + addresses: #11006 + type: Bug Fix + impact: High + +- relnote: | + Fixed the `Cluster` phase flapping between `Healthy` and a plugin-failure + phase when a post-reconcile plugin hook returned an error; the `Healthy` phase + is now registered as the last step of a successful reconciliation, so a loop + that ends in a plugin error never reports `Healthy`. + details: | + Contributed by @GabriFedi97. + jira: + addresses: #10421 + type: Bug Fix + impact: High + +- relnote: | + Fixed stale certificate data and partial reads after an external server's + Secret was rotated (for example a CA bundle shrinking from two certificates to + one): the file is now written atomically, so libpq always reads either the old + or the new value, never a mix. + details: | + Contributed by @Anand-240. + jira: + addresses: #10975 + type: Bug Fix + impact: High + +- relnote: | + Fixed plugin connectivity to use the plugin `Service` FQDN instead of its + short name, avoiding failures when a cluster-level proxy is automatically + injected into pods. + details: | + Contributed by @kdautrey. + jira: + addresses: #10921 + type: Bug Fix + impact: High + +- relnote: | + Fixed excessive operator log noise from the per-request `Cluster` + create/update validation webhook messages, now logged at `debug` instead of + `info`. + jira: + addresses: #10984 + type: Bug Fix + impact: High + +- relnote: | + Fixed a first-primary bootstrap deadlock where a status-patch conflict after + the data PVC was created but before the initialization Job was started left + the orphan Pending PVC counted as an instance, blocking the bootstrap gate; + the PVC-state reconciler now recreates the bootstrap Job reusing the assigned + serial. + jira: + addresses: #11039 + type: Bug Fix + impact: High + +- relnote: | + Fixed external cluster names and secret selector references being joined into + filesystem paths without validation, letting a `..` component or path + separator escape the external secrets directory when the instance manager + dumps connection material; these values are now rejected at the validating + webhook and re-checked at the write site. + details: | + Reported by @r0binak. + jira: + addresses: #11045 + type: Bug Fix + impact: High + +- relnote: | + Fixed `kubectl cnp psql` on Windows, where execution relied on a Unix-only + system call and failed with "not supported by windows"; Windows now launches + `kubectl exec` as a child process. + details: | + Contributed by @Utkarsh-sharma47. + jira: + addresses: #10972 + type: Bug Fix + impact: High + +- relnote: | + Fixed an unbounded memory leak in `kubectl cnp logs -f` on busy clusters, + where a per-log-group timer was never released; timers are now reused across + iterations. + details: | + Contributed by @Anand-240. + jira: + addresses: #10976 + type: Bug Fix + impact: High + diff --git a/product_docs/docs/postgres_for_kubernetes/1/rel_notes/src/1.30.0_rel_notes.yml b/product_docs/docs/postgres_for_kubernetes/1/rel_notes/src/1.30.0_rel_notes.yml new file mode 100644 index 0000000000..a5955ae860 --- /dev/null +++ b/product_docs/docs/postgres_for_kubernetes/1/rel_notes/src/1.30.0_rel_notes.yml @@ -0,0 +1,566 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/EnterpriseDB/docs/refs/heads/develop/tools/automation/generators/relgen/relnote-schema.json +product: EDB CloudNativePG Cluster +version: 1.30.0 +date: 29 June 2026 +intro: | + This release of EDB Postgres® AI for CloudNativePG™ Cluster includes the following: +components: + "Operator": 1.30.0 + "CNP plugin": 1.30.0 + upstream-merge: Upstream [1.30.0](https://cloudnative-pg.io/docs/1.30/release_notes/v1.30/) +highlights: | + The `cluster` reference is now immutable on the `Database`, `Pooler`, + `Publication`, `Subscription`, and `ScheduledBackup` resources. Pointing one + of these objects at a different cluster has no well-defined semantics and + previously left the controllers in an inconsistent state; the update is now + rejected at the API server via a CEL validation rule. + ([#10743](https://github.com/cloudnative-pg/cloudnative-pg/pull/10743)) +relnotes: +- relnote: | + Primary `Lease` for safe primary election + details: | + introduced a Kubernetes `Lease` object (named after the cluster) that acts as + a mutex serializing primary promotion: the instance manager must hold the + lease before acting as primary and releases it on clean shutdown so replicas + can promote without waiting for the full TTL. Timings are configurable via the + new `.spec.primaryLease` stanza. The lease is a promotion gate, not a fence. + Primary isolation remains responsible for fencing. + jira: + addresses: #10627 + type: Feature + impact: High + +- relnote: | + `DatabaseRole` CRD for declarative role management + details: | + introduced a `DatabaseRole` custom resource that manages a PostgreSQL role as + a standalone Kubernetes object, instead of declaring it inline in the + `Cluster`'s `.spec.managed.roles` stanza. Each role gets its own lifecycle, + status, and RBAC, which suits GitOps workflows and lets role definitions live + next to the applications that own them. The spec reuses the same + `RoleConfiguration` structure as the inline method, so migrating a role is a + matter of moving the stanza into its own manifest. A + `databaseRoleReclaimPolicy` field (`retain`, the default, or `delete`) + controls what happens to the role when the resource is deleted, mirroring + persistent volumes. + jira: + addresses: #6155 + type: Feature + impact: High + +- relnote: | + TLS client certificates for declarative roles + details: | + a `DatabaseRole` can now include a `clientCertificate` block to have the + operator automatically generate and renew a TLS client certificate, signed by + the cluster's client CA and stored in a `-client-cert` + Secret. This enables password-free PostgreSQL `cert` authentication; the + Secret is cleaned up when the feature is disabled or the `DatabaseRole` is + deleted. + jira: + addresses: #10896 + type: Feature + impact: High + +- relnote: | + PgBouncer image management via image catalogs + details: | + the `Pooler` resource can now reference an entry in an `ImageCatalog` or + `ClusterImageCatalog` through the new `spec.pgbouncer.imageCatalogRef` field, + centralizing PgBouncer image management. When a catalog entry is updated, all + referencing `Poolers` are automatically reconciled and roll out the new image + without any change to their spec. The resolved image is reported in + `status.image`, and a new `status.phase` (`active`, `paused`, `inactive`, or + `failed`), also surfaced as a `Phase` column in `kubectl get pooler`, + summarizes the lifecycle. + jira: + addresses: #10568 + type: Feature + impact: High + +- relnote: | + Enabled `pg_upgrade` in-place major upgrades to PostgreSQL 19 or later for + clusters that use Image Volume extensions, building on the extension-path + support added to `pg_upgrade` in PostgreSQL 19. + details: | + During the upgrade `Job`, the source- and target-version extension images are + mounted side by side, so the old server keeps its libraries and a failed + upgrade reverts cleanly. + jira: + addresses: #10366 + type: Enhancement + impact: High + +- relnote: | + Added TLS support for the `Pooler` metrics endpoint via + `.spec.monitoring.tls.enabled`. + details: | + When enabled, the metrics server is served over HTTPS, reusing the certificate + and key from `.spec.pgbouncer.clientTLSSecret` and reloading it on every + handshake to support rotation without a restart; the generated `PodMonitor` + scrapes over `https` accordingly. + jira: + addresses: #10466 + type: Enhancement + impact: High + +- relnote: | + Added a label selector to the `Cluster` scale subresource (`status.selector`), + making a `Cluster` a valid `targetRef` for the Vertical Pod Autoscaler (VPA) + and Horizontal Pod Autoscaler (HPA), which can now map a `Cluster` to its + instance pods. + details: | + Contributed by @sebv004. + jira: + addresses: #8996 + type: Enhancement + impact: High + +- relnote: | + The operator now emits a `Warning` `PrimaryStatusCheckFailed` event on the + `Cluster` when the primary pod is `Ready` from the kubelet perspective but the + operator's `/pg/status` check fails and failover is deferred, giving users + visibility into the deferral via `kubectl describe cluster`. + jira: + addresses: #10509 + type: Enhancement + impact: High + +- relnote: | + Added the `ENABLE_WEBHOOK_NAMESPACE_SUFFIX` flag, which suffixes the + operator's webhook configuration names with `-` so that + multiple operator instances can coexist on the same cluster. + details: | + The operator only looks up these configurations; users must create and + maintain them. Contributed by @maxlengdell. + jira: + addresses: #10420 + type: Enhancement + impact: High + +- relnote: | + The operator now reloads a CNPG-i plugin automatically when its pods are + rolled: it watches the `EndpointSlices` backing plugin `Services` and + re-enqueues every cluster using the plugin once the new pods become `Ready`, + so an upgraded plugin is picked up without waiting for the next resync. + jira: + addresses: #10836 + type: Enhancement + impact: High + +- relnote: | + Instance serial numbers are now assigned by reusing the lowest free slot among + existing instance names, instead of always incrementing a global counter. + details: | + Pod and PVC names stay stable across instance recreation (for example, an + instance recreated after a node drain comes back with the same name), and + serials freed by deleted instances are reclaimed. A new `Initialized` cluster + condition reports whether the cluster has completed its first bootstrap, and + `status.latestGeneratedNode` is deprecated: it is no longer written, but is + preserved on the CRD for backward compatibility. + jira: + addresses: #10548 + type: Enhancement + impact: High + +- relnote: | + Defaulting and validation now run during reconciliation as a fallback when + admission webhooks are unavailable, or configured to ignore failures, so the + operator no longer reconciles invalid or incomplete specs. + details: | + Missing defaults are applied directly, and validation failures are surfaced in + the resource status instead of failing silently later. + jira: + addresses: #10874 + type: Enhancement + impact: High + +- relnote: | + `search_path` pinning on operator-issued connections + details: | + a database owner could plant overloaded built-in operators in the `public` + schema and alter the `search_path` so that operator introspection probes, + running as the cluster superuser, resolved those overloads before + `pg_catalog`, a `CWE-426` privilege-escalation chain (same class as + `CVE-2018-1058`) that could lead to in-pod RCE via `COPY ... FROM PROGRAM`. + The operator now pins `search_path = pg_catalog, public, pg_temp` on every + pooled connection so it ships in the startup message and takes precedence over + tenant-controlled defaults. + jira: + addresses: #10774 + type: Security + impact: High + +- relnote: | + Authenticated operator-to-instance-manager calls + details: | + the instance manager's remote webserver previously accepted unauthenticated + requests, so any process on the pod network could trigger backups, instance + manager upgrades, or WAL archival. The operator now generates an in-memory + ECDSA P-256 client certificate at startup and reconciles its SHA-256 + fingerprint into the cluster status; the instance manager rejects requests to + sensitive endpoints that do not present a matching certificate. + jira: + addresses: #10579 + type: Security + impact: High + +- relnote: | + Operator-side SCRAM-SHA-256 password encoding + details: | + the operator now SCRAM-SHA-256 encodes cleartext role passwords before issuing + `CREATE`/`ALTER ROLE ... PASSWORD`, so the literal PostgreSQL parses (and that + extensions such as `pg_stat_statements` or `pgaudit` may capture) is the SCRAM + verifier rather than the cleartext secret. Pre-hashed (MD5 or SCRAM) values + are forwarded unchanged, and the per-Secret annotation + `k8s.enterprisedb.io/passwordPassthrough: "enabled"` opts out. + jira: + addresses: #10724 + type: Security + impact: High + +- relnote: | + Added support for Kubernetes 1.36. + jira: + addresses: #10900 + type: Change + impact: High + +- relnote: | + Updated the default PostgreSQL version to 18.4. + jira: + addresses: #10719 + type: Change + impact: High + +- relnote: | + Updated the Kubernetes versions used to test the operator on public cloud + providers. + jira: + addresses: #10720, #10563 + type: Change + impact: High + +- relnote: | + Fixed declarative `Database`, `Publication`, and `Subscription` objects + reporting a stale primary-side status forever after their cluster was demoted + to a replica; the controller now re-checks the replica condition and watches + the `Cluster` so a demotion is detected promptly. + jira: + addresses: #10871 + type: Bug Fix + impact: High + +- relnote: | + Fixed non-sequential pod names (for example `-1`, `-3`) caused by the instance + serial counter being advanced before the corresponding `Job` and PVCs were + created; the bump is now persisted only after those resources exist. + jira: + addresses: #10491 + type: Bug Fix + impact: High + +- relnote: | + Fixed deletion of a `Database`, `Publication`, or `Subscription` getting stuck + in `Terminating` on a replica cluster, where the replica gate ran before the + finalizer reconciler and the finalizer was never released. + details: | + On a replica the PostgreSQL object is left to the primary cluster. + jira: + addresses: #10853 + type: Bug Fix + impact: High + +- relnote: | + Fixed a conflicting duplicate `Database` or `Subscription` with a `delete` + reclaim policy dropping the PostgreSQL object owned by the surviving CR; the + drop is now gated on a recorded reconciliation. + jira: + addresses: #10870 + type: Bug Fix + impact: High + +- relnote: | + Fixed the `postgres` superuser being left locked out after superuser access + was disabled and then re-enabled, because the cached secret version was not + invalidated and the password was never re-applied. + details: | + Diagnosed by @mhartmann-jaconi. + jira: + addresses: #10834 + type: Bug Fix + impact: High + +- relnote: | + Fixed backups getting stuck in the `started` phase when the instance manager + running them was restarted (for example by the in-place upgrade following an + operator upgrade) before the backup reached `running`; the reconciliation is + now rescheduled so the lost session is detected. + jira: + addresses: #10859 + type: Bug Fix + impact: High + +- relnote: | + Fixed `exec`/`attach` streaming to negotiate WebSocket with a SPDY fallback, + restoring compatibility both with Kubernetes versions that have removed SPDY + and with platforms such as OpenShift that reject WebSocket exec upgrades. + details: | + Contributed by @bartscheers. + jira: + addresses: #10876, #10933 + type: Bug Fix + impact: High + +- relnote: | + Fixed resource leaks when concurrent `Backup` objects raced: backups now run + in strict creation-time order, so an already-executing backup is never + preempted by a newer one and its replication slot and PostgreSQL session are + no longer orphaned on the primary. + details: | + Contributed by @GabriFedi97. + jira: + addresses: #10747 + type: Bug Fix + impact: High + +- relnote: | + Fixed role reconciliation clearing the password on a PostgreSQL role when the + referenced Secret could not be fetched; the role is now left untouched until + the Secret becomes available, and per-action errors are aggregated for better + visibility. + jira: + addresses: #10053 + type: Bug Fix + impact: High + +- relnote: | + Fixed a bootstrap failure where a metrics-exporter setup error (commonly a + duplicate-key race with the controller) rolled back `streaming_replica` + creation and wedged replica joins. + details: | + The metrics-exporter step now runs in a separate transaction. Contributed by + @BlaiseAntony. + jira: + addresses: #10749 + type: Bug Fix + impact: High + +- relnote: | + Fixed a `ScheduledBackup` controller loop that occurred when a `Backup` was + created but its status patch never landed; the controller now adopts an + existing `Backup` for the next iteration instead of looping on + `AlreadyExists`. + jira: + addresses: #10612 + type: Bug Fix + impact: High + +- relnote: | + Fixed a nil-pointer panic when reconciling a `Pooler` whose `Cluster` has been + deleted. + jira: + addresses: #10667 + type: Bug Fix + impact: High + +- relnote: | + Fixed bootstrap log handling so that all named log pipes (`postgres`, + `postgres.csv`, and `postgres.json`) get consumers during + `WithActiveInstance`, preventing regular files from being created in place of + the named pipes. + jira: + addresses: #10043 + type: Bug Fix + impact: High + +- relnote: | + Fixed generation of invalid IPv6 URLs by wrapping the address in square + brackets. + details: | + Contributed by @Infinoid. + jira: + addresses: #10682 + type: Bug Fix + impact: High + +- relnote: | + Fixed an external cluster plugin still being treated as active when its + configuration set `enabled: false`. + jira: + addresses: #10932 + type: Bug Fix + impact: High + +- relnote: | + Fixed a race during bootstrap recovery from an object store where the restore + job could read a stale `Cluster` (primary not yet recorded and timeline still + unset) and have its `.history` files rejected by the split-brain guard. + details: | + When this happened, recovery stopped at the base backup's timeline and + silently dropped transactions committed on later timelines. History files are + now allowed while the cluster timeline is unset. Contributed by @dennispidun. + jira: + addresses: #10818 + type: Bug Fix + impact: High + +- relnote: | + Fixed a race where deleting an instance's PVCs could leave the instance + permanently stuck: if the data PVC was removed while a WAL PVC was still + terminating, the operator recreated the instance bound to the terminating + volume, leaving the Pod unschedulable and blocking all further reconciliation. + details: | + The operator now waits for terminating PVCs to be fully removed before + recreating or reattaching an instance, and surfaces the wait through a log + line and the cluster phase. + jira: + addresses: #11017 + type: Bug Fix + impact: High + +- relnote: | + Fixed a cache race during cluster creation when the server and client CA + resolve to the same Secret (the default): a stale informer cache triggered a + redundant `Create` that failed with `AlreadyExists` and could leave the + cluster stuck in `Unable to create required cluster objects`. + details: | + The operator now reuses the already-fetched CA Secret when the names match. + jira: + addresses: #10989 + type: Bug Fix + impact: High + +- relnote: | + Fixed the `pg_basebackup` bootstrap path overwriting or failing on a + pre-existing `PGDATA` (for example after a replica Pod restart) by enforcing + the same pre-flight directory check already applied by the other bootstrap + methods; this also protects statically provisioned PVCs from being silently + overwritten. + jira: + addresses: #11006 + type: Bug Fix + impact: High + +- relnote: | + Fixed the `Cluster` phase flapping between `Healthy` and a plugin-failure + phase when a post-reconcile plugin hook returned an error; the `Healthy` phase + is now registered as the last step of a successful reconciliation, so a loop + that ends in a plugin error never reports `Healthy`. + details: | + Contributed by @GabriFedi97. + jira: + addresses: #10421 + type: Bug Fix + impact: High + +- relnote: | + Fixed stale certificate data and partial reads after an external server's + Secret was rotated (for example a CA bundle shrinking from two certificates to + one): the file is now written atomically, so libpq always reads either the old + or the new value, never a mix. + details: | + Contributed by @Anand-240. + jira: + addresses: #10975 + type: Bug Fix + impact: High + +- relnote: | + Fixed plugin connectivity to use the plugin `Service` FQDN instead of its + short name, avoiding failures when a cluster-level proxy is automatically + injected into pods. + details: | + Contributed by @kdautrey. + jira: + addresses: #10921 + type: Bug Fix + impact: High + +- relnote: | + Fixed excessive operator log noise from the per-request `Cluster` + create/update validation webhook messages, now logged at `debug` instead of + `info`. + jira: + addresses: #10984 + type: Bug Fix + impact: High + +- relnote: | + Fixed `spec.postgresql.parameters` accepting keys that are not valid + PostgreSQL parameter names, which could inject arbitrary directives into + `postgresql.conf`; key names are now validated by the webhook. + jira: + addresses: #11029 + type: Bug Fix + impact: High + +- relnote: | + Fixed a switchover deadlock when a WAL-archiver plugin was enabled on an + existing cluster: with `primaryUpdateMethod: switchover` the primary could not + be rolled out because a clean demotion needs the archiver sidecar that is + still missing. + details: | + The operator now recreates the primary Pod in place so the sidecar is injected + and archiving resumes. + jira: + addresses: #11032 + type: Bug Fix + impact: High + +- relnote: | + Fixed a cluster staying in `Setting up primary` indefinitely when the + instance-creation Job exhausted its backoff limit; the operator now detects + the terminal Job failure and marks the cluster unrecoverable, naming the + failed Job and pointing to its logs. + jira: + addresses: #11035 + type: Bug Fix + impact: High + +- relnote: | + Fixed a first-primary bootstrap deadlock where a status-patch conflict after + the data PVC was created but before the initialization Job was started left + the orphan Pending PVC counted as an instance, blocking the bootstrap gate; + the PVC-state reconciler now recreates the bootstrap Job reusing the assigned + serial. + jira: + addresses: #11039 + type: Bug Fix + impact: High + +- relnote: | + Fixed external cluster names and secret selector references being joined into + filesystem paths without validation, letting a `..` component or path + separator escape the external secrets directory when the instance manager + dumps connection material; these values are now rejected at the validating + webhook and re-checked at the write site. + details: | + Reported by @r0binak. + jira: + addresses: #11045 + type: Bug Fix + impact: High + +- relnote: | + Fixed `kubectl cnp psql` on Windows, where execution relied on a Unix-only + system call and failed with "not supported by windows"; Windows now launches + `kubectl exec` as a child process. + details: | + Contributed by @Utkarsh-sharma47. + jira: + addresses: #10972 + type: Bug Fix + impact: High + +- relnote: | + Fixed an unbounded memory leak in `kubectl cnp logs -f` on busy clusters, + where a per-log-group timer was never released; timers are now reused across + iterations. + details: | + Contributed by @Anand-240. + jira: + addresses: #10976 + type: Bug Fix + impact: High + diff --git a/product_docs/docs/postgres_for_kubernetes/1/resource_management.mdx b/product_docs/docs/postgres_for_kubernetes/1/resource_management.mdx index 74ef4be2d8..afa3cf0c6f 100644 --- a/product_docs/docs/postgres_for_kubernetes/1/resource_management.mdx +++ b/product_docs/docs/postgres_for_kubernetes/1/resource_management.mdx @@ -114,3 +114,76 @@ For more details on resource management, please refer to the ["Managing Compute Resources for Containers"](https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/) page from the Kubernetes documentation. !!! + +## Integration with the Vertical Pod Autoscaler (VPA) + +The `Cluster` CRD exposes the `scale` subresource together with the label +selector for its instance pods. This makes a `Cluster` a valid `targetRef` for the +[Vertical Pod Autoscaler](https://github.com/kubernetes/autoscaler/tree/master/vertical-pod-autoscaler) +(VPA), so VPA can observe the instance pods and emit CPU and memory +recommendations for them. + +We recommend running VPA in **recommendation-only** mode +(`updatePolicy.updateMode: Off`). In this mode VPA only reports its +recommendations, which an operator can then apply to `spec.resources` of the +`Cluster` through a normal manifest update; {{name.ln}} performs the rolling +update of the instances using its usual switchover-aware procedure. VPA +produces a recommendation per container: use the one for the `postgres` +container, since that is what `spec.resources` configures. + +Example targeting a `Cluster`: + +```yaml +apiVersion: autoscaling.k8s.io/v1 +kind: VerticalPodAutoscaler +metadata: + name: cluster-example-vpa +spec: + targetRef: + apiVersion: postgresql.k8s.enterprisedb.io/v1 + kind: Cluster + name: cluster-example + updatePolicy: + updateMode: "Off" +``` + +!!!warning + +Do not use `updateMode: Auto`, `Recreate`, or `Initial` against a +{{name.ln}}-managed `Cluster`. The operator owns the pod specification and +treats `spec.resources` of the `Cluster` as the source of truth: it does not +adopt the resources VPA writes onto a running pod, so the live pod and the +declared `spec.resources` silently diverge. Any tuning you sized against the +declared resources (for example a `shared_buffers` value the operator +validated against the memory request) no longer matches the pod's actual +limits. VPA also evicts pods through the Kubernetes eviction API, bypassing +the operator's switchover-aware sequencing; the default primary +`PodDisruptionBudget` then blocks eviction of the primary, so VPA stalls +instead of completing. Apply the VPA recommendations to the `Cluster` manifest +manually instead. +!!! + +## Integration with the Horizontal Pod Autoscaler (HPA) + +The `scale` subresource also exposes `spec.instances`, so a +[Horizontal Pod Autoscaler](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/) +(HPA) can technically change the number of instances in a `Cluster`. +In practice this is **not recommended** for a PostgreSQL cluster, for several +reasons. + +Scaling a `Cluster` only adds or removes standby replicas; it never relieves +write load on the primary. The selector exposed through the scale subresource +matches the primary and all replicas, which have opposite workload profiles +(write-heavy primary, read-only replicas), so the per-pod average that HPA +computes from a CPU or memory metric is not a meaningful signal for any of +them. Adding a replica only dilutes that average further without addressing a +hot primary. + +HPA is also unaware of {{name.ln}}' own constraints on `spec.instances`. If +you configure synchronous replicas, a scale-down below `maxSyncReplicas + 1` +instances is rejected by the validating webhook, and HPA keeps retrying a +value it cannot satisfy. +If you nonetheless drive `spec.instances` from an HPA, base it on a custom +metric that actually reflects read replica load, and set `minReplicas` above +the synchronous-replica floor. Review the impact on replication and quorum +carefully first. diff --git a/product_docs/docs/postgres_for_kubernetes/1/samples.mdx b/product_docs/docs/postgres_for_kubernetes/1/samples.mdx index a8a5727ee6..6b58b94f0c 100644 --- a/product_docs/docs/postgres_for_kubernetes/1/samples.mdx +++ b/product_docs/docs/postgres_for_kubernetes/1/samples.mdx @@ -145,6 +145,11 @@ For a list of available options, see [API reference](pg4k.v1.md). Declares a role with the `managed` stanza. Includes password management with Kubernetes secrets. +**Declarative role management with the `DatabaseRole` resource** +: [`role-examples.yaml`](../samples/role-examples.yaml): + Standalone `DatabaseRole` resources targeting an existing cluster, including + password management with a Kubernetes secret. + ## Managed services **Cluster with managed services** diff --git a/product_docs/docs/postgres_for_kubernetes/1/samples/cluster-example-full.yaml b/product_docs/docs/postgres_for_kubernetes/1/samples/cluster-example-full.yaml index 988cd2596e..60f5fbac53 100644 --- a/product_docs/docs/postgres_for_kubernetes/1/samples/cluster-example-full.yaml +++ b/product_docs/docs/postgres_for_kubernetes/1/samples/cluster-example-full.yaml @@ -35,7 +35,7 @@ metadata: name: cluster-example-full spec: description: "Example of cluster" - imageName: docker.enterprisedb.com/k8s/postgresql:18.3-standard-ubi9 + imageName: docker.enterprisedb.com/k8s/postgresql:18.4-standard-ubi9 # imagePullSecret is only required if the images are located in a private registry # imagePullSecrets: # - name: private_registry_access diff --git a/product_docs/docs/postgres_for_kubernetes/1/samples/cluster-example-logical-source.yaml b/product_docs/docs/postgres_for_kubernetes/1/samples/cluster-example-logical-source.yaml index 9f9e355a85..23180b3348 100644 --- a/product_docs/docs/postgres_for_kubernetes/1/samples/cluster-example-logical-source.yaml +++ b/product_docs/docs/postgres_for_kubernetes/1/samples/cluster-example-logical-source.yaml @@ -1,4 +1,15 @@ apiVersion: postgresql.k8s.enterprisedb.io/v1 +kind: DatabaseRole +metadata: + name: cluster-example-app +spec: + cluster: + name: cluster-example + name: app + login: true + replication: true +--- +apiVersion: postgresql.k8s.enterprisedb.io/v1 kind: Cluster metadata: name: cluster-example @@ -29,12 +40,6 @@ spec: highAvailability: synchronizeLogicalDecoding: true - managed: - roles: - - name: app - login: true - replication: true - postgresql: parameters: hot_standby_feedback: 'on' diff --git a/product_docs/docs/postgres_for_kubernetes/1/samples/pooler-example-cluster-image-catalog.yaml b/product_docs/docs/postgres_for_kubernetes/1/samples/pooler-example-cluster-image-catalog.yaml new file mode 100644 index 0000000000..e227904a14 --- /dev/null +++ b/product_docs/docs/postgres_for_kubernetes/1/samples/pooler-example-cluster-image-catalog.yaml @@ -0,0 +1,42 @@ +apiVersion: postgresql.k8s.enterprisedb.io/v1 +kind: ClusterImageCatalog +metadata: + name: cluster-image-catalog-example +spec: + images: + - image: docker.enterprisedb.com/k8s/postgresql:18.4-standard-ubi9 + major: 18 + componentImages: + - key: pgbouncer + image: docker.enterprisedb.com/k8s/pgbouncer:1.25.1-ubi9 +--- +apiVersion: postgresql.k8s.enterprisedb.io/v1 +kind: Cluster +metadata: + name: cluster-example +spec: + instances: 1 + imageCatalogRef: + apiGroup: postgresql.k8s.enterprisedb.io + kind: ClusterImageCatalog + name: cluster-image-catalog-example + major: 18 + storage: + size: 1Gi +--- +apiVersion: postgresql.k8s.enterprisedb.io/v1 +kind: Pooler +metadata: + name: pooler-example-rw +spec: + cluster: + name: cluster-example + instances: 1 + type: rw + pgbouncer: + poolMode: session + imageCatalogRef: + apiGroup: postgresql.k8s.enterprisedb.io + kind: ClusterImageCatalog + name: cluster-image-catalog-example + key: pgbouncer diff --git a/product_docs/docs/postgres_for_kubernetes/1/samples/pooler-example-explicit-image.yaml b/product_docs/docs/postgres_for_kubernetes/1/samples/pooler-example-explicit-image.yaml new file mode 100644 index 0000000000..d85cc5d126 --- /dev/null +++ b/product_docs/docs/postgres_for_kubernetes/1/samples/pooler-example-explicit-image.yaml @@ -0,0 +1,22 @@ +apiVersion: postgresql.k8s.enterprisedb.io/v1 +kind: Cluster +metadata: + name: cluster-example +spec: + instances: 1 + imageName: docker.enterprisedb.com/k8s/postgresql:18.4-standard-ubi9 + storage: + size: 1Gi +--- +apiVersion: postgresql.k8s.enterprisedb.io/v1 +kind: Pooler +metadata: + name: pooler-example-rw +spec: + cluster: + name: cluster-example + instances: 1 + type: rw + pgbouncer: + poolMode: session + image: docker.enterprisedb.com/k8s/pgbouncer:1.25.1-ubi9 diff --git a/product_docs/docs/postgres_for_kubernetes/1/samples/pooler-example-image-catalog.yaml b/product_docs/docs/postgres_for_kubernetes/1/samples/pooler-example-image-catalog.yaml new file mode 100644 index 0000000000..f6d3930dac --- /dev/null +++ b/product_docs/docs/postgres_for_kubernetes/1/samples/pooler-example-image-catalog.yaml @@ -0,0 +1,42 @@ +apiVersion: postgresql.k8s.enterprisedb.io/v1 +kind: ImageCatalog +metadata: + name: image-catalog-example +spec: + images: + - image: docker.enterprisedb.com/k8s/postgresql:18.4-standard-ubi9 + major: 18 + componentImages: + - key: pgbouncer + image: docker.enterprisedb.com/k8s/pgbouncer:1.25.1-ubi9 +--- +apiVersion: postgresql.k8s.enterprisedb.io/v1 +kind: Cluster +metadata: + name: cluster-example +spec: + instances: 1 + imageCatalogRef: + apiGroup: postgresql.k8s.enterprisedb.io + kind: ImageCatalog + name: image-catalog-example + major: 18 + storage: + size: 1Gi +--- +apiVersion: postgresql.k8s.enterprisedb.io/v1 +kind: Pooler +metadata: + name: pooler-example-rw +spec: + cluster: + name: cluster-example + instances: 1 + type: rw + pgbouncer: + poolMode: session + imageCatalogRef: + apiGroup: postgresql.k8s.enterprisedb.io + kind: ImageCatalog + name: image-catalog-example + key: pgbouncer diff --git a/product_docs/docs/postgres_for_kubernetes/1/samples/postgis-example.yaml b/product_docs/docs/postgres_for_kubernetes/1/samples/postgis-example.yaml index 99491f8322..21ce41aec0 100644 --- a/product_docs/docs/postgres_for_kubernetes/1/samples/postgis-example.yaml +++ b/product_docs/docs/postgres_for_kubernetes/1/samples/postgis-example.yaml @@ -3,7 +3,7 @@ kind: Cluster metadata: name: postgis-example spec: - imageName: docker.enterprisedb.com/k8s_enterprise/postgresql:18.3-minimal-ubi9 + imageName: docker.enterprisedb.com/k8s/postgresql:18.4-minimal-ubi9 instances: 1 storage: diff --git a/product_docs/docs/postgres_for_kubernetes/1/samples/role-examples.yaml b/product_docs/docs/postgres_for_kubernetes/1/samples/role-examples.yaml new file mode 100644 index 0000000000..17e137c024 --- /dev/null +++ b/product_docs/docs/postgres_for_kubernetes/1/samples/role-examples.yaml @@ -0,0 +1,46 @@ +apiVersion: postgresql.k8s.enterprisedb.io/v1 +kind: DatabaseRole +metadata: + name: cluster-example-reporting +spec: + cluster: + name: cluster-example + name: reporting + login: true +--- +apiVersion: postgresql.k8s.enterprisedb.io/v1 +kind: DatabaseRole +metadata: + name: role-dante +spec: + cluster: + name: cluster-example + name: dante + comment: my database-side comment + login: true + superuser: false + createdb: true + createrole: false + inherit: false + clientCertificate: + enabled: true + replication: false + bypassrls: false + connectionLimit: 4 + validUntil: "2053-04-12T15:04:05Z" + inRoles: + - pg_monitor + - pg_signal_backend + passwordSecret: + name: cluster-example-dante +--- +apiVersion: v1 +data: + username: ZGFudGU= + password: ZGFudGU= +kind: Secret +metadata: + name: cluster-example-dante + labels: + k8s.enterprisedb.io/reload: "true" +type: kubernetes.io/basic-auth diff --git a/product_docs/docs/postgres_for_kubernetes/1/scheduling.mdx b/product_docs/docs/postgres_for_kubernetes/1/scheduling.mdx index 30af886cee..c746900f66 100644 --- a/product_docs/docs/postgres_for_kubernetes/1/scheduling.mdx +++ b/product_docs/docs/postgres_for_kubernetes/1/scheduling.mdx @@ -46,7 +46,7 @@ metadata: name: cluster-example spec: instances: 3 - imageName: docker.enterprisedb.com/k8s/postgresql:18.3-standard-ubi9 + imageName: docker.enterprisedb.com/k8s/postgresql:18.4-standard-ubi9 affinity: enablePodAntiAffinity: true # Default value diff --git a/product_docs/docs/postgres_for_kubernetes/1/ssl_connections.mdx b/product_docs/docs/postgres_for_kubernetes/1/ssl_connections.mdx index 7db15e04a8..e569bff942 100644 --- a/product_docs/docs/postgres_for_kubernetes/1/ssl_connections.mdx +++ b/product_docs/docs/postgres_for_kubernetes/1/ssl_connections.mdx @@ -180,7 +180,7 @@ Output: version -------------------------------------------------------------------------------------- ------------------ -PostgreSQL 18.3 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 8.3.1 20191121 (Red Hat +PostgreSQL 18.4 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 8.3.1 20191121 (Red Hat 8.3.1-5), 64-bit (1 row) ``` diff --git a/product_docs/docs/postgres_for_kubernetes/1/storage.mdx b/product_docs/docs/postgres_for_kubernetes/1/storage.mdx index 050fa804d5..1b365d3ad3 100644 --- a/product_docs/docs/postgres_for_kubernetes/1/storage.mdx +++ b/product_docs/docs/postgres_for_kubernetes/1/storage.mdx @@ -339,10 +339,76 @@ $ kubectl get pods NAME READY STATUS RESTARTS AGE cluster-example-1 1/1 Running 0 5m58s cluster-example-2 1/1 Running 0 5m43s -cluster-example-4-join-v2 0/1 Completed 0 17s -cluster-example-4 1/1 Running 0 10s +cluster-example-3-join-v2 0/1 Completed 0 17s +cluster-example-3 1/1 Running 0 10s ``` +## Volume reduction + +Kubernetes does not provide an API to shrink a PVC, and {{name.ln}}' +validating webhook rejects any attempt to decrease `.spec.storage.size`, +`.spec.walStorage.size` or any tablespace storage size in `.spec.tablespaces`. +You can still reduce the storage of a cluster, but only by recreating +each instance with a smaller volume, as described below. + +!!!warning + +{{name.ln}} does not support automated volume shrinking, as it is a +delicate operation that can lead to data loss if performed incorrectly. For +the time being, it can only be achieved manually, through the supervised +procedure described below. +This procedure requires you to temporarily disable the validating webhook. +While validation is disabled, the operator accepts spec changes that would +normally be rejected, including unsafe or destructive ones. Proceed with +caution and at your own risk, and re-enable validation as soon as possible. + +Before you start, make sure the cluster's current data, WAL, and any tablespace +data comfortably fit within the new, smaller sizes. If they don't, the instances +recreated on smaller volumes can fail to rejoin or quickly run out of space. +!!! + +To reduce the size of the persistent volumes: + +1. Disable the validating webhook by setting the `k8s.enterprisedb.io/validation: disabled` + annotation on the `Cluster`, set `.spec.storage.size` (and, if present, + `.spec.walStorage.size` or tablespace storage size in `.spec.tablespaces`) + to the new, smaller value, and increase `.spec.instances` by 1 to provide a + spare instance during the rollout. + +2. Re-enable validation by removing the `k8s.enterprisedb.io/validation` annotation (or + setting it to `enabled`). The new, smaller size is now stored in the spec + and is applied to every instance the operator recreates from this point on. + Existing instances keep their current volumes; for each one, the operator + logs an informational `cannot decrease storage requirement` message until + that instance is recreated. This is expected and harmless. + +3. Destroy one standby that still has a volume of the old size. The operator + provisions a replacement instance — reusing the name of the one you + destroyed, since instance serials are recycled — on the new, smaller volume: + + ```sh + kubectl-cnp destroy CLUSTER INSTANCE + ``` + +4. Wait for the operator to create the replacement instance and for it to + become healthy. + +5. Repeat steps 3 and 4 for every remaining standby that still has an + old-size volume. + +6. Promote one of the newly created standbys so that the current primary — + which still has an old-size volume — is demoted to a standby: + + ```sh + kubectl-cnp promote CLUSTER INSTANCE + ``` + +7. Destroy the former primary (now a standby with an old-size volume) so the + operator provisions its replacement on the new, smaller volume, and wait + until all instances are healthy. + +8. Decrease `.spec.instances` back to its original value. + ## Static provisioning of persistent volumes {{name.ln}} was designed to work with dynamic volume provisioning. This diff --git a/product_docs/docs/postgres_for_kubernetes/1/troubleshooting.mdx b/product_docs/docs/postgres_for_kubernetes/1/troubleshooting.mdx index 836febe699..f1368e32c7 100644 --- a/product_docs/docs/postgres_for_kubernetes/1/troubleshooting.mdx +++ b/product_docs/docs/postgres_for_kubernetes/1/troubleshooting.mdx @@ -221,7 +221,7 @@ Cluster in healthy state Name: cluster-example Namespace: default System ID: 7044925089871458324 -PostgreSQL Image: docker.enterprisedb.com/k8s/postgresql:18.3-standard-ubi9 +PostgreSQL Image: docker.enterprisedb.com/k8s/postgresql:18.4-standard-ubi9 Primary instance: cluster-example-1 Instances: 3 Ready instances: 3 @@ -290,7 +290,7 @@ kubectl describe cluster -n | grep "Image Name" Output: ```shell - Image Name: docker.enterprisedb.com/k8s/postgresql:18.3-standard-ubi9 + Image Name: docker.enterprisedb.com/k8s/postgresql:18.4-standard-ubi9 ``` !!!note