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
23 changes: 23 additions & 0 deletions docs/guides/postgres/concepts/catalog.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,29 @@ The default value of this field is `false`. If `spec.deprecated` is set `true`,

`spec.podSecurityPolicies.databasePolicyName` is a required field that specifies the name of the pod security policy required to get the database server pod(s) running.

### spec.tde

`spec.tde` is an optional field that marks whether this version supports
Transparent Data Encryption via Percona's `pg_tde` extension. It is only set on
Percona distribution builds, because the `tde_heap` access method ships only
with Percona Server for PostgreSQL. It has the following fields:

- `spec.tde.supported` is a boolean that gates the `spec.tde` section of the
[Postgres](/docs/guides/postgres/concepts/postgres.md) CRD. A Postgres object
that sets `spec.tde` must reference a version whose `spec.tde.supported` is
`true`, otherwise the admission webhook rejects it.
- `spec.tde.extensionName` is the name of the encryption extension the operator
loads through `shared_preload_libraries` and creates in the database, normally
`pg_tde`.

```yaml
spec:
distribution: Percona
tde:
supported: true
extensionName: pg_tde
```

```bash
helm upgrade -i kubedb oci://ghcr.io/appscode-charts/kubedb \
--namespace kubedb --create-namespace \
Expand Down
30 changes: 30 additions & 0 deletions docs/guides/postgres/concepts/opsrequest.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,8 @@ A `PostgresOpsRequest` object has the following fields in the `spec` section.
- `Restart`
- `Reconfigure`
- `ReconfigureTLS`
- `RotatePrincipalKey`
- `EnableWALEncryption`

>You can perform only one type of operation on a single `PostgresOpsRequest` CR. For example, if you want to update your database and scale up its replica then you have to create two separate `PostgresOpsRequest`. At first, you have to create a `PostgresOpsRequest` for updating. Once it is completed, then you can create another `PostgresOpsRequest` for scaling. You should not create two `PostgresOpsRequest` simultaneously.

Expand Down Expand Up @@ -172,6 +174,34 @@ Here, when you specify the resource request for `Postgres` container, the schedu

>You can increase/decrease resources for both `postgres` container and `exporter` container on a single `PostgresOpsRequest` CR.

#### spec.rotatePrincipalKey

`spec.rotatePrincipalKey` is used with the `RotatePrincipalKey` type to rotate the
[TDE](/docs/guides/postgres/tde/overview/index.md) principal key. The principal
key wraps the per-relation internal keys, so rotating it re-wraps those keys
online, without rewriting data and without a restart. This field consists of the
Comment thread
coderabbitai[bot] marked this conversation as resolved.
following optional sub-field:

- `spec.rotatePrincipalKey.keyName` pins the name of the new principal key in the
key provider. If left empty, the operator generates one.

Requires `spec.tde` to be configured on the referenced Postgres.

#### spec.enableWALEncryption

`spec.enableWALEncryption` is used with the `EnableWALEncryption` type to turn on
WAL (write-ahead log) encryption for a TDE-enabled cluster. The operator sets the
server key, flips `spec.tde.encryptWAL` on the Postgres object, and performs a
rolling restart so every node reloads with `pg_tde.wal_encrypt=on`.
`spec.tde.encryptWAL` is mutable, but this OpsRequest is the supported way to
change it: patching the field directly skips the server-key setup and rolling
restart, so replicas would not agree on WAL encryption state. WAL encryption
requires a global (`vault` or `kmip`) key provider. This field consists of the
following optional sub-field:

- `spec.enableWALEncryption.keyName` pins the name of the WAL server key in the
key provider. If left empty, the operator generates one.

#### spec.timeout

Timeout for each step of the ops request in second. If a step doesn't finish within the specified timeout, the ops request will result in failure.
Expand Down
56 changes: 56 additions & 0 deletions docs/guides/postgres/concepts/postgres.md
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,62 @@ PostgreSQL managed by KubeDB can be monitored with builtin-Prometheus and Promet
```
- `configuration.secretName` is an optional field that specifies the name of the secret that holds custom configuration files for Postgres cluster.

