feat(aula-17): adicionar Cloud Native PostgreSQL (CNPG)

- Cluster PostgreSQL 3 instâncias com anti-affinity por hostname (hard)
  e por zona (soft) para spread entre datacenters Hetzner
- Backup automático via Barman Cloud para Hetzner Object Storage (S3)
- ScheduledBackup diário às 03:00
- App demo que valida conexão com o banco
- setup.sh: instala operator, cria cluster, deploya demo
- cleanup.sh: remoção limpa (backups S3 preservados)
This commit is contained in:
ArgoCD Setup
2026-05-09 02:14:22 -03:00
parent 5634c5f98f
commit 17a2891329
10 changed files with 1016 additions and 1 deletions
+9
View File
@@ -0,0 +1,9 @@
apiVersion: v1
kind: Secret
metadata:
name: cnpg-backup-credentials
namespace: cnpg
type: Opaque
stringData:
ACCESS_KEY_ID: CHANGE_ACCESS_KEY
ACCESS_SECRET_KEY: CHANGE_SECRET_KEY
+89
View File
@@ -0,0 +1,89 @@
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: shared-postgres
namespace: cnpg
spec:
imageName: ghcr.io/cloudnative-pg/postgresql:17.2-4
instances: 3
enableSuperuserAccess: true
# ── Topology-aware placement ──
# Hetzner CCM labels nodes automatically:
# topology.kubernetes.io/zone = fsn1 | nbg1 | hel1 (datacenter)
# topology.kubernetes.io/region = eu-central | hel-southeast
#
# Layer 1: podAntiAffinity on hostname (hard constraint)
# → No 2 PG pods on the same node. Ever.
#
# Layer 2: podAntiAffinity on zone (soft constraint)
# → Prefer spreading across datacenters. With nodes in fsn1, nbg1, hel1,
# you get 1 pod per DC. With only eu-central nodes, they still spread
# across FSN and NBG (both in eu-central, ~1-2ms apart).
#
# Prerequisite for cross-region (eu-central + HEL):
# - Node pool in eu-central (FSN + NBG) → aula-08
# - Node pool in hel-southeast (HEL) → add worker after aula-08
# - Without HEL nodes, all 3 pods stay in eu-central (still HA within region)
affinity:
topologyKey: kubernetes.io/hostname
podAntiAffinityType: required
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
topologyKey: topology.kubernetes.io/zone
labelSelector:
matchLabels:
cnpg.io/cluster: shared-postgres
storage:
size: 10Gi
storageClass: hcloud-volumes
walStorage:
size: 5Gi
storageClass: hcloud-volumes
resources:
requests:
cpu: 500m
memory: 1Gi
limits:
cpu: "1"
memory: 1Gi
postgresql:
parameters:
max_connections: "100"
shared_buffers: "256MB"
effective_cache_size: "512MB"
work_mem: "4MB"
maintenance_work_mem: "128MB"
log_min_duration_statement: "1000"
bootstrap:
initdb:
database: app
owner: app
secret:
name: shared-postgres-superuser
superuserSecret:
name: shared-postgres-superuser
backup:
barmanObjectStore:
destinationPath: s3://CHANGE_BUCKET_NAME/cnpg-backups/shared-postgres
endpointURL: https://CHANGE_ENDPOINT
s3Credentials:
accessKeyId:
name: cnpg-backup-credentials
key: ACCESS_KEY_ID
secretAccessKey:
name: cnpg-backup-credentials
key: ACCESS_SECRET_KEY
wal:
compression: gzip
data:
compression: gzip
jobs: 2
retentionPolicy: "30d"
monitoring:
enablePodMonitor: true
startDelay: 3600
livenessProbeTimeout: 90
primaryUpdateStrategy: unsupervised
primaryUpdateMethod: switchover
+11
View File
@@ -0,0 +1,11 @@
apiVersion: postgresql.cnpg.io/v1
kind: ScheduledBackup
metadata:
name: shared-postgres-backup
namespace: cnpg
spec:
cluster:
name: shared-postgres
schedule: "0 3 * * *"
backupOwnerReference: cluster
method: barmanObjectStore