PostgreSQL Hoge beschikbaarheid met knapperige gegevens PGO: Enterprise Kubernetes-implementatie
Enterprise PostgreSQL HA met Crunchy Data PGO op Kubernetes
PostgreSQL in productie draaien op Kubernetes vereist meer dan een StatefulSet met een persistent volume. U hebt geautomatiseerde failover, continue back-up en point-in-time herstel, pooling van verbindingen, TLS-encryptie, monitoring en de mogelijkheid om consistent te implementeren bij cloudproviders en bare metal nodig. Crunchy Data PGO (Postgres Operator) v5 levert dit allemaal via een enkele Kubernetes-native aangepaste bron – dePostgresClusterCRD – ondersteund door beproefde componenten: Patroni voor op consensus gebaseerde HA, pgBackRest voor bedrijfsback-up, PgBouncer voor verbindingspooling en pgMonitor voor Prometheus-compatibele observatie.
Deze handleiding behandelt alles wat nodig is om een door PGO beheerd PostgreSQL-cluster te brengen, van de initiële implementatie tot gebruik op productieniveau in AWS EKS, Azure AKS, GCP GKE en bare metal k3s met Rancher. Elke sectie bevat concrete YAML-, Helm-waarden en operationele procedures die u aan uw omgeving kunt aanpassen.
Crunchy Data PGO v5-architectuur
PGO v5 is een volledige herschrijving van de Crunchy Postgres Operator. Het vervangt de vorige pgcluster/pgreplica/pgpolicy CRDs door een enkelePostgresCluster-bron die elk aspect van een PostgreSQL-implementatie declaratief beschrijft. De operator let op wijzigingen in deze bron en stemt de onderliggende Kubernetes-objecten – StatefulSets, Services, ConfigMaps, Secrets, Jobs – af op de gewenste status.
De architectuur is gebouwd op vier pijlers.Patronidraait als zijspan in elke PostgreSQL-pod en beheert de verkiezing van leiders, replicatietopologie en automatische failover met behulp van Kubernetes-native gedistribueerde consensus.pgBackRestverwerkt volledige, differentiële en incrementele back-ups plus continue WAL-archivering naar objectopslag (S3, GCS, Azure Blob) of lokale PVC's.PgBouncerbiedt lichtgewicht verbindingspooling die PostgreSQL beschermt tegen verbindingsstormen.pgMonitormaakt PostgreSQL-statistieken zichtbaar via een Prometheus-exporteurzijspan voor integratie met uw bestaande observatiestapel.
De operator zelf is staatloos: alle persistente statussen bevinden zich in het PostgreSQL-cluster en de back-uprepository. Dit betekent dat u de operator kunt upgraden of opnieuw kunt opstarten zonder dat dit gevolgen heeft voor actieve databases. De operator-afstemmingslus is idempotent: het meerdere keren toepassen van dezelfdePostgresCluster-specificatie levert dezelfde set Kubernetes-objecten op.
PGO v5
installerenPGO v5 kan worden geïnstalleerd via Helm of directe kubectl-manifesten. Voor productiedoeleinden wordt de voorkeur gegeven aan de Helm-aanpak, omdat deze naadloos integreert met GitOps-workflows en versiegestuurde upgrades biedt.
# Add the Crunchy Data Helm repository
helm repo add crunchydata https://charts.crunchydata.com
helm repo update
# Install PGO into its own namespace
helm install pgo crunchydata/pgo \
--namespace postgres-operator \
--create-namespace \
--set controllerImages.cluster=registry.crunchydata.com/crunchydata/postgres-operator:ubi8-5.7.2-0 \
--set relatedImages.postgres_16=registry.crunchydata.com/crunchydata/crunchy-postgres:ubi8-16.6-1 \
--set relatedImages.pgbackrest=registry.crunchydata.com/crunchydata/crunchy-pgbackrest:ubi8-2.54.1-0 \
--set relatedImages.pgbouncer=registry.crunchydata.com/crunchydata/crunchy-pgbouncer:ubi8-1.23.1-0 \
--set relatedImages.pgexporter=registry.crunchydata.com/crunchydata/crunchy-postgres-exporter:ubi8-0.16.0-0Voor omgevingen met luchtspleten spiegelt u de vereiste images naar uw interne register en werkt u derelatedImages-waarden dienovereenkomstig bij. PGO haalt alleen afbeeldingen op die zijn gespecificeerd in de Helm-waarden of dePostgresCluster-specificatie - het bereikt tijdens runtime nooit externe registers, tenzij dit expliciet is geconfigureerd om dit te doen.
# Verify the operator is running
kubectl get pods -n postgres-operator
NAME READY STATUS RESTARTS AGE
pgo-controller-manager-7d8f9b6c4-xk2pt 1/1 Running 0 45sPostgresCluster CRD Specificatie
DePostgresClusterCRD is het enige declaratieve oppervlak voor uw gehele PostgreSQL-implementatie. Hieronder vindt u een productieklare specificatie die de belangrijkste onderdelen demonstreert. Elke sectie wordt in de volgende delen van deze handleiding gedetailleerd besproken.
apiVersion: postgres-operator.crunchydata.com/v1beta1
kind: PostgresCluster
metadata:
name: production-db
namespace: databases
spec:
postgresVersion: 16
image: registry.crunchydata.com/crunchydata/crunchy-postgres:ubi8-16.6-1
instances:
- name: pgha1
replicas: 3
resources:
requests:
cpu: "2"
memory: 8Gi
limits:
cpu: "4"
memory: 16Gi
dataVolumeClaimSpec:
storageClassName: gp3-csi
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 100Gi
walVolumeClaimSpec:
storageClassName: gp3-csi
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 20Gi
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- topologyKey: kubernetes.io/hostname
labelSelector:
matchLabels:
postgres-operator.crunchydata.com/cluster: production-db
tolerations:
- key: "workload"
operator: "Equal"
value: "database"
effect: "NoSchedule"
backups:
pgbackrest:
image: registry.crunchydata.com/crunchydata/crunchy-pgbackrest:ubi8-2.54.1-0
configuration:
- secret:
name: pgbackrest-s3-creds
global:
repo1-retention-full: "7"
repo1-retention-diff: "14"
repo1-path: /pgbackrest/production-db/repo1
repo1-s3-uri-style: path
repos:
- name: repo1
schedules:
full: "0 2 * * 0" # Sunday 2am
differential: "0 2 * * 1-6" # Mon-Sat 2am
incremental: "0 */4 * * *" # Every 4 hours
s3:
bucket: mycompany-pg-backups
endpoint: s3.eu-west-1.amazonaws.com
region: eu-west-1
proxy:
pgBouncer:
image: registry.crunchydata.com/crunchydata/crunchy-pgbouncer:ubi8-1.23.1-0
replicas: 2
resources:
requests:
cpu: 500m
memory: 256Mi
limits:
cpu: "1"
memory: 512Mi
config:
global:
pool_mode: transaction
max_client_conn: "1000"
default_pool_size: "25"
min_pool_size: "5"
reserve_pool_size: "5"
reserve_pool_timeout: "3"
monitoring:
pgmonitor:
exporter:
image: registry.crunchydata.com/crunchydata/crunchy-postgres-exporter:ubi8-0.16.0-0
resources:
requests:
cpu: 100m
memory: 128Mi
patroni:
dynamicConfiguration:
synchronous_mode: true
postgresql:
parameters:
shared_buffers: 2GB
effective_cache_size: 6GB
work_mem: 32MB
maintenance_work_mem: 512MB
max_connections: 200
wal_buffers: 64MB
checkpoint_completion_target: 0.9
random_page_cost: 1.1
effective_io_concurrency: 200
min_wal_size: 1GB
max_wal_size: 4GB
max_worker_processes: 8
max_parallel_workers_per_gather: 4
max_parallel_workers: 8
log_min_duration_statement: 500
log_checkpoints: "on"
log_connections: "on"
log_disconnections: "on"
log_lock_waits: "on"
users:
- name: appuser
databases: ["appdb"]
options: "NOSUPERUSER"
- name: readonly
databases: ["appdb"]
options: "NOSUPERUSER"
databaseInitSQL:
name: init-sql-configmap
key: init.sqlDeze specificatie creëert een PostgreSQL 16-cluster met drie exemplaren met afzonderlijke gegevens- en WAL-volumes, S3-back-ups volgens een volledig/differentieel/incrementeel schema, PgBouncer-verbindingspooling in transactiemodus, Prometheus-statistiekenexport en synchrone Patroni-replicatie. De anti-affiniteitsregel van de pod zorgt ervoor dat alle drie de instanties op verschillende Kubernetes-knooppunten terechtkomen.
Patroni-gebaseerde HA en automatische failover
Patroni is het HA-framework dat is ingebed in elke door PGO beheerde PostgreSQL-pod. Het gebruikt de Kubernetes API als gedistribueerde configuratieopslag (DCS) - er is geen afzonderlijk etcd- of ZooKeeper-cluster vereist. Patroni bewaakt voortdurend de gezondheid van de primaire PostgreSQL en replica's. Wanneer de primaire niet meer reageert, initieert Patroni een automatische failover: het promoveert de meest up-to-date replica naar de primaire en configureert de resterende replica's opnieuw om de nieuwe leider te volgen.
Het failover-proces in PGO werkt als volgt. Patroni op elke pod heeft een leidersslot in Kubernetes (via Endpoints of ConfigMap-objecten). De huidige primaire moet deze vergrendeling vernieuwen met een configureerbaar interval (standaard 10 seconden TTL, 3 seconden luswachttijd). Als de primaire niet kan worden vernieuwd (omdat deze is gecrasht, het knooppunt is overleden of het netwerk deze heeft gepartitioneerd), zal een replica die het dichtst bij de WAL-positie van de primaire is, de vergrendeling verkrijgen en zichzelf promoten. Het hele proces is doorgaans binnen 10 tot 30 seconden voltooid.
Synchrone replicatiemodus, ingeschakeld viasynchronous_mode: truein de Patroni-configuratie, garandeert nul gegevensverlies (RPO = 0) ten koste van een iets hogere schrijflatentie. In de synchrone modus wordt een transactie pas aan de client bevestigd als ten minste één replica heeft bevestigd dat hij de WAL heeft ontvangen. Als er geen synchrone replica beschikbaar is, schakelt Patroni tijdelijk de synchrone modus uit om de beschikbaarheid te behouden. U kunt dit overschrijven metsynchronous_mode_strict: trueals u de beschikbaarheid liever opoffert voor consistentie.
# Check Patroni cluster status
kubectl exec -it production-db-pgha1-0 -n databases -- patronictl list
+----------------------------+-------------------+---------+---------+----+-----------+
| Member | Host | Role | State | TL | Lag in MB |
+----------------------------+-------------------+---------+---------+----+-----------+
| production-db-pgha1-0 | 10.244.0.15 | Leader | running | 3 | |
| production-db-pgha1-1 | 10.244.1.22 | Replica | running | 3 | 0 |
| production-db-pgha1-2 | 10.244.2.18 | Replica | running | 3 | 0 |
+----------------------------+-------------------+---------+---------+----+-----------+
# Manual switchover (planned, zero downtime)
kubectl exec -it production-db-pgha1-0 -n databases -- \
patronictl switchover --master production-db-pgha1-0 --candidate production-db-pgha1-1 --force
# Manual failover (forced, for emergencies)
kubectl exec -it production-db-pgha1-1 -n databases -- \
patronictl failover --candidate production-db-pgha1-1 --forcePGO configureert automatisch de Kubernetes Services om de Patroni-leider te volgen. Deproduction-db-primary-service verwijst altijd naar de pod die momenteel de leidervergrendeling bevat, zodat toepassingen die via deze service verbinding maken, een naadloze failover ervaren met slechts een korte reset van de verbinding.
pgBackRest Back-up en herstel
pgBackRest is de back-upengine die in PGO is geïntegreerd. Het ondersteunt drie back-uptypen: volledig, differentieel en incrementeel, plus continue WAL-archivering voor point-in-time herstel (PITR). Begrijpen hoe deze in elkaar passen is essentieel voor het ontwerpen van een back-upstrategie die de opslagkosten, back-upsnelheid en hersteltijd in evenwicht houdt.
Een volledige back-up vankopieert de volledige PostgreSQL-gegevensmap en is de basis voor alle andere back-uptypen. Eendifferentiële back-upkopieert alleen pagina's die zijn gewijzigd sinds de laatste volledige back-up. Een incrementele back-up vankopieert alleen pagina's die zijn gewijzigd sinds de laatste back-up van welk type dan ook. Tijdens het herstel koppelt pgBackRest automatisch de vereiste back-ups aan elkaar. Voor het herstellen van een incrementele back-up zijn bijvoorbeeld de incrementele plus de eerdere differentiële (of volledige) plus de volledige back-up nodig, plus eventuele WAL-segmenten die nodig zijn om het doelherstelpunt te bereiken.
Back-upschemaconfiguratie
Het back-upschema wordt gedefinieerd in derepos-sectie van de pgBackRest-configuratie binnen dePostgresCluster-specificatie. Een solide productieschema voert doorgaans wekelijks volledige, dagelijkse differentiële en frequentere incrementele back-ups uit.
backups:
pgbackrest:
global:
repo1-retention-full: "4" # Keep 4 full backups
repo1-retention-full-type: count
repo1-retention-diff: "14" # Keep 14 differentials
repos:
- name: repo1
schedules:
full: "0 2 * * 0" # Weekly full: Sunday 2am
differential: "0 2 * * 1-6" # Daily diff: Mon-Sat 2am
incremental: "0 */6 * * *" # Every 6 hours
s3:
bucket: mycompany-pg-backups
endpoint: s3.eu-west-1.amazonaws.com
region: eu-west-1Handmatige back-up en herstel van
# Trigger a manual full backup
kubectl annotate postgrescluster production-db -n databases \
postgres-operator.crunchydata.com/pgbackrest-backup="$(date +%s)" \
--overwrite
# Check backup status
kubectl exec -it production-db-pgha1-0 -n databases -- \
pgbackrest info --stanza=db
# Restore to a specific point in time
# First, update the PostgresCluster spec:
spec:
backups:
pgbackrest:
restore:
enabled: true
repoName: repo1
options:
- --type=time
- --target="2026-04-12 08:30:00+00"
- --target-action=promote
# Apply the restore annotation
kubectl annotate postgrescluster production-db -n databases \
postgres-operator.crunchydata.com/pgbackrest-restore="$(date +%s)" \
--overwriteTijdens een PITR-herstel sluit PGO alle PostgreSQL-instanties af, herstelt vanaf de dichtstbijzijnde volledige of differentiële back-up, speelt WAL-segmenten opnieuw af tot de doeltijd en start vervolgens het cluster. De hele operatie wordt georkestreerd door de operator; er is geen handmatige tussenkomst op individuele pods nodig.
PgBouncer-verbindingspooling
PostgreSQL creëert een nieuw proces voor elke clientverbinding. Op grote schaal – honderden of duizenden applicatie-pods die elk verbindingspools onderhouden – mislukt dit model. PgBouncer bevindt zich tussen uw applicatie en PostgreSQL en multiplext veel clientverbindingen over een kleiner aantal serververbindingen.
PGO implementeert PgBouncer als een afzonderlijke implementatie met een eigen service. Uw toepassingen moeten verbinding maken met deproduction-db-pgbouncer-service, niet rechtstreeks met de primaire PostgreSQL-service. PgBouncer ondersteunt drie poolmodi:
- Sessiepooling— een serververbinding wordt toegewezen aan een client voor de levensduur van de clientverbinding. Veiligst, maar minst efficiënt.
- Transactiepooling— een serververbinding wordt alleen toegewezen voor de duur van een transactie. Meest efficiënt voor webworkloads. Dit is de aanbevolen standaardwaarde.
- Verzameling van overzichten— er wordt een serververbinding toegewezen voor één enkel overzicht. Werkt alleen voor eenvoudige, niet-transactionele werklasten.
proxy:
pgBouncer:
replicas: 3
config:
global:
pool_mode: transaction
max_client_conn: "2000"
default_pool_size: "30"
min_pool_size: "10"
reserve_pool_size: "10"
reserve_pool_timeout: "3"
server_idle_timeout: "300"
server_lifetime: "3600"
client_idle_timeout: "600"
tcp_keepalive: "1"
tcp_keepidle: "30"
tcp_keepintvl: "10"
tcp_keepcnt: "3"
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
topologyKey: kubernetes.io/hostname
labelSelector:
matchLabels:
postgres-operator.crunchydata.com/role: pgbouncerLet op detcp_keepalive-instellingen: deze zijn van cruciaal belang wanneer PgBouncer achter een cloud-load balancer of Kubernetes-service draait. Zonder agressieve keepalives kunnen inactieve verbindingen stilletjes worden verbroken door tussenliggende netwerkcomponenten, waardoor bij de volgende querypoging toepassingsfouten ontstaan.
pgMonitor en Prometheus/Grafana-bewaking
De monitoring-integratie vanPGO maakt gebruik van eencrunchy-postgres-exporterzijspan in elke PostgreSQL-pod. Deze exporteur schrapt de interne statistische weergaven van PostgreSQL en stelt deze bloot als Prometheus-statistieken op poort 9187. De exporteur dekt kant-en-klaar meer dan 150 statistieken, inclusief verbindingen, replicatievertraging, transactiesnelheden, cache-hitratio's, tabel- en indexstatistieken, slotconflicten en WAL-generatiesnelheden.
# ServiceMonitor for Prometheus Operator auto-discovery
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: postgres-monitoring
namespace: databases
labels:
release: kube-prometheus-stack
spec:
selector:
matchLabels:
postgres-operator.crunchydata.com/cluster: production-db
postgres-operator.crunchydata.com/crunchy-postgres-exporter: "true"
endpoints:
- port: exporter
interval: 15s
scrapeTimeout: 10sCrunchy Data biedt een set vooraf gebouwde Grafana-dashboards die u rechtstreeks kunt importeren. Deze omvatten het PostgreSQL-overzicht, de replicatiestatus, de back-upstatus van pgBackRest, PgBouncer-statistieken en het gebruik van bronnen op pod-niveau. Importeer ze via de dashboardinrichting van Grafana of handmatig vanuit de Crunchy Data-voorbeeldrepository.
# Install Grafana dashboards as ConfigMaps
kubectl create configmap grafana-pg-overview \
--from-file=pg-overview.json=dashboards/pg-overview.json \
-n monitoring
kubectl label configmap grafana-pg-overview grafana_dashboard=1 -n monitoringKritieke waarschuwingsregels voor PostgreSQL
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: postgres-alerts
namespace: databases
labels:
release: kube-prometheus-stack
spec:
groups:
- name: postgresql-health
rules:
- alert: PostgresReplicationLagHigh
expr: ccp_replication_lag_size_bytes > 104857600
for: 5m
labels:
severity: warning
annotations:
summary: "Replica {{ $labels.pod }} lag exceeds 100MB"
- alert: PostgresConnectionsExhausted
expr: ccp_connection_stats_active / ccp_connection_stats_max_connections > 0.85
for: 2m
labels:
severity: critical
annotations:
summary: "PostgreSQL connections above 85% capacity"
- alert: PostgresDeadlockDetected
expr: rate(ccp_stat_database_deadlocks[5m]) > 0
for: 1m
labels:
severity: warning
annotations:
summary: "Deadlocks detected in {{ $labels.datname }}"
- alert: PostgresCacheHitRatioLow
expr: ccp_stat_database_blks_hit / (ccp_stat_database_blks_hit + ccp_stat_database_blks_read) < 0.95
for: 10m
labels:
severity: warning
annotations:
summary: "Cache hit ratio below 95% for {{ $labels.datname }}"
- alert: PgBackRestStaleBackup
expr: time() - ccp_backrest_last_full_backup_time_since_completion_seconds > 604800
for: 1h
labels:
severity: critical
annotations:
summary: "No full backup in the last 7 days"AWS EKS-implementatie
Voor het implementeren van PGO op AWS EKS is configuratie van het EBS CSI-stuurprogramma voor persistente volumes en IAM Roles for Service Accounts (IRSA) voor S3-back-uptoegang vereist. Deze aanpak vermijdt het opslaan van AWS-referenties met een lange levensduur in Kubernetes-geheimen.
# Install the EBS CSI driver (required for gp3 volumes)
eksctl create addon --name aws-ebs-csi-driver --cluster my-cluster --region eu-west-1 \
--service-account-role-arn arn:aws:iam::111122223333:role/AmazonEKS_EBS_CSI_DriverRole
# Create a gp3 StorageClass
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: gp3-csi
provisioner: ebs.csi.aws.com
parameters:
type: gp3
iops: "3000"
throughput: "125"
encrypted: "true"
volumeBindingMode: WaitForFirstConsumer
allowVolumeExpansion: true# IAM policy for pgBackRest S3 access
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetObject",
"s3:DeleteObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::mycompany-pg-backups",
"arn:aws:s3:::mycompany-pg-backups/*"
]
}
]
}
# Create an IRSA-enabled service account
eksctl create iamserviceaccount \
--name pgbackrest-sa \
--namespace databases \
--cluster my-cluster \
--attach-policy-arn arn:aws:iam::111122223333:policy/PGBackRestS3Policy \
--approveVerwijs in dePostgresCluster-specificatie naar de S3-bucket en regio. PGO gebruikt automatisch de inloggegevens van de serviceaccount van de pod (via IRSA) - er zijn geen expliciete toegangssleutels nodig.
backups:
pgbackrest:
repos:
- name: repo1
s3:
bucket: mycompany-pg-backups
endpoint: s3.eu-west-1.amazonaws.com
region: eu-west-1Voor multi-AZ-veerkracht moet u ervoor zorgen dat uw EKS-knooppuntgroepen ten minste drie beschikbaarheidszones bestrijken en de eerder getoonde topologiespreidingsbeperkingen gebruiken om PostgreSQL-pods erover te distribueren.
Azure AKS-implementatie
Azure AKS maakt gebruik van beheerde schijven voor permanente opslag en Azure Blob Storage voor pgBackRest-back-ups. De aanbevolen opslagklasse maakt gebruik van Premium SSD v2 of Premium LRS voor databaseworkloads.
# StorageClass for Azure Premium SSD
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: azure-premium-ssd
provisioner: disk.csi.azure.com
parameters:
skuName: Premium_LRS
kind: Managed
volumeBindingMode: WaitForFirstConsumer
allowVolumeExpansion: true
---
# pgBackRest with Azure Blob Storage
backups:
pgbackrest:
configuration:
- secret:
name: pgbackrest-azure-creds
global:
repo1-azure-account: mystorageaccount
repo1-retention-full: "7"
repos:
- name: repo1
schedules:
full: "0 2 * * 0"
differential: "0 2 * * 1-6"
azure:
container: pg-backups
---
# Secret with Azure credentials
apiVersion: v1
kind: Secret
metadata:
name: pgbackrest-azure-creds
namespace: databases
stringData:
azure.conf: |
[global]
repo1-azure-key=BASE64_STORAGE_ACCOUNT_KEYVoor Workload Identity (het Azure-equivalent van AWS IRSA) configureert u het AKS-cluster met OIDC-uitgever en maakt u een federatieve identiteitsreferentie voor het pgBackRest-serviceaccount. Hierdoor zijn er geen opslagaccountsleutels meer nodig in geheimen.
GCP GKE-implementatie
GKE gebruikt Persistent Disk (pd-ssd) voor opslag en GCS voor pgBackRest-back-ups. GKE Workload Identity wijst Kubernetes-serviceaccounts toe aan Google Cloud-serviceaccounts voor veilige, sleutelloze authenticatie.
# StorageClass for GKE SSD Persistent Disk
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: pd-ssd
provisioner: pd.csi.storage.gke.io
parameters:
type: pd-ssd
volumeBindingMode: WaitForFirstConsumer
allowVolumeExpansion: true
---
# pgBackRest with GCS
backups:
pgbackrest:
configuration:
- secret:
name: pgbackrest-gcs-creds
repos:
- name: repo1
gcs:
bucket: mycompany-pg-backups
---
# GCS service account key secret
apiVersion: v1
kind: Secret
metadata:
name: pgbackrest-gcs-creds
namespace: databases
stringData:
gcs-key.json: |
{
"type": "service_account",
"project_id": "my-project",
...
}# Enable Workload Identity on GKE
gcloud container clusters update my-cluster \
--workload-pool=my-project.svc.id.goog
# Create and bind IAM service account
gcloud iam service-accounts create pgbackrest-gcs \
--display-name="pgBackRest GCS Access"
gcloud projects add-iam-policy-binding my-project \
--member="serviceAccount:pgbackrest-gcs@my-project.iam.gserviceaccount.com" \
--role="roles/storage.objectAdmin"
gcloud iam service-accounts add-iam-policy-binding \
pgbackrest-gcs@my-project.iam.gserviceaccount.com \
--role="roles/iam.workloadIdentityUser" \
--member="serviceAccount:my-project.svc.id.goog[databases/production-db-pgbackrest]"Noodherstel in meerdere regio's
PGO ondersteunt stand-byclusters voor noodherstel over meerdere regio's. Een standby-cluster herhaalt WAL voortdurend vanuit de pgBackRest-repository van het primaire cluster, waarbij een warme kopie wordt onderhouden die kan worden gepromoveerd tot een onafhankelijke primaire cluster in het geval van een regionale storing.
# Standby cluster in Region B
apiVersion: postgres-operator.crunchydata.com/v1beta1
kind: PostgresCluster
metadata:
name: production-db-standby
namespace: databases
spec:
postgresVersion: 16
image: registry.crunchydata.com/crunchydata/crunchy-postgres:ubi8-16.6-1
standby:
enabled: true
repoName: repo1
instances:
- name: pgha1
replicas: 2
dataVolumeClaimSpec:
storageClassName: gp3-csi
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 100Gi
backups:
pgbackrest:
image: registry.crunchydata.com/crunchydata/crunchy-pgbackrest:ubi8-2.54.1-0
configuration:
- secret:
name: pgbackrest-s3-creds
repos:
- name: repo1
s3:
bucket: mycompany-pg-backups
endpoint: s3.us-east-1.amazonaws.com
region: us-east-1Om het standby-cluster tijdens een ramp te promoten, stelt ustandby.enabled: falsein de specificatie in en past u de wijziging toe. PGO promoot de stand-by naar een onafhankelijk primair cluster. Deze promotie is onomkeerbaar: u moet de replicatierelatie helemaal opnieuw opbouwen nadat de oorspronkelijke primaire regio is hersteld.
Bare Metal k3s/Rancher-implementatie
Het uitvoeren van PGO op bare metal k3s met Rancher-beheer vereist zorgvuldige aandacht voor opslag en netwerken, omdat u niet over door de cloudprovider beheerde schijven of load balancers beschikt.
Longhorn-opslag
Longhorn is een lichtgewicht, gedistribueerd blokopslagsysteem voor Kubernetes dat ideaal is voor bare metal-omgevingen. Het repliceert volumes over meerdere knooppunten voor duurzaamheid en ondersteunt snapshots, back-ups en volume-uitbreiding.
# Install Longhorn via Helm
helm repo add longhorn https://charts.longhorn.io
helm repo update
helm install longhorn longhorn/longhorn \
--namespace longhorn-system \
--create-namespace \
--set defaultSettings.defaultReplicaCount=3 \
--set defaultSettings.storageOverProvisioningPercentage=100 \
--set defaultSettings.storageMinimalAvailablePercentage=15
---
# Longhorn StorageClass for PostgreSQL
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: longhorn-pg
provisioner: driver.longhorn.io
parameters:
numberOfReplicas: "3"
staleReplicaTimeout: "2880"
fsType: ext4
dataLocality: best-effort
volumeBindingMode: WaitForFirstConsumer
allowVolumeExpansion: true
reclaimPolicy: RetainMetalLB voor taakverdeling
# Install MetalLB
helm repo add metallb https://metallb.github.io/metallb
helm install metallb metallb/metallb --namespace metallb-system --create-namespace
---
# Configure IP address pool
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: pg-pool
namespace: metallb-system
spec:
addresses:
- 192.168.1.200-192.168.1.210
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: pg-l2
namespace: metallb-system
spec:
ipAddressPools:
- pg-poolAls MetalLB is geconfigureerd, ontvangen de services van PGO van het typeLoadBalancerIP-adressen van uw pool, waardoor de PostgreSQL primaire en PgBouncer-eindpunten rechtstreeks bereikbaar zijn vanaf uw netwerk zonder handmatige port forwarding.
pgBackRest met lokale PVC of NFS voor Bare Metal
# For environments without S3/GCS/Azure Blob, use a PVC-based repo
backups:
pgbackrest:
repos:
- name: repo1
schedules:
full: "0 2 * * 0"
differential: "0 2 * * 1-6"
volume:
volumeClaimSpec:
storageClassName: longhorn-pg
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 200GiVoor air-gapped omgevingen kunt u ook een secundaire pgBackRest-repository configureren die back-ups verzendt naar een NFS-share of een MinIO-instantie die on-premises draait, waardoor een back-upkopie buiten het cluster wordt geleverd zonder afhankelijkheden van de cloud.
TLS/SSL Coderingsconfiguratie
PGO genereert standaard zelfondertekende TLS-certificaten voor alle interne communicatie - PostgreSQL-instanties, replicatie, pgBackRest en PgBouncer communiceren allemaal via gecodeerde kanalen zonder enig handmatig certificaatbeheer. Voor productieomgevingen wilt u echter doorgaans certificaten gebruiken die zijn ondertekend door de CA van uw organisatie.
# Create a TLS secret with your CA-signed certificates
kubectl create secret tls production-db-tls \
--cert=server.crt \
--key=server.key \
-n databases
kubectl create secret generic production-db-ca \
--from-file=ca.crt=ca.crt \
-n databases
---
# Reference in PostgresCluster spec
spec:
customTLSSecret:
name: production-db-tls
customReplicationTLSSecret:
name: production-db-replication-tlsPGO configureert PostgreSQL metssl = onen stelt de juistessl_cert_file-,ssl_key_file- enssl_ca_file-parameters in. PgBouncer is op dezelfde manier geconfigureerd om TLS te vereisen voor clientverbindingen en om TLS te gebruiken bij het verbinden met PostgreSQL-backends.
# Enforce TLS for all client connections via pg_hba.conf
spec:
patroni:
dynamicConfiguration:
postgresql:
pg_hba:
- hostssl all all 0.0.0.0/0 scram-sha-256
- hostssl replication all 0.0.0.0/0 scram-sha-256Aangepaste PostgreSQL-configuratie
PGO maakt de PostgreSQL-configuratie zichtbaar via de dynamische configuratiesectie van Patroni. Dit is de aanbevolen aanpak omdat Patroni ervoor zorgt dat alle instances een consistente configuratie behouden en indien nodig opnieuw opstarten afhandelt.
patroni:
dynamicConfiguration:
postgresql:
parameters:
# Memory
shared_buffers: 4GB
effective_cache_size: 12GB
work_mem: 64MB
maintenance_work_mem: 1GB
huge_pages: "try"
# WAL
wal_buffers: 128MB
min_wal_size: 2GB
max_wal_size: 8GB
checkpoint_completion_target: 0.9
wal_compression: lz4
# Query Planning
random_page_cost: 1.1
effective_io_concurrency: 200
default_statistics_target: 200
# Parallelism
max_worker_processes: 16
max_parallel_workers_per_gather: 4
max_parallel_workers: 8
max_parallel_maintenance_workers: 4
# Connections
max_connections: 200
idle_in_transaction_session_timeout: 60000
statement_timeout: 300000
# Logging
log_min_duration_statement: 250
log_checkpoints: "on"
log_connections: "on"
log_disconnections: "on"
log_lock_waits: "on"
log_temp_files: 0
log_autovacuum_min_duration: 0
# Autovacuum Tuning
autovacuum_max_workers: 5
autovacuum_naptime: 30
autovacuum_vacuum_cost_limit: 800
autovacuum_vacuum_scale_factor: 0.02
autovacuum_analyze_scale_factor: 0.01Deze parameters gaan uit van een knooppunt met 16 CPU-kernen en 32 GB RAM speciaal voor PostgreSQL. Passhared_buffersaan tot ongeveer 25% van het beschikbare RAM eneffective_cache_sizetot ongeveer 75%. De WAL- en checkpoint-instellingen zijn afgestemd op schrijfintensieve werklasten - vermindermax_wal_sizevoor leesintensieve systemen waarbij de checkpoint-frequentie er minder toe doet.
Gebruikers- en databasebeheer
PGO beheert PostgreSQL-gebruikers en databases declaratief via deusers-sectie van dePostgresCluster-specificatie. Wanneer u een gebruiker toevoegt, creëert PGO de rol in PostgreSQL, genereert een willekeurig wachtwoord en slaat de inloggegevens op in een Kubernetes Secret.
users:
- name: appuser
databases: ["appdb"]
options: "NOSUPERUSER NOCREATEDB NOCREATEROLE"
- name: readonly
databases: ["appdb"]
options: "NOSUPERUSER NOCREATEDB NOCREATEROLE"
- name: migrations
databases: ["appdb"]
options: "NOSUPERUSER CREATEDB"
- name: monitoring
databases: ["postgres"]
options: "NOSUPERUSER LOGIN"
---
# Access credentials from the generated secret
kubectl get secret production-db-pguser-appuser -n databases -o jsonpath='{.data.password}' | base64 -d
# The secret also contains a full connection URI
kubectl get secret production-db-pguser-appuser -n databases -o jsonpath='{.data.uri}' | base64 -d
# postgresql://appuser:PASSWORD@production-db-primary.databases.svc:5432/appdbVoor het verlenen van alleen-lezen toegang gebruikt u de functiedatabaseInitSQLom SQL uit te voeren bij het maken van een cluster, waardoor een alleen-lezen rol wordt gemaakt en deze SELECT wordt toegekend aan alle tabellen.
# init.sql ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
name: init-sql-configmap
namespace: databases
data:
init.sql: |
-- Read-only role for reporting users
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO readonly;
GRANT CONNECT ON DATABASE appdb TO readonly;
GRANT USAGE ON SCHEMA public TO readonly;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO readonly;
-- Extensions
CREATE EXTENSION IF NOT EXISTS pg_stat_statements;
CREATE EXTENSION IF NOT EXISTS pgcrypto;
CREATE EXTENSION IF NOT EXISTS pg_trgm;Rolling Updates en belangrijke versie-upgrades
PGO verwerkt kleine versie-upgrades via rolling updates. Wanneer u de afbeeldingstag in dePostgresCluster-specificatie wijzigt naar een nieuwere patchrelease, werkt PGO de instances één voor één bij, beginnend met replica's en eindigend met de primaire (die een Patroni-omschakeling activeert om de downtime te minimaliseren).
# Minor version upgrade: change the image tag
spec:
image: registry.crunchydata.com/crunchydata/crunchy-postgres:ubi8-16.7-0Grote versie-upgrades (bijvoorbeeld PostgreSQL 15 tot 16) vereisenpg_upgrade, die PGO orkestreert via een afzonderlijkePGUpgradeCRD.
apiVersion: postgres-operator.crunchydata.com/v1beta1
kind: PGUpgrade
metadata:
name: production-db-upgrade
namespace: databases
spec:
postgresClusterName: production-db
fromPostgresVersion: 15
toPostgresVersion: 16
image: registry.crunchydata.com/crunchydata/crunchy-upgrade:ubi8-5.7.2-0Het upgradeproces sluit het bestaande cluster af, voertpg_upgrade --linkuit om een interne upgrade uit te voeren met behulp van harde links (waardoor het kopiëren van gegevens wordt geminimaliseerd), verifieert de upgrade en start het cluster op de nieuwe versie. Maak altijd een volledige back-up voordat u een grote versie-upgrade start en test de procedure eerst op een niet-productiecluster.
# Pre-upgrade checklist
# 1. Take a full backup
kubectl annotate postgrescluster production-db -n databases \
postgres-operator.crunchydata.com/pgbackrest-backup="$(date +%s)" \
--overwrite
# 2. Verify backup completed
kubectl exec -it production-db-pgha1-0 -n databases -- pgbackrest info --stanza=db
# 3. Shutdown the cluster (set replicas to 0 or use PGO shutdown annotation)
kubectl annotate postgrescluster production-db -n databases \
postgres-operator.crunchydata.com/shutdown="$(date +%s)" \
--overwrite
# 4. Apply the PGUpgrade resource
kubectl apply -f pg-upgrade.yaml
# 5. Update the PostgresCluster spec with the new version and image
# 6. Remove the shutdown annotation to start the upgraded clusterAanbevelingen voor productietuning
Het uitvoeren van PGO in productie vereist aandacht voor verschillende operationele gebieden na de initiële implementatie.
Opslagprestaties
- Afzonderlijke data- en WAL-volumes: Gebruik altijd
walVolumeClaimSpecom WAL op een speciale PVC te plaatsen. Dit voorkomt dat WAL-activiteiten die veel schrijven vereisen, te maken krijgen met gegevens-I/O. - Gebruik hoge-IOPS-opslag: gp3 (AWS), Premium SSD v2 (Azure), pd-ssd (GCP) of NVMe-ondersteunde Longhorn op bare metal. De willekeurige I/O-patronen van PostgreSQL vereisen opslag met lage latentie.
- Volume-uitbreiding: Zorg ervoor dat uw StorageClass
allowVolumeExpansion: trueheeft. PGO kan PVC's ononderbroken uitbreiden op ondersteunde opslagproviders.
Pod-verstoringsbudgetten
PGO maakt automatisch PDB's voor uw PostgreSQL-instanties, maar controleert of ze geschikt zijn voor uw HA-vereisten.
# Check PDBs
kubectl get pdb -n databases
NAME MIN AVAILABLE MAX UNAVAILABLE ALLOWED DISRUPTIONS AGE
production-db-pgha1 1 N/A 2 7dBronverzoeken en limieten
- Stel geheugenverzoeken in die gelijk zijn aan de limieten voor database-pods om OOM-kills te voorkomen en een gegarandeerde QoS-klasse te garanderen.
- Stel CPU-verzoeken conservatief in en limieten hoger om barsten tijdens vacuüm- of onderhoudswerkzaamheden mogelijk te maken.
- Bewaak het daadwerkelijke gebruik via pgMonitor-statistieken en pas dit elk kwartaal aan.
Verbindingsbeheer
- Maak altijd verbinding via PgBouncer, niet rechtstreeks met PostgreSQL.
- Stel
max_connectionsin PostgreSQL in op een waarde die rekening houdt met de poolgrootte van PgBouncer plus systeemverbindingen (replicatie, monitoring, superuser). - Gebruik de transactiepoolingmodus voor webapplicaties. Schakel alleen over op sessiepooling als uw toepassing voorbereide instructies of een status op sessieniveau gebruikt (bijvoorbeeld
SET-opdrachten, tijdelijke tabellen).
Back-upvalidatie
- Test regelmatig herstelbewerkingen door een klooncluster te maken op basis van een back-up en rooktests op applicatieniveau uit te voeren.
- Controleer de
PgBackRestStaleBackup-waarschuwing om ervoor te zorgen dat back-ups op tijd worden voltooid. - Valideer PITR door specifieke tijdstempels te herstellen en de consistentie van gegevens te verifiëren.
# Clone cluster for backup validation
apiVersion: postgres-operator.crunchydata.com/v1beta1
kind: PostgresCluster
metadata:
name: backup-validation
namespace: databases
spec:
postgresVersion: 16
image: registry.crunchydata.com/crunchydata/crunchy-postgres:ubi8-16.6-1
dataSource:
postgresCluster:
clusterName: production-db
repoName: repo1
options:
- --type=time
- --target="2026-04-12 06:00:00+00"
instances:
- name: pgha1
replicas: 1
dataVolumeClaimSpec:
storageClassName: gp3-csi
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 100Gi
backups:
pgbackrest:
repos:
- name: repo1
volume:
volumeClaimSpec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 50GiNetwerkbeleid
# Restrict PostgreSQL traffic to known namespaces
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: postgres-network-policy
namespace: databases
spec:
podSelector:
matchLabels:
postgres-operator.crunchydata.com/cluster: production-db
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
app-access: database
- podSelector:
matchLabels:
postgres-operator.crunchydata.com/cluster: production-db
ports:
- port: 5432
protocol: TCP
- port: 9187
protocol: TCPControlechecklist
- Replicatievertraging: waarschuwing wanneer een replica 100 MB of 60 seconden vertraging overschrijdt.
- Verbindingsverzadiging: waarschuwing wanneer actieve verbindingen 80% van
max_connectionsoverschrijden. - Afwijkingen in transactiepercentages: Baselineer uw TPS en waarschuwt voor significante afwijkingen.
- Schijfgebruik: waarschuwing bij drempelwaarden van 70% en 85% bij runbooks voor volume-uitbreiding.
- Versheid van back-ups: Waarschuw wanneer de laatste volledige back-up ouder is dan uw RPO-venster.
- Vergrendelingsconflict: waarschuwing bij langdurige vergrendelingen (> 30 seconden) die kunnen duiden op applicatiefouten.
- Autovacuümgezondheid: waarschuwing wanneer tafels langer dan 24 uur niet zijn gestofzuigd.
Noodherstel-runbook
Een disaster recovery plan heeft alleen zin als het getest is. In het volgende runbook worden de belangrijkste procedures beschreven voor het herstellen van veelvoorkomende foutscenario's.
Fout bij enkele pod
Patroni en Kubernetes handelen dit automatisch af. Als de primaire pod crasht, promoot Patroni binnen 10-30 seconden een replica. Kubernetes start de mislukte pod opnieuw op, die weer wordt samengevoegd als een replica.
Fout bij één knooppunt
Als een knooppunt waarop een PostgreSQL-pod draait, sterft, plant Kubernetes de pod opnieuw op een gezond knooppunt. De pod wordt aangesloten op de bestaande PVC (als de opslag op het netwerk is aangesloten) of wordt hersteld vanaf een back-up (als er lokale opslag is gebruikt). Pod-anti-affiniteitsregels zorgen ervoor dat de resterende instanties verkeer blijven bedienen.
Volledig clusterverlies
Als het volledige Kubernetes-cluster verloren gaat, implementeer dan een nieuw cluster, installeer PGO en maak een nieuwePostgresClustermet eendataSourcedie naar de back-uprepository verwijst. PGO herstelt de laatste back-up en speelt WAL af naar het meest recente beschikbare punt.
Regionale failover
Als de primaire regio verloren gaat, promoveert u het stand-bycluster doorstandby.enabled: falsein te stellen. Update uw DNS of load balancer zodat deze naar de nieuwe primaire regio verwijst. Zodra de oorspronkelijke regio is hersteld, kunt u de stand-byrelatie in omgekeerde volgorde opnieuw opbouwen.
# Promote standby cluster
kubectl patch postgrescluster production-db-standby -n databases --type merge \
-p '{"spec":{"standby":{"enabled":false}}}'
# Verify the cluster is now an independent primary
kubectl exec -it production-db-standby-pgha1-0 -n databases -- patronictl listOperationele commando's Beknopte referentie
# Cluster status
kubectl get postgrescluster -n databases
kubectl describe postgrescluster production-db -n databases
# Patroni status
kubectl exec -it production-db-pgha1-0 -n databases -- patronictl list
kubectl exec -it production-db-pgha1-0 -n databases -- patronictl history
# Connect to PostgreSQL
kubectl exec -it production-db-pgha1-0 -n databases -- psql -U postgres
# Backup info
kubectl exec -it production-db-pgha1-0 -n databases -- pgbackrest info --stanza=db
# Manual backup
kubectl annotate postgrescluster production-db -n databases \
postgres-operator.crunchydata.com/pgbackrest-backup="$(date +%s)" --overwrite
# Restart PostgreSQL (rolling)
kubectl annotate postgrescluster production-db -n databases \
postgres-operator.crunchydata.com/restart="$(date +%s)" --overwrite
# Logs
kubectl logs production-db-pgha1-0 -n databases -c database
kubectl logs production-db-pgha1-0 -n databases -c pgbackrest
kubectl logs production-db-pgha1-0 -n databases -c exporter
# PgBouncer status
kubectl exec -it $(kubectl get pod -l postgres-operator.crunchydata.com/role=pgbouncer -n databases -o name | head -1) -n databases -- psql -U pgbouncer pgbouncer -c "SHOW POOLS;"
# Scale replicas
kubectl patch postgrescluster production-db -n databases --type merge \
-p '{"spec":{"instances":[{"name":"pgha1","replicas":5}]}}'Conclusie
Crunchy Data PGO transformeert PostgreSQL op Kubernetes van een operationele last in een beheersbaar, declaratief systeem. DePostgresClusterCRD legt de volledige implementatie vast – instances, replicatie, back-up, pooling, monitoring, TLS – in één versiegestuurde bron. Patroni biedt beproefde automatische failover. pgBackRest levert back-ups op bedrijfsniveau met herstel op een bepaald tijdstip naar elke objectopslag in de cloud. PgBouncer verzorgt de pooling van verbindingen die het proces-per-verbindingsmodel van PostgreSQL op schaal vereist. En pgMonitor voert de statistieken die u nodig heeft in Prometheus en Grafana in voor operationeel inzicht.
De implementatiepatronen voor AWS EKS, Azure AKS, GCP GKE en bare metal k3s delen dezelfde kernspecificaties voor dePostgresCluster. Wat verandert is de opslagklasse, de configuratie van de back-uprepository en de netwerklaag. Deze consistentie is de echte waarde van een operatorgebaseerde aanpak: uw team leert één tool, één operationeel model en één set runbooks die overal werken.
Begin met een cluster met drie exemplaren, PgBouncer in transactiepoolingmodus, een wekelijks volledig plus dagelijks differentieel back-upschema en de kern Prometheus-waarschuwingen. Valideer uw back-upherstelprocedure op de eerste dag, niet wanneer u deze voor het eerst nodig heeft. Breid uit naar stand-byclusters met meerdere regio's, synchrone replicatie en geavanceerde afstemming naarmate uw beschikbaarheidsvereisten en operationele volwassenheid toenemen. De operator verzorgt de monteurs; het is uw verantwoordelijkheid om de architectuur goed genoeg te begrijpen om de juiste afwegingen te maken voor uw werklast.