### spec.tde

`spec.tde` is an optional field that enables Transparent Data Encryption (TDE)
for the cluster using Percona's [`pg_tde`](/docs/guides/postgres/tde/overview/index.md)
extension. When set, table and index data (and optionally the WAL) are encrypted
at rest. TDE requires a `PostgresVersion` whose `spec.distribution` is `Percona`
and whose `spec.tde.supported` is `true`, because the `tde_heap` access method
ships only with Percona Server for PostgreSQL. The whole section is validated by
the admission webhook, and `spec.tde.keyProvider` and `spec.tde.cipher` are
immutable once the database is created.
Comment thread
coderabbitai[bot] marked this conversation as resolved.

```yaml
spec:
tde:
keyProvider:
vault:
address: https://vault.example.com:8200
mountPath: secret
tokenSecretRef:
name: vault-token
defaultEncryptedTables: true
encryptWAL: false
cipher: aes_128
```

It has the following fields:

- `spec.tde.keyProvider` is a required field that selects exactly one place the
principal key lives. Choose one of:
- `vault` points at a HashiCorp Vault KV v2 engine (`address`, `mountPath`,
`tokenSecretRef`, optional `caSecretRef` and `namespace`). This is a global
provider and is required for WAL encryption and for replicated clusters.
- `kmip` points at a KMIP server (`address`, `port`, `credentialSecretRef`
holding `ca.crt`, `client.crt` and `client.key`). Also a global provider.
- `file` uses a local keyring on the data volume. It is only valid for a
single replica (standalone) and cannot back WAL encryption. Use it for
development, not production.
- `spec.tde.defaultEncryptedTables` is an optional boolean. When `true`, the
operator makes `tde_heap` the default access method so every new table is
encrypted without extra SQL.
- `spec.tde.enforceEncryption` is an optional boolean that sets
`pg_tde.enforce_encryption`, which rejects the creation of unencrypted tables.
- `spec.tde.encryptWAL` is an optional boolean that turns on WAL encryption.
It requires a global (`vault` or `kmip`) provider. Enable it after creation
through an [`EnableWALEncryption`](/docs/guides/postgres/concepts/opsrequest.md)
OpsRequest rather than editing the spec directly, so the server key is set up
and the nodes are restarted for you.
- `spec.tde.cipher` is an optional field that selects the encryption algorithm,
one of `aes_128` (default) or `aes_256`.

The principal key can be rotated online, without a restart, through a
[`RotatePrincipalKey`](/docs/guides/postgres/concepts/opsrequest.md) OpsRequest.
The KMS credentials are projected into every pod at `/etc/pg-tde`, outside the
data directory. To learn more, visit the [TDE overview](/docs/guides/postgres/tde/overview/index.md)
and [guide](/docs/guides/postgres/tde/guide/index.md).

### spec.podTemplate

KubeDB allows providing a template for database pod through `spec.podTemplate`. KubeDB operator will pass the information provided in `spec.podTemplate` to the PetSet created for Postgres database.
Expand Down
10 changes: 10 additions & 0 deletions docs/guides/postgres/tde/_index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
title: TDE Encryption at Rest
menu:
docs_{{ .version }}:
identifier: guides-postgres-tde
name: TDE Encryption at Rest
parent: pg-postgres-guides
weight: 75
menu_name: docs_{{ .version }}
---
88 changes: 88 additions & 0 deletions docs/guides/postgres/tde/backup/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
---
title: Backup & Restore a TDE-Encrypted Postgres
menu:
docs_{{ .version }}:
identifier: guides-postgres-tde-backup
name: Backup & Restore
parent: guides-postgres-tde
weight: 30
menu_name: docs_{{ .version }}
section_menu_id: guides
---

> New to KubeDB? Please start with the [KubeDB documentation](/docs/README.md).

# Backup & Restore a TDE-Encrypted Postgres

