17a2891329
- 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)
89 lines
2.6 KiB
YAML
89 lines
2.6 KiB
YAML
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 |