Adds the shared CloudNativePG cluster apps-pg for S5 application databases: - helm/apps-pg-cluster.yaml — Cluster CR, PG 16, 1 instance, 10Gi - helm/apps-pg-networkpolicies.yaml — egress-to-kube-api + ingress-from-cnpg-operator + label-based ingress opt-in (railiance.io/postgres-client=apps-pg) - helm/apps-pg-secret.sops.yaml.template — bootstrap credential template (encrypt with SOPS before committing the real .sops.yaml) - Makefile targets: apps-pg-deploy, apps-pg-status (with cnpg-plugin fallback), apps-pg-shell (apps_admin/apps_meta), apps-pg-logs - docs/apps-pg.md (codex) — consumer onboarding contract clarifying the CNPG 1.28 role/database lifecycle boundary Also fixes helm/gitea-db-cluster.yaml: spec.postgresql.version is not a valid CNPG v1 field (strict decoding rejects it). Replaced with spec.imageName matching the live cluster (postgresql:18.1-system-trixie) so make db-deploy is a no-op instead of an apply rejection. Live state at commit time: Cluster apps-pg in healthy state, primary apps-pg-1 Running, smoke-tested via psql from a labeled temp ns. Co-Authored-By: codex <noreply@openai.com> Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
98 lines
3.5 KiB
Markdown
98 lines
3.5 KiB
Markdown
# apps-pg Shared PostgreSQL Cluster
|
|
|
|
`apps-pg` is the shared CloudNativePG cluster for S5 application
|
|
databases. It lives in the `databases` namespace and is owned by
|
|
`railiance-platform` as an S3 platform service.
|
|
|
|
## Cluster Identity
|
|
|
|
- CNPG Cluster: `apps-pg`
|
|
- Namespace: `databases`
|
|
- PostgreSQL major version: `16`
|
|
- Primary endpoint: `apps-pg-rw.databases.svc.cluster.local:5432`
|
|
- Read-only endpoint: `apps-pg-ro.databases.svc.cluster.local:5432`
|
|
- Bootstrap database: `apps_meta`
|
|
- Bootstrap role: `apps_admin`
|
|
|
|
`apps_admin` is a platform bootstrap and smoke-test role. Do not copy it
|
|
into application namespaces, use it in S5 runtime configuration, or treat
|
|
it as a consumer credential.
|
|
|
|
## Consumer Onboarding
|
|
|
|
Each S5 application gets its own role, database, and runtime Secret. The
|
|
current flow is platform-administered until OpenBao or a dedicated
|
|
database onboarding automation owns the lifecycle end to end.
|
|
|
|
1. Request an app database in the consuming repo workplan. Include the
|
|
app name, namespace, database name, role name, intended owners, and
|
|
any required extensions.
|
|
2. Platform reviews and approves the database/role names. Names should
|
|
be app-scoped, for example `vergabe` and `vergabe_db`.
|
|
3. Platform provisions the backing PostgreSQL role and credential for
|
|
the approved app. Until automation exists, this is a controlled
|
|
operator SQL action against `apps-pg`, not a self-service repo apply.
|
|
4. Add a CNPG `Database` manifest in the platform-managed database
|
|
manifests, with `spec.cluster.name: apps-pg` and `spec.owner` set to
|
|
the approved role.
|
|
5. Label the consuming namespace so NetworkPolicy allows access:
|
|
|
|
```bash
|
|
kubectl label namespace <app-namespace> \
|
|
railiance.io/postgres-client=apps-pg
|
|
```
|
|
|
|
6. Publish or mirror the runtime Secret into the consumer namespace. The
|
|
Secret should contain only that app's role credential and DSN fields.
|
|
7. Wire the DSN into the application Helm values or runtime
|
|
configuration. Prefer the RW service for migrations and writes:
|
|
`postgresql://<role>:<password>@apps-pg-rw.databases.svc.cluster.local:5432/<database>`.
|
|
|
|
Example CNPG `Database` resource:
|
|
|
|
```yaml
|
|
apiVersion: postgresql.cnpg.io/v1
|
|
kind: Database
|
|
metadata:
|
|
name: vergabe-db
|
|
namespace: databases
|
|
spec:
|
|
cluster:
|
|
name: apps-pg
|
|
name: vergabe_db
|
|
owner: vergabe
|
|
```
|
|
|
|
## CNPG Boundary
|
|
|
|
CNPG 1.28 provides a standalone `Database` CRD. It does not provide a
|
|
standalone `Role` CRD in this cluster. Role lifecycle is cluster-scoped,
|
|
through `Cluster.spec.managed.roles` or a controlled SQL workflow.
|
|
|
|
Consumer repos must therefore not assume they can create PostgreSQL
|
|
roles themselves. They can request a database and consume a runtime
|
|
Secret after the platform role has been provisioned.
|
|
|
|
## Network Policy
|
|
|
|
The `databases` namespace has a default-deny posture. `apps-pg` accepts
|
|
client traffic on TCP/5432 only from namespaces labeled:
|
|
|
|
```text
|
|
railiance.io/postgres-client=apps-pg
|
|
```
|
|
|
|
The CNPG operator in `cnpg-system` is allowed to manage the cluster on
|
|
the standard PostgreSQL, instance manager, and metrics ports.
|
|
|
|
## Backup And Roadmap
|
|
|
|
`apps-pg` starts as a conservative single-instance, 10Gi cluster to match
|
|
the current node capacity and existing CNPG footprint. Adding a replica,
|
|
PgBouncer/CNPG `Pooler`, resize policy, and CNPG-native backup coverage
|
|
are follow-up platform work items.
|
|
|
|
Until backup coverage is explicitly added, consumer onboarding should
|
|
record whether app data is disposable, externally reproducible, or
|
|
requires an immediate backup follow-up before production use.
|