A TDE-encrypted Postgres cannot use the community physical backup and WAL
archiving path: the physical backup tool (`pg_basebackup`) and the WAL reader
used for continuous archiving cannot read `pg_tde`-encrypted files or its
custom WAL records. KubeDB ships `pg_tde`-aware equivalents for the physical
path, so once you point at the right catalog entries, physical backup and
restore work the same way you would expect. Logical backups are unaffected:
KubeStash's logical backup path already talks to Postgres over the normal
protocol, described below.

Read the [TDE overview](/docs/guides/postgres/tde/overview/index.md) and
[TDE guide](/docs/guides/postgres/tde/guide/index.md) first.

## Logical backup & restore (KubeStash)

[KubeStash logical backup](/docs/guides/postgres/backup/kubestash/logical/index.md)
uses `pg_dump`/`pg_dumpall` to back up and `psql` to restore, which talk to
Postgres over the normal protocol and never touch the on-disk files directly,
so a TDE cluster backs up exactly like a community one -- no extra
configuration needed on the
`BackupConfiguration`/`RestoreSession` side. The `postgres-addon` used by
KubeStash detects the Percona distribution automatically.

The one thing to plan for is the **restore target**:

- Restoring a TDE-encrypted dump into another TDE (Percona) cluster works as
expected; data is re-encrypted under the target cluster's own principal key.
- Restoring a TDE-encrypted dump into a **non-TDE (community) Postgres** is
rejected: the dump contains `pg_tde`/`tde_heap` DDL that a community server
cannot execute. The restore addon detects this up front and fails loudly
instead of partially applying the dump.

## Physical backup, continuous archiving & PITR

Follow the [continuous archiving and PITR guide](/docs/guides/postgres/pitr/archiver.md)
for the general `PostgresArchiver` setup (`BackupStorage`, `RetentionPolicy`,
`PostgresArchiver`, `spec.archiver.ref` on the `Postgres` object). For a TDE
cluster, the differences are:

- **Full/base backups** use `pg_tde_basebackup` instead of `pg_basebackup`
(selected automatically whenever the database image is a Percona
distribution -- no field to set).
- **WAL archiving and PITR recovery** need a `pg_tde`-aware archiver image,
because reading the commit LSN out of the WAL stream (for archiving) and
replaying it (for recovery) both require registering `pg_tde`'s custom WAL
resource manager, and -- when `spec.tde.encryptWAL: true` -- decrypting the
WAL itself. Use a `PostgresVersion` whose `spec.archiver.walg.image` points
at the Percona build of the archiver image (matching the `-percona` catalog
entries used elsewhere in TDE, e.g. `17.9-percona`), not the community
build. The KubeDB installer ships the correct image per version; you only
need to make sure you deployed the `-percona` `PostgresVersion`, the same
one used to create the database.
- This applies whether or not `spec.tde.encryptWAL` is enabled: even with WAL
encryption off, `pg_tde` still writes custom WAL records that a community
WAL reader does not recognize.

With the Percona archiver image in place, PITR works the same for both
`encryptWAL: false` and `encryptWAL: true` clusters. Either way, the original
cluster's principal key must still be resolvable through its key provider
(Vault, KMIP, or file) at restore time: decrypting the archived WAL and the
base backup's `pg_tde` internal keys both depend on it, regardless of whether
WAL encryption itself was on. Restore a `Postgres` with
`spec.init.archiver.recoveryTimestamp` exactly as shown in the
[PITR guide](/docs/guides/postgres/pitr/archiver.md#restore-postgresql).
Comment thread
coderabbitai[bot] marked this conversation as resolved.

## Next Steps

- Review the [TDE overview](/docs/guides/postgres/tde/overview/index.md) for
the key hierarchy and limitations.
- Follow the [TDE guide](/docs/guides/postgres/tde/guide/index.md) to deploy
an encrypted Postgres, rotate the principal key, and enable WAL encryption.
- Learn about [logical backup & restore with KubeStash](/docs/guides/postgres/backup/kubestash/logical/index.md).
- Learn about [continuous archiving and point-in-time recovery](/docs/guides/postgres/pitr/archiver.md).
Loading
Loading