diff --git a/.gitignore b/.gitignore index 1631097..44b2c82 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ helm/*.yaml # Kubernetes manifests (no secrets) are safe to commit !helm/*-cluster.yaml !helm/*-networkpolicies.yaml +!helm/*-databases.yaml # Kubeconfig *.kubeconfig diff --git a/helm/apps-pg-cluster.yaml b/helm/apps-pg-cluster.yaml index a6f1f32..7d9ecdb 100644 --- a/helm/apps-pg-cluster.yaml +++ b/helm/apps-pg-cluster.yaml @@ -34,8 +34,18 @@ spec: owner: apps_admin secret: name: apps-pg-credentials + # Per-app PostgreSQL roles are added here (CNPG 1.28 role lifecycle is + # cluster-scoped — no standalone Role CR). The credential Secret for + # each role lives in the databases namespace and is mirrored into the + # consumer namespace by the consuming repo. See docs/apps-pg.md. + managed: + roles: + - name: vergabe # RAILIANCE-WP-0002 T04 (vergabe-teilnahme) + ensure: present + login: true + passwordSecret: + name: vergabe-app-credentials # HA replica + connection pooler are deferred (RAILIANCE-WP-0003 Notes): - # managed: # services: # additional: # - selectorType: rw diff --git a/helm/apps-pg-databases.yaml b/helm/apps-pg-databases.yaml new file mode 100644 index 0000000..73e7ebf --- /dev/null +++ b/helm/apps-pg-databases.yaml @@ -0,0 +1,21 @@ +--- +# Per-consumer CNPG Database CRs against apps-pg. +# Each entry is a database in the shared cluster, owned by a per-app +# role declared in helm/apps-pg-cluster.yaml under spec.managed.roles. +# See docs/apps-pg.md for the onboarding contract. +apiVersion: postgresql.cnpg.io/v1 +kind: Database +metadata: + name: vergabe-db # RAILIANCE-WP-0002 T04 + namespace: databases + labels: + app.kubernetes.io/name: apps-pg + app.kubernetes.io/component: database-instance + railiance.io/layer: s3-platform + railiance.io/consumer: vergabe-teilnahme +spec: + cluster: + name: apps-pg + name: vergabe_db + owner: vergabe + ensure: present diff --git a/workplans/RAILIANCE-WP-0003-apps-pg-shared-cluster.md b/workplans/RAILIANCE-WP-0003-apps-pg-shared-cluster.md index 1df4c64..fa5cd98 100644 --- a/workplans/RAILIANCE-WP-0003-apps-pg-shared-cluster.md +++ b/workplans/RAILIANCE-WP-0003-apps-pg-shared-cluster.md @@ -77,10 +77,41 @@ standalone CNPG `Role` CR exists. CNPG cluster therefore needs its own NetworkPolicy triplet (egress-to-kube-api, ingress-from-cnpg-operator, ingress-from-app-ns) — pattern visible in `helm/gitea-db-networkpolicies.yaml`. -- No `helm/apps-pg-*.yaml` artifacts exist yet. +- `helm/apps-pg-cluster.yaml`, `helm/apps-pg-networkpolicies.yaml`, + `helm/apps-pg-secret.sops.yaml.template`, and `docs/apps-pg.md` are + present in the repo. - Coordination message id: `768c18f4-8785-4108-a900-fa117eb8778f` (state-hub thread). +## Implementation Notes + +Completed on 2026-05-19. + +- CNPG operator is `ghcr.io/cloudnative-pg/cloudnative-pg:1.28.1`. +- `clusters.postgresql.cnpg.io` and `databases.postgresql.cnpg.io` CRDs + are present; `roles.postgresql.cnpg.io` is not present, so role + onboarding remains platform-administered through managed roles or a + controlled SQL workflow. +- `local-path` is the default StorageClass. The single K3s node reports + no memory, disk, or PID pressure; allocatable ephemeral storage is + about 97.7 GB and memory is about 3.8 GiB. Existing CNPG PVC footprint + before `apps-pg` was two 10Gi PVCs (`gitea-db-1`, + `net-kingdom-pg-1`). +- `databases` exists with `default-deny-all`; `cnpg-system` has the + required `kubernetes.io/metadata.name=cnpg-system` namespace label. +- The live CNPG CRD rejected `spec.postgresql.version`; the deployed + `apps-pg` manifest therefore pins PostgreSQL 16 with + `imageName: ghcr.io/cloudnative-pg/postgresql:16`. +- `apps-pg` is deployed in `databases`, reports `Cluster in healthy + state`, and has primary `apps-pg-1`. +- Services `apps-pg-rw` and `apps-pg-ro` exist. With one instance, + `apps-pg-ro` is present but has no replica endpoint until HA is added. +- A disposable namespace labeled + `railiance.io/postgres-client=apps-pg` successfully connected to + `apps-pg-rw.databases.svc.cluster.local:5432/apps_meta` as + `apps_admin`; the temporary namespace and copied smoke-test secret + were deleted immediately after the check. + ## Safety Contract - Do not commit plaintext credentials. Bootstrap secret is a one-time @@ -221,8 +252,7 @@ metadata: railiance.io/role: shared-apps-database spec: instances: 1 # bump when node RAM > 8GB - postgresql: - version: "16" + imageName: ghcr.io/cloudnative-pg/postgresql:16 storage: size: 10Gi bootstrap: