Skip to content
Open
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
4 changes: 2 additions & 2 deletions product_docs/docs/postgres_for_kubernetes/1/backup.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,8 @@ This use case can also be extended to [replica clusters](replica_cluster.md),
as they can simply rely on the WAL archive to synchronize across long
distances, extending disaster recovery goals across different regions.

When you [configure a WAL archive](wal_archiving.md), {{name.ln}} provides
out-of-the-box an [RPO](before_you_start.md#rpo) <= 5 minutes for disaster
When you [configure a WAL archive](wal_archiving.md), EDB Postgres for Kubernetes provides
out-of-the-box an [RPO](before_you_start.md#rpo) 5 minutes for disaster
recovery, even across regions.

!!! Important
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
title: 'Before You Start'
title: 'Before you start'
originalFilePath: 'src/before_you_start.md'
---

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -661,7 +661,7 @@ spec:
```

All the requirements must be met for the clone operation to work, including
the same PostgreSQL version (in our case 18.0).
the same PostgreSQL version (in our case 18.1).

#### TLS certificate authentication

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
title: 'Instance pod configuration'
title: 'Instance Pod configuration'
originalFilePath: 'src/cluster_conf.md'
---

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ the [official External Secrets documentation](https://external-secrets.io/latest
## Integration with PostgreSQL and {{name.ln}}

When it comes to PostgreSQL databases, External Secrets integrates seamlessly
with {{name.ln}} in two major use cases:
with EDB Postgres for Kubernetes in two major use cases:

- **Automated password management:** ESO can handle the automatic generation
and rotation of database user passwords stored in Kubernetes `Secret`
Expand Down
28 changes: 27 additions & 1 deletion product_docs/docs/postgres_for_kubernetes/1/cnp_i.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ originalFilePath: 'src/cnp_i.md'


The **CloudNativePG Interface** ([CNPG-I](https://github.com/cloudnative-pg/cnpg-i))
is a standard way to extend and customize {{name.ln}} without modifying its
is a standard way to extend and customize EDB Postgres for Kubernetes without modifying its
core codebase.

## Why CNP-I?
Expand Down Expand Up @@ -166,6 +166,32 @@ spec:
You can provide your own certificate bundles, but the recommended method is
to use [Cert-manager](https://cert-manager.io).

#### Customizing the Certificate DNS Name

By default, EDB Postgres for Kubernetes uses the Service name as the server name for TLS
verification when connecting to the plugin. If your environment requires the
certificate to have a different DNS name (e.g., `barman-cloud.svc`), you can
customize it using the `k8s.enterprisedb.io/pluginServerName` annotation:

```yaml
apiVersion: v1
kind: Service
metadata:
annotations:
k8s.enterprisedb.io/pluginClientSecret: cnpg-i-plugin-example-client-tls
k8s.enterprisedb.io/pluginServerSecret: cnpg-i-plugin-example-server-tls
k8s.enterprisedb.io/pluginPort: "9090"
k8s.enterprisedb.io/pluginServerName: barman-cloud.svc
name: barman-cloud
namespace: postgresql-operator-system
spec:
[...]
```

This allows the operator to verify the plugin's certificate against the
specified DNS name instead of the default Service name. The server certificate
must include this DNS name in its Subject Alternative Names (SAN).

## Using a plugin

To enable a plugin, configure the `.spec.plugins` section in your `Cluster`
Expand Down
136 changes: 80 additions & 56 deletions product_docs/docs/postgres_for_kubernetes/1/connection_pooling.mdx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
title: 'Connection pooling'
title: 'Connection Pooling'
originalFilePath: 'src/connection_pooling.md'
---

Expand All @@ -14,6 +14,10 @@ between your applications and a PostgreSQL service, for example, the `rw`
service. It creates a separate, scalable, configurable, and highly available
database access layer.

!!! Warning
EDB Postgres for Kubernetes requires the `auth_dbname` feature in PgBouncer.
Make sure to use a PgBouncer container image version **1.19 or higher**.

## Architecture

The following diagram highlights how introducing a database access layer based
Expand Down Expand Up @@ -51,7 +55,7 @@ spec:
!!! Important
The pooler name can't be the same as any cluster name in the same namespace.

This example creates a `Pooler` resource called `pooler-example-rw`
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
service (`rw`, therefore `cluster-example-rw`).
Expand All @@ -78,118 +82,138 @@ the configuration files used with PgBouncer.

## Pooler resource lifecycle

`Pooler` resources aren't cluster-managed resources. You create poolers
manually when they're needed. You can also deploy multiple poolers per
`Pooler` resources are not managed automatically by the operator. You create
them manually when needed, and you can deploy multiple poolers for the same
PostgreSQL cluster.

What's important is that the life cycles of the `Cluster` and the `Pooler`
resources are currently independent. Deleting the cluster doesn't imply the
deletion of the pooler, and vice versa.
The key point to understand is that the lifecycles of the `Cluster` and
`Pooler` resources are independent. Deleting a cluster does not automatically
remove its poolers, and deleting a pooler does not affect the cluster.

!!! Important
Once you know how a pooler works, you have full freedom in terms of
possible architectures. You can have clusters without poolers, clusters with
a single pooler, or clusters with several poolers, that is, one per application.
!!! Info
Once you are familiar with how poolers work, you have complete flexibility
in designing your architecture. You can run clusters without poolers, clusters
with a single pooler, or clusters with multiple poolers (for example, one per
application).

!!! Important
When the operator is upgraded, the pooler pods will undergo a rolling
upgrade. This is necessary to ensure that the instance manager within the
pooler pods is also upgraded.
When the operator itself is upgraded, pooler pods will also undergo a
rolling upgrade. This ensures that the instance manager inside the pooler
pods is upgraded consistently.

## Security

Any PgBouncer pooler is transparently integrated with {{name.ln}} support for
in-transit encryption by way of TLS connections, both on the client
(application) and server (PostgreSQL) side of the pool.

Specifically, PgBouncer reuses the certificates of the PostgreSQL server. It
also uses TLS client certificate authentication to connect to the PostgreSQL
server to run the `auth_query` for clients' password authentication (see
[Authentication](#authentication)).

Containers run as the pgbouncer system user, and access to the `pgbouncer`
database is allowed only by way of local connections, through peer authentication.
Containers run as the `pgbouncer` system user, and access to the `pgbouncer`
administration database is allowed only by way of local connections, through
peer authentication.

### Certificates

By default, a PgBouncer pooler uses the same certificates that are used by the
cluster. However, if you provide those certificates, the pooler accepts secrets
with the following formats:
By default, a PgBouncer pooler reuses the same certificates as the PostgreSQL
cluster. It relies on TLS client certificate authentication to connect to the
PostgreSQL server and run the `auth_query` used for client password
authentication (see ["Authentication"](#authentication)).

Supplying your own secrets disables the built-in integration. From that point,
you gain complete control (and responsibility) for managing authentication.
Supported secret formats are:

1. Basic Auth
2. TLS
3. Opaque

In the Opaque case, it looks for the following specific keys that need to be used:
For Opaque secrets, the `Pooler` resource expects the following keys:

- tls.crt
- tls.key
- `tls.crt`
- `tls.key`

So you can treat this secret as a TLS secret, and start from there.
In practice, this means you can treat an Opaque secret as a TLS secret,
starting from the same structure.

## Authentication

Password-based authentication is the only supported method for clients of
PgBouncer in {{name.ln}}.
### Default authentication method

By default, EDB Postgres for Kubernetes natively supports password-based authentication for
PgBouncer clients connecting to the PostgreSQL database.

Internally, the implementation relies on PgBouncer's `auth_user` and
`auth_query` options. Specifically, the operator:
This built-in mechanism leverages PgBouncer’s `auth_dbname` (introduced in
version 1.19), together with the `auth_user` and `auth_query` options.

!!! Important
If you provide your own certificate secrets, the built-in integration is
disabled. In that case, you are fully responsible for configuring and
managing PgBouncer authentication.

- Creates a standard user called `cnp_pooler_pgbouncer` in the PostgreSQL server
The built-in integration performs the following tasks:

- Creates a dedicated user called `cnp_pooler_pgbouncer` in the PostgreSQL
server
- Creates the lookup function in the `postgres` database and grants execution
privileges to the cnp_pooler_pgbouncer user (PoLA)
privileges to `cnp_pooler_pgbouncer` (following PoLA principles)
- Issues a TLS certificate for this user
- Sets `cnp_pooler_pgbouncer` as the `auth_user`
- Configures PgBouncer to use the TLS certificate to authenticate
`cnp_pooler_pgbouncer` against the PostgreSQL server
- Removes all the above when it detects that a cluster doesn't have
any pooler associated to it
- Configures PgBouncer to use `cnp_pooler_pgbouncer` as the `auth_user` and
`postgres` as the `auth_dbname`
- Configures PgBouncer to authenticate `cnp_pooler_pgbouncer` against
PostgreSQL using the issued TLS certificate
- Cleans up all of the above automatically when no poolers are associated with
the cluster

!!! Important
If you specify your own secrets, the operator doesn't automatically
integrate the pooler.
#### SQL instructions

To manually integrate the pooler, if you specified your own
secrets, you must run the following queries from inside your cluster.
As part of the built-in integration, EDB Postgres for Kubernetes automatically executes a set
of SQL statements during reconciliation. These statements are run by the
instance manager using the `postgres` user against the `postgres` database.

First, you must create the role:
Role creation:

```sql
CREATE ROLE cnp_pooler_pgbouncer WITH LOGIN;
```

Then, for each application database, grant the permission for
`cnp_pooler_pgbouncer` to connect to it:
Grant access to the `postgres` database:

```sql
GRANT CONNECT ON DATABASE { database name here } TO cnp_pooler_pgbouncer;
GRANT CONNECT ON DATABASE postgres TO cnp_pooler_pgbouncer;
```

Finally, as a *superuser* connect in each application database, and then create
the authentication function inside each of the application databases:
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:

```sql
CREATE OR REPLACE FUNCTION public.user_search(uname TEXT)
RETURNS TABLE (usename name, passwd text)
LANGUAGE sql SECURITY DEFINER AS
'SELECT usename, passwd FROM pg_catalog.pg_shadow WHERE usename=$1;';
```

Restrict and grant permissions on the lookup function:

```sql
REVOKE ALL ON FUNCTION public.user_search(text)
FROM public;

GRANT EXECUTE ON FUNCTION public.user_search(text)
TO cnp_pooler_pgbouncer;
```

!!! Important
Given that `user_search` is a `SECURITY DEFINER` function, you need to
create it through a role with `SUPERUSER` privileges, such as the `postgres`
user.
### Custom authentication method

Providing your own certificate secrets disables the built-in integration.

This gives you the flexibility — and responsibility — to manage the
authentication process yourself. You can follow the instructions above to
replicate similar behavior to the default setup.

## Pod templates

You can take advantage of pod templates specification in the `template`
section of a `Pooler` resource. For details, see
section of a `Pooler` resource. For details, see
[`PoolerSpec`](pg4k.v1.md#postgresql-k8s-enterprisedb-io-v1-PoolerSpec) in the API reference.

Using templates, you can configure pods as you like, including fine control
Expand Down Expand Up @@ -320,7 +344,7 @@ replicas).
If your infrastructure spans multiple availability zones with high latency
across them, be aware of network hops. Consider, for example, the case of your
application running in zone 2, connecting to PgBouncer running in zone 3, and
pointing to the PostgreSQL primary in zone 1.
pointing to the PostgreSQL primary in zone 1.

## PgBouncer configuration options

Expand Down
Loading