Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions product_docs/docs/postgres_for_kubernetes/1/backup.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ two main ways:
- **Natively**, with support for:

- [Object storage via Barman Cloud](backup_barmanobjectstore.md)
*(although deprecated from 1.26 in favor of the Barman Cloud Plugin)*
*(deprecated from 1.26 in favor of the Barman Cloud Plugin; 1.31 is the
last minor release with native support, which is removed starting from
1.32.0)*
- [Kubernetes Volume Snapshots](backup_volumesnapshot.md), if
supported by the underlying storage class

Expand Down Expand Up @@ -126,6 +128,7 @@ for your disaster recovery plans.
- **Object store–based backups**, via the [**Barman Cloud
Plugin**](https://cloudnative-pg.io/plugin-barman-cloud/) or the
[**deprecated native integration**](backup_barmanobjectstore.md)
(removed starting from 1.32.0)
- [**Volume Snapshots**](backup_volumesnapshot.md), using the
Kubernetes CSI interface and supported storage classes

Expand Down Expand Up @@ -386,7 +389,18 @@ and on-demand backups:
- `barmanObjectStore` – Uses [Barman Cloud for object storage](backup_barmanobjectstore.md)
*(deprecated starting with v1.26 in favor of the
[Barman Cloud Plugin](https://cloudnative-pg.io/plugin-barman-cloud/),
but still the default for backward compatibility)*
but still the default for backward compatibility; 1.31 is the last minor
release with native support, which is removed starting from 1.32.0)*

!!!warning

Native Barman Cloud support, including the `barmanObjectStore` backup
method and the `.spec.backup.barmanObjectStore` stanza, is removed starting
from {{name.ln}} 1.32.0. Releases up to and including 1.31, and their
patch releases, keep native support for as long as they are supported.
Follow [Migrating from Built-in {{name.ln}} Backup](https://cloudnative-pg.io/plugin-barman-cloud/docs/migration/)
to move to the Barman Cloud Plugin before upgrading to 1.32 or later.
!!!

Specify the method using the `.spec.method` field (defaults to
`barmanObjectStore`).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,12 @@ originalFilePath: 'src/appendixes/backup_barmanobjectstore.md'
!!!warning
As of {{name.ln}} 1.26, **native Barman Cloud support is deprecated** in
favor of the **Barman Cloud Plugin**. This page has been moved to the appendix
for reference purposes. While the native integration remains functional for
now, we strongly recommend beginning a gradual migration to the plugin-based
interface after appropriate testing. For guidance, see
for reference purposes. **{{name.ln}} 1.31 is the last minor release that
ships with native Barman Cloud support, which is removed starting from
1.32.0.** Releases up to and including 1.31, and their patch releases, keep
native support for as long as they are supported. You must migrate to the
plugin before upgrading to 1.32 or later. We strongly recommend migrating to
the plugin-based interface after appropriate testing. For guidance, see
[Migrating from Built-in {{name.ln}} Backup](https://cloudnative-pg.io/plugin-barman-cloud/docs/migration/).
!!!

Expand Down
113 changes: 111 additions & 2 deletions product_docs/docs/postgres_for_kubernetes/1/bootstrap.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -553,7 +553,10 @@ the operation has been
thoroughly tested. The {{name.ln}} community does not endorse this approach
for such use cases, and recommends using logical import instead. It is
exceedingly rare that all requirements for physical replication are met in a
way that seamlessly works with {{name.ln}}.
way that seamlessly works with {{name.ln}}. If you still need to go down
this path, we strongly recommend relying on one of the
[professional support companies](https://cloudnative-pg.io/support/)
listed on the {{name.ln}} website.
!!!

!!!warning
Expand Down Expand Up @@ -591,7 +594,10 @@ The following requirements apply to the `pg_basebackup` bootstrap method:

- target and source must have the same hardware architecture
- target and source must have the same major PostgreSQL version
- target and source must have the same tablespaces
- target and source must have the same tablespaces (same names), with the
locations in the source mapped through `tablespaceMapping` when they differ
from the {{name.ln}} ones (see
[Mapping tablespaces from the source](#mapping-tablespaces-from-the-source))
- source must be configured with enough `max_wal_senders` to grant
access from the target for this one-off operation by providing at least
one *walsender* for the backup plus one for WAL streaming
Expand Down Expand Up @@ -798,6 +804,109 @@ completed**:
password for the application user (the `app` user in this case) will be
updated to the `password` value in the secret.

#### Passing additional options to `pg_basebackup`

This is an advanced option. You can append custom options to the
`pg_basebackup` command built by the operator with
`.spec.bootstrap.pg_basebackup.additionalArgs`, for example to reduce the
impact on the source server or to speed up the copy of a very large data
directory:

```yaml
spec:
bootstrap:
pg_basebackup:
source: cluster-example
additionalArgs:
- --max-rate=50M
- --checkpoint=fast
- --sync-method=syncfs
```

In this example:

- `--max-rate=50M` limits the transfer rate, reducing the load on the source
- `--checkpoint=fast` avoids waiting for a spread checkpoint on the source
- `--sync-method=syncfs` avoids a slow per-file `fsync` phase at the end of the
copy (PostgreSQL 17 and later only)

!!!warning

The operator rejects the options it relies on: the target directory and output
format (`-D`/`--pgdata`, `-F`/`--format`, `-R`/`--write-recovery-conf`,
`-X`/`--wal-method`, `--waldir`, `-t`/`--target`), the connection parameters
(`-d`/`--dbname`, `-h`/`--host`, `-p`/`--port`, `-U`/`--username`,
`-w`/`--no-password`, `-W`/`--password`, taken from `externalClusters`), the
tablespace relocation (`-T`/`--tablespace-mapping`), the creation of a
permanent replication slot on the source (`-C`/`--create-slot`), which the new
cluster would never use, and `--help` and `--version`. Abbreviated long options
that match one of them are rejected too.

All the other options are passed as they are, and some of them may still
interfere with the operator. You are responsible for the arguments and for
their compatibility with the PostgreSQL version in use. The project does not
test combinations of `pg_basebackup` options.
!!!

This setting only applies to the bootstrap of the cluster. It does not affect
the `pg_basebackup` executions used to join new replicas.

#### Mapping tablespaces from the source

If the source instance uses tablespaces, declare each of them in
`spec.tablespaces`, using the same name it has in the source instance.
`pg_basebackup` relocates tablespaces by path and not by name, so if the source
does not already use the {{name.ln}} location for a tablespace, map it with
`tablespaceMapping`, which associates the name of the tablespace with its
location in the source instance:

```yaml
spec:
tablespaces:
- name: data_ts
storage:
size: 1Gi
bootstrap:
pg_basebackup:
source: external-postgres
tablespaceMapping:
- name: data_ts
sourceLocation: /data/pg/data_ts
```

!!!warning

Use `tablespaceMapping` with caution, as it is meant for sources that are not
managed by {{name.ln}}, such as an instance running outside Kubernetes. As
explained in the [introduction of this method](#bootstrap-from-a-live-cluster-pg_basebackup),
the {{name.ln}} community does not endorse that kind of migration, and
recommends logical import instead. If you still need it, we strongly
recommend relying on one of the
[professional support companies](https://cloudnative-pg.io/support/)
listed on the {{name.ln}} website. The operator does not validate that the
resulting tablespace layout will work correctly.
!!!

!!!warning

The operator does not check which tablespaces the source instance has. Make
sure that every tablespace of the source instance is declared in
`spec.tablespaces`, and mapped through `tablespaceMapping` unless the source
already uses the {{name.ln}} location. A tablespace that is not mapped is
restored under the path it has in the source instance, inside the Pod. If that
path is not writable, the bootstrap fails. If it is, the data ends up in an
unexpected location.
!!!

!!!warning

Do not run `CREATE TABLESPACE` on the source from the start of the base backup
until the target stops following the source. For a standalone cluster, that is
the end of the cloning operation; for a replica cluster, it is the promotion of
the cluster. WAL replay carries the source path unmodified, so replaying such a
record fails on the target.
!!!

#### Current limitations

##### Snapshot copy
Expand Down
11 changes: 11 additions & 0 deletions product_docs/docs/postgres_for_kubernetes/1/cluster_conf.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,17 @@ the `.spec.ephemeralVolumesSizeLimit.shm` field in the cluster spec.
Use this field only in case of
[PostgreSQL running with `posix` shared memory dynamic allocation](postgresql_conf.md#dynamic-shared-memory-settings).

## ServiceAccount token mount

The `automountServiceAccountToken` field of the cluster specification
controls the automatic mount of the `ServiceAccount` token in the instance
Pods and in the Jobs run by the operator. Setting it to `false` helps comply
with admission policies enforced in hardened environments; the operator then
mounts an equivalent projected volume so that the instance manager can keep
working. See
["Disabling the automatic mount of the ServiceAccount token"](security.md#disabling-the-automatic-mount-of-the-serviceaccount-token)
for the details.

## Environment variables

!!!important
Expand Down
72 changes: 37 additions & 35 deletions product_docs/docs/postgres_for_kubernetes/1/failover.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -87,35 +87,29 @@ 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
manager itself unreachable), the replica can promote once the lease has been
unchanged for `leaseDurationSeconds` since the operator named it the target
primary. 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 lease alone does not stop a primary that has lost connectivity to the
Kubernetes API server but is still running. Stopping it is the job of the
[primary isolation](instance_manager.md#primary-isolation) check, which watches
how long the lease has gone without a successful renewal.
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 reports an isolated primary as unhealthy, which
the kubelet then restarts through its normal container-termination
path. That path is a *smart* shutdown: it refuses new connections
but lets sessions that are already open keep committing until
`.spec.smartShutdownTimeout` elapses (180 seconds by default), so
it narrows the write window during a partition rather than closing
it outright.
- The isolation check stops an *isolated* primary from continuing to
accept writes, by shutting PostgreSQL down immediately.

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. If that write window matters
for your workload, set `.spec.smartShutdownTimeout: 0` so the
restart goes straight to a fast shutdown instead of waiting out the
full window.
server but remains otherwise healthy.

### Inspecting the primary lease

Expand Down Expand Up @@ -147,12 +141,12 @@ 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. |
| Field | Default | Description |
| ------------------------------ | ------- | ------------------------------------------------------------------------- |
| `leaseDurationSeconds` | `15` | How long the target primary waits on an unchanged lease before taking 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:
Expand All @@ -176,13 +170,21 @@ admission webhook: `leaseDurationSeconds` must be greater than
underlying Kubernetes leader election.
!!!

!!!warning

These timings also set how fast an isolated primary stops. See
[Primary Isolation](instance_manager.md#primary-isolation) for the margin to
keep between them and the isolation check `requestTimeout`.
!!!

!!!note

`leaseDurationSeconds` and `retryPeriodSeconds` govern two different timings.
After an abrupt primary loss (the previous primary did not release the lease), a
After an abrupt primary loss (the previous primary did not release the lease), the
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
before it may take over, counted from the moment it becomes the target primary:
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
Expand Down Expand Up @@ -284,17 +286,17 @@ mechanism, driven by `tolerationSeconds` on the
`node.kubernetes.io/unreachable` `NoExecute` taint (`300s` by default). That
timer does not hold up the operator's failover decision; {{name.ln}}
promotes a new primary as soon as the `Ready` condition flips. By that point
the kubelet on the isolated node has already noticed the problem: with the
PostgreSQL on the isolated node has already been stopped locally: with the
default `.spec.probes.liveness.isolationCheck.enabled: true`, the instance
manager fails its own liveness probe once it can reach neither the API
server nor the rest of the cluster, and the kubelet restarts the container
within approximately three probe periods (`~30s`). That restart goes
through the normal termination path, a smart shutdown that lets sessions
already open on the isolated primary keep committing until
`.spec.smartShutdownTimeout` elapses (180 seconds by default) on top of
that ~30s detection window. Full high availability (recreation of the old
primary on a healthy node by the operator) is still gated on the
taint-based eviction actually deleting the pod.
manager requests an immediate PostgreSQL shutdown once its last successful lease
renewal is older than the renew deadline and either at least one other instance
is unreachable or a reachable one names a different target primary, within the
timings described under [Primary Isolation](instance_manager.md#primary-isolation).
When PostgreSQL stops, the instance manager exits and the kubelet restarts the
container, so the step-down shows up as a container restart, not as a liveness
probe failure. Full high availability (recreation of the old primary on
a healthy node by the operator) is still gated on the taint-based eviction
actually deleting the pod.

## Failover Quorum (Quorum-based Failover)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,15 @@ By default, {{name.ln}} automatically manages the relevant GUCs by setting:
PostgreSQL to locate any extension control file within `/extensions/<EXTENSION_NAME>/share/extension`
- `dynamic_library_path` to `/extensions/<EXTENSION_NAME>/lib`

A directory is added to these GUCs only if it exists in the mounted extension
image. This is the case, for example, of a module that ships only a `lib`
directory and no `share` one: it contributes to `dynamic_library_path` but
leaves `extension_control_path` untouched, instead of adding an entry that
points to a missing directory. The same rule applies to the custom paths
described in [Setting Custom Paths](#setting-custom-paths). The instance
manager performs this check every time it generates the PostgreSQL
configuration.

!!!note
Extension names containing underscores (e.g., `pg_ivm`) are converted to use
hyphens (e.g., `pg-ivm`) for Kubernetes volume names to comply with RFC 1123
Expand Down Expand Up @@ -406,6 +415,12 @@ following fields:
- `env`: A list of `name` and `value` pairs to be set as environment variables within
the Postgres process.

Entries of `extension_control_path` and `dynamic_library_path` that do not
exist in the extension image are skipped, as described in
[Mounting and PostgreSQL Configuration](#mounting-and-postgresql-configuration).
Entries of `ld_library_path` and `bin_path` are added as declared, without any
existence check.

This flexibility enables you to support complex or non-standard extension
images while maintaining clarity and predictability.

Expand Down Expand Up @@ -439,6 +454,15 @@ spec:
- `/extensions/my-extension/my/share/path` appended to `extension_control_path`
- `/extensions/my-extension/my/lib/path` appended to `dynamic_library_path`

!!!note

As with the default directories, a custom path that does not exist in the image
is skipped without raising an error. A typo in a custom path therefore shows up
as a missing entry in the GUC, not as a failure. To verify what was applied,
run `SHOW extension_control_path;` or `SHOW dynamic_library_path;`. Skipped
paths are also logged by the instance manager at `debug` level.
!!!

This allows PostgreSQL to discover your extension’s control files and shared
libraries correctly, even with a non-standard layout.

Expand Down
Loading