Transparent Data Encryption (TDE) in EDB Postgres Extended (PGE) in a Kubernetes Environment

Swapnil Suryawanshi
Swapnil Suryawanshi

Transparent Data Encryption (TDE) is a technology used by several database vendors to encrypt data at rest, meaning the database files are stored on disk. However, TDE does not encrypt data that is actively being used. TDE is available in the EDB Postgres Advanced Server and EDB Postgres Extended Server starting from version 15, and it is supported by the EDB Postgres for Kubernetes operator.

Note: TDE is available only for operands that support it: EPAS and PG Extended, versions 15 and newer.

This write-up details the process of setting up Transparent Data Encryption (TDE) in an EDB Postgres Extended (PGE) cluster within a Kubernetes environment. The steps taken, along with their results, are explained below.

Step-by-Step Implementation

Setting Up EDB Postgres Extended

The images for the EDB Postgres for Kubernetes operator, as well as various operands, are kept in private container image registries under For more information, refer to the following resources:


  • Operator: EDB Postgres for Kubernetes v1.22.1
  • Database: EDB Postgres Extended 15.6

1. Create a Namespace for TDE

We start by creating a namespace called tde to isolate our TDE setup.

kubectl create ns tde

namespace/tde created

2. Create a Secret for the TDE Key

Next, we create a Kubernetes secret to store our TDE encryption key. This secret will be referenced in our Postgres cluster configuration.

kubectl create secret generic -o yaml tde-key --from-literal=key=PostgresRocks -n tde


apiVersion: v1
  key: UG9zdGdyZXNSb2Nrcw==
kind: Secret
  creationTimestamp: "2024-03-22T11:20:28Z"
  name: tde-key
  namespace: tde
  resourceVersion: "14915"
  uid: 948e7254-ea82-4355-82a8-7790c0dab1f3
type: Opaque

3. Define the Postgres Cluster with TDE-Enabled

We define the Postgres cluster configuration in postgres-extended-tde.yaml. Note the use of epas to specify the EDB Postgres Advanced Server, which supports TDE.

kind: Cluster
  name: cluster-tde
  instances: 1
    size: 1Gi
  - name: my-secret
        enabled: true
          name: tde-key
          key: key

Note: Various values for the postgresql spec were tried, but only epas worked in the TDE specification.

4. Apply the Postgres Cluster Configuration

We apply the configuration to create the Postgres cluster.

kubectl apply -f postgres-extended-tde.yaml -n tde created

5. Verify the Pod Status

We check the status of the pods to ensure the cluster is running.

kubectl get pods -n tde


cluster-tde-1   1/1     Running   0          36s

6. Check the Cluster Status

We use kubectl cnp status to get a detailed status report of the cluster.

Note: cnp plugin needs to be installed if not already, and link to the Docs

kubectl cnp status cluster-tde -n tde


Cluster Summary
Name:                cluster-tde
Namespace:           tde
System ID:           7349148315743027232
PostgreSQL Image:
Primary instance:    cluster-tde-1
Primary start time:  2024-03-22 11:28:56 +0000 UTC (uptime 1m49s)
Status:              Cluster in healthy state 
Instances:           1
Ready instances:     1
Current Write LSN:   0/305BE98 (Timeline: 1 - WAL File: 000000010000000000000003)

Certificates Status
Certificate Name         Expiration Date                Days Left Until Expiration
----------------         ---------------                --------------------------
cluster-tde-ca           2024-06-20 11:23:47 +0000 UTC  90.00
cluster-tde-replication  2024-06-20 11:23:47 +0000 UTC  90.00
cluster-tde-server       2024-06-20 11:23:47 +0000 UTC  90.00

Continuous Backup status
Not configured

Physical backups
No running physical backups found

Streaming Replication status
Not configured

Unmanaged Replication Slot Status
No unmanaged replication slots found

Managed roles status
No roles managed

Tablespaces status
No managed tablespaces

Instances status
Name           Database Size  Current LSN  Replication role  Status  QoS         Manager Version  Node
----           -------------  -----------  ----------------  ------ ------

cluster-tde-1 29 MB 0/305BE98 Primary OK BestEffort 1.22.1 kind-pg4k-control-plane

7. Access the Postgres Instance and Verify TDE

We connect to the Postgres instance using kubectl cnp psql and perform basic SQL operations to verify that the database is operational and using TDE.

kubectl cnp psql cluster-tde -n tde

psql (15.6 (EDB Postgres Extended Server 15.6.0))
Type "help" for help.


We then run several SQL commands to create a table, insert data, and check the physical storage to confirm encryption.

postgres=# select version();
 PostgreSQL 15.6 (EDB Postgres Extended Server 15.6.0) on x86_64-pc-linux-gnu, compiled by gcc (GCC) 8.5.0 20210514 (Red Hat 8.5.0-20), 64-bit
(1 row)

postgres=# create table testtde (name varchar, id int);

postgres=# insert into testtde values('swapnil',1);

postgres=# select * from testtde;
  name   | id 
 swapnil |  1
(1 row)

postgres=# select pg_relation_filepath('testtde');
(1 row)

8. Validate Data Encryption

To confirm that the data is encrypted on disk, we examine the file associated with the testtde table.

kubectl exec -ti cluster-tde-1 -n tde -- bash

Once inside the container, we navigate to the data directory and use hexdump to inspect the file contents.

[postgres@cluster-tde-1 /]$ cd /var/lib/postgresql/data/pgdata/base/5/
[postgres@cluster-tde-1 5]$ ls -lrth 16394
-rw------- 1 postgres postgres 8.0K Mar 22 11:53 16394

[postgres@cluster-tde-1 5]$ hexdump -C 16394 | grep swapnil
[postgres@cluster-tde-1 5]$ hexdump -C 16394 | tail -5
00001fc0  34 e6 28 8e 42 81 83 a3  71 9d 22 10 83 69 a9 03  |4.(.B...q."..i..|
00001fd0  70 43 fe af 7f 66 d8 cc  78 2b 1c 78 8f 9e e1 42  |pC...f..x+.x...B|
00001fe0  fd a4 38 97 b1 df 43 1e  a8 18 87 90 15 50 90 58  |..8...C......P.X|
00001ff0  a1 64 2e d2 8e ff f4 a6  a8 33 20 70 4f 52 07 0c  |.d.......3 pOR..|

No plain text data ("swapnil") is visible in the file, confirming that the data is encrypted.

9. Validate Data Encryption Version

Finally, we validate the data encryption version to confirm TDE is configured correctly across the cluster.

postgres=# select data_encryption_version from pg_control_init();
(1 row)


Through these steps, we have successfully set up and verified Transparent Data Encryption (TDE) in an EDB Postgres Extended (PGE) cluster running in a Kubernetes environment. The cluster was scaled and verified for encrypted data storage, ensuring data security both in single and multi-instance setups.


Was this article helpful?

0 out of 0 found this helpful