# PostgreSQL (RDS)

Provision an RDS PostgreSQL instance and connect it to Kloudfuse.

## Prerequisites

- PostgreSQL 18
- Instance class: `db.m5.large` or larger
- Same VPC as the EKS cluster

Set the required environment variables before running the commands on this page:

```console
export NAMESPACE=<your-namespace>
export PG_PASSWORD=<your-password>
```

## Create Kubernetes Secret

```console
PG_PASSWORD_ENCODED=$(python3 -c "import urllib.parse; print(urllib.parse.quote('$PG_PASSWORD', safe=''))")

kubectl create secret generic kfuse-pg-credentials \
  --namespace="$NAMESPACE" \
  --from-literal=postgres-password="$PG_PASSWORD" \
  --from-literal=postgresql-password="$PG_PASSWORD" \
  --from-literal=postgresql-password-encoded="$PG_PASSWORD_ENCODED" \
  --from-literal=postgresql-replication-password="$PG_PASSWORD"

curl -o rds-ca-bundle.pem https://truststore.pki.rds.amazonaws.com/global/global-bundle.pem
kubectl create secret generic pg-tls-ca-cert \
  --namespace="$NAMESPACE" \
  --from-file=ca.crt=rds-ca-bundle.pem
```

## Create RDS Instance

```console
aws rds create-db-instance \
  --db-instance-identifier "<cluster-name>-pg" \
  --db-instance-class db.m5.large \
  --engine postgres \
  --engine-version "18.3" \
  --master-username postgres \
  --master-user-password "<rds-master-password>" \
  --allocated-storage 100 \
  --storage-type gp3 \
  --no-publicly-accessible \
  --storage-encrypted
```

## Create Application Database User

Connect to RDS using the master user and create the application user:

```console
psql "host=<rds-endpoint> user=postgres dbname=postgres sslmode=require"
```

```sql
CREATE USER <your-app-username> WITH PASSWORD '$PG_PASSWORD' CREATEDB;
```

## Helm Values

Add the following to your `custom-values.yaml`. Use the RDS endpoint from the instance created above.

- Standard (kfuse)
- FED (kfuse-fed)

```yaml
global:
  configDB:
    host: "<rds-endpoint>"
    username: "<your-app-username>"
  orchestratorDB:
    host: "<rds-endpoint>"
    username: "<your-app-username>"

installKfusePgCredentials: false
```

The FED chart defaults to a non-`postgres` username. Set the username consistently across all services:

```yaml
global:
  configDB:
    host: "<rds-endpoint>"
    username: "<your-app-username>"
  orchestratorDB:
    host: "<rds-endpoint>"
    username: "<your-app-username>"

installKfusePgCredentials: false

# Per-service PostgreSQL username overrides
az-service:
  config:
    configdb:
      pgUser: "<your-app-username>"
    orchestratordb:
      pgUser: "<your-app-username>"

beffe:
  config:
    PG_USER: "<your-app-username>"

config-mgmt-service:
  config:
    configdb:
      user: "<your-app-username>"

ingester:
  config:
    rum:
      postgresdb:
        user: "<your-app-username>"
  postgresql:
    auth:
      username: "<your-app-username>"

pinot:
  pgConfig:
    user: "<your-app-username>"

query-service:
  config:
    PG_USER: "<your-app-username>"
  advancefunctions:
    config:
      PG_USER: "<your-app-username>"
  rulemanager:
    config:
      PG_USER: "<your-app-username>"

trace-query-service:
  config:
    PG_USER: "<your-app-username>"

rum-query-service:
  config:
    defaultBackendVersion: v1

logs-query-service:
  config:
    MetadataDb:
      pgUser: "<your-app-username>"

logs-transformer:
  config:
    LogConfigDb:
      pgUser: "<your-app-username>"

trace-transformer:
  config:
    SpanConfigDb:
      pgUser: "<your-app-username>"

user-mgmt-service:
  config:
    PG_USER: "<your-app-username>"

zapper:
  config:
    pgConfig:
      user: "<your-app-username>"

grafana:
  grafana.ini:
    database:
      user: "<your-app-username>"
```
