Workstation Logo
Producten
AI LabsOpenAI AgentsClaude AgentsGrok BotWorkstation CRM (WSL CRM)MarketingAlle Producten
AI-Oplossingen
AI-WerkstationsAI SME PackagesPrivé AIGPU-ClustersEdge AIEnterprise AI LabAI per Industrie
Diensten
PlatformmoderniseringDigitale engineeringDatafundamenten & AIAutonome operatiesAI-adviesDevOps-automatiseringCybersecuritySoftwareontwikkelingAgentontwikkelingMLOps-opzet
Over Ons
PartnersKlantverhalen
Artikelen
Documentatie
WSL ProxyRing PromoterWSL VaultJobshoutSysOps 24/7
Blog
ContactLogin
Workstation

AI-werkstations, AI multi-agent software, GPU-infrastructuur en intelligente agentoplossingen voor moderne bedrijven.

Contact

AI-oplossingen

AI-WerkstationsAI SME PackagesPrivé AIGPU-ClustersEdge AIEnterprise AI LabAI per Industrie

Producten

Alle ProductenWSL CRM & ERPMarketingOpenAI AgentsWSL ProxyRing PromoterWSL VaultJobshoutSysOps 24/7

Bedrijf

Over OnsWaarom WorkstationPartnersKlantverhalenPrijzenContact

Bronnen

ArtikelenDocumentatieBlogZoekenSitemap
UK-kantoor
77-79 Marlowes, Hemel Hempstead HP1 1LFRoute: neem afrit 20 van de M25, Outer LondonBedrijfsnummer: 11641870Ma - Vr: 9:00 - 18:00 GMT
+44 7515 356 146
België-kantoor
Workstation SRL, Rue Vanderkindere 34, 1180 Uccle, BrusselsBE 0751.518.683Ma - Vr: 9:00 - 18:00 CET
+32 492 45 67 46
India-kantoor
#159 Sector 9, Pocket 1, DDA Flats, 110077 Dwarka, New Delhi
+91 98881 98841

© 2026 Workstation AI. Alle rechten voorbehouden.

PrivacyCookiesServicevoorwaardenWebsite-sitemap

Loading blog...

Home / Blog
DatabaseKubernetesDevOpsBackend

PostgreSQL Hoge beschikbaarheid met Zalando Postgres Operator: Multi-Cloud Kubernetes implementatiehandleiding

Implementeer PostgreSQL HA van productiekwaliteit met Zalando Operator op elk Kubernetes-platform

Balinder Walia12 april 202625 min read

Introductie: waarom PostgreSQL hoge beschikbaarheid op Kubernetes belangrijk is voor

Het draaien van PostgreSQL in productie vereist een hoge beschikbaarheid (HA). Downtime, gemeten in minuten, kan bedrijven miljoenen dollars aan omzetverlies kosten, het vertrouwen van klanten ondermijnen en overeenkomsten inzake serviceniveau schenden. Kubernetes is het de facto platform geworden voor het orkestreren van gecontaineriseerde workloads, maar het uitvoeren van stateful services zoals PostgreSQL op Kubernetes brengt unieke uitdagingen met zich mee: persistent opslagbeheer, verkiezing van leiders, automatische failover, back-uporkestratie en pooling van verbindingen.

DeZalando Postgres Operatoris een open-source, beproefde oplossing die Zalando, Europa's grootste online moderetailer, heeft gebouwd om honderden PostgreSQL-clusters in productie te beheren. Het maakt gebruik vanPatronivoor op consensus gebaseerde verkiezing van leiders,Spiloals de PostgreSQL-containerimage,WAL-Gvoor continue archivering en herstel op een bepaald tijdstip, enPgBouncervoor het poolen van verbindingen. Samen leveren deze componenten een volledig geautomatiseerde, zelfherstellende PostgreSQL-implementatie die werkt in elke Kubernetes-distributie: van beheerde cloudservices zoals AWS EKS, Azure AKS en Google GKE tot bare-metal clusters met k3s met Rancher.

In deze uitgebreide gids verkennen we de architectuur van de Zalando Postgres Operator, lopen we door de installatie en configuratie op meerdere Kubernetes-platforms, duiken we diep in replicatie, back-ups, noodherstel, monitoring en productie-afstemming. Aan het einde beschikt u over de kennis om PostgreSQL HA-clusters van productiekwaliteit te implementeren en te bedienen op elke Kubernetes-infrastructuur.

Zalando Postgres Operatorarchitectuur

Het begrijpen van de architectuur is essentieel voordat u het implementeert. De Zalando Postgres Operator volgt het Kubernetes-operatorpatroon: hij let op Custom Resource Definitions (CRDs) van het typepostgresqlen stemt de gewenste status af op daadwerkelijke Kubernetes-bronnen. Hier ziet u hoe de componenten in elkaar passen:

Zalando Postgres OperatorarchitectuurPostgreSQL CRD-type: postgresqlPostgres-operatorHorloges & VerzoentStatefulSetBeheert de levenscyclus van de podPrimaire podSpilo (PostgreSQL)Patroni-agentReplicapod 1Spilo (PostgreSQL)Patroni-agentReplicapod 2Spilo (PostgreSQL)Patroni-agentPatroni DCS (Kubernetes API)Leiderverkiezing & ClusterstatusPgBouncerVerbindingspoolingWAL-GBack-ups naar S3/GCS/AzurePrimaireReplicaConsensus/DCSBack-upVerbindingspool

Spilo: de PostgreSQL-containerafbeelding

Spilois Zalando's Docker-image die PostgreSQL bundelt met Patroni, WAL-G en essentiële extensies. Elke pod in de StatefulSet voert een Spilo-container uit. Spilohandvatten:

  • PostgreSQL-server— de database-engine zelf, die versies 13 tot en met 16
  • ondersteunt
  • Patroni— de HA-agent die de verkiezing, replicatie en failover van leiders beheert
  • WAL-G— continue WAL-archiverings- en basisback-uptool
  • pg_cron, pg_stat_statements, PostGIS— veelgebruikte extensies vooraf geïnstalleerd

Patroni: Leiderverkiezing en automatische failover

Patroni is het hart van het HA-mechanisme. Het maakt gebruik van een Distributed Configuration Store (DCS) om de clusterstatus te behouden en leidersverkiezingen uit te voeren. In de Zalando-operatorcontext gebruikt Patroni deKubernetes APIzelf als DCS (via Endpoints of ConfigMaps), waardoor er geen externe etcd- of ZooKeeper-cluster nodig is.

Hier ziet u hoe Patroni's failover-proces werkt:

  1. Gezondheidscontroles— Elke Patroni-agent bewaakt voortdurend zijn lokale PostgreSQL-instantie en rapporteert de status aan de DCS.
  2. Leader lock— De primaire bevat een leader lock in de DCS (een Kubernetes Endpoint-object). Het slot heeft een TTL (standaard 30 seconden).
  3. Foutdetectie— Als de primaire er niet in slaagt zijn vergrendeling binnen de TTL te vernieuwen, detecteren replica's de afwezigheid.
  4. Verkiezing— In aanmerking komende replica's strijden om het leidersslot. De replica met de minste replicatievertraging wint.
  5. Promotie— De winnende replica promoveert zichzelf naar primair, werkt de DCS bij en het KubernetesmasterService-eindpunt wordt automatisch bijgewerkt.
  6. Schermen— De oude primaire is omheind (gestopt of gedegradeerd tot replica) om gespleten hersenen te voorkomen.

Dit volledige failover-proces wordt doorgaans voltooid in15-30 seconden, waardoor minimale downtime voor uw applicaties wordt gegarandeerd.

WAL-G: Continue archivering en back-up

WAL-G is een archieftool van de volgende generatie voor PostgreSQL die back-up naar S3, Google Cloud Storage (GCS) en Azure Blob Storage ondersteunt. Het biedt:

  • Basisback-ups— Volledige fysieke back-ups met behulp vanpg_basebackup
  • WAL-archivering— Continu vooruitschrijven van logboekverzending voor herstel op een bepaald tijdstip
  • Delta-back-ups— Incrementele back-ups die alleen gewijzigde pagina's opslaan
  • -codering— AES-256-codering van back-ups in rust
  • Compressie— LZ4- of ZSTD-compressie voor lagere opslagkosten

Kubernetes-bronhiërarchie

Wanneer u een aangepastepostgresql-resource maakt, maakt de operator een uitgebreide set Kubernetes-resources om het cluster te beheren. Het begrijpen van deze hiërarchie is belangrijk voor het oplossen van problemen en het monitoren:

Kubernetes-bronnenhiërarchie — Zalando-operatorpostgresql CRDPostgres-operatorStatefulSet-service(master)-service(replica)EindpuntenVOB-podsPVCsGeheimenPgBouncer ImplementeerService (pooler)PrimaireReplicaReplicaDoorgetrokken lijnen = directe creatie | Stippellijnen = voorwaardelijke creatie

-bronnen gemaakt door de operator

  • StatefulSet— Beheert de PostgreSQL-pods met stabiele netwerkidentiteiten en geordende implementatie
  • Services— Twee ClusterIP-services:<cluster-name>voor de primaire en<cluster-name>-replvoor leesreplica's
  • Eindpunten— Patroni werkt eindpunten bij zodat deze naar de huidige leider verwijzen voor een naadloze failover
  • PodDisruptionBudgets (PDB)— Zorgt ervoor dat ten minste één exemplaar beschikbaar blijft tijdens vrijwillige verstoringen
  • Secrets— PostgreSQL superuser-, replicatie- en applicatiereferenties opgeslagen als Kubernetes Secrets
  • PersistentVolumeClaims (PVCs)— Eén PVC per pod voor PostgreSQL gegevensopslag
  • PgBouncer-implementatie— Optionele verbindingspooler geïmplementeerd als een afzonderlijke implementatie met een eigen service

Installatie op meerdere Kubernetes-platforms

Vereisten

Zorg ervoor dat u beschikt over:

voordat u de Zalando Postgres Operator installeert
  • Een actief Kubernetes-cluster (v1.25+)
  • kubectlgeconfigureerd met clusterbeheerderstoegang
  • helmv3 heeft
  • geïnstalleerd
  • Een standaard StorageClass geconfigureerde

Operatorinstallatie via Helm

De aanbevolen installatiemethode maakt gebruik van Helm. Dit werkt consistent op alle Kubernetes-platforms:

# Add the Zalando Postgres Operator Helm repository
helm repo add postgres-operator-charts https://opensource.zalando.com/postgres-operator/charts/postgres-operator
helm repo add postgres-operator-ui-charts https://opensource.zalando.com/postgres-operator/charts/postgres-operator-ui
helm repo update

# Create a dedicated namespace
kubectl create namespace postgres-operator

# Install the operator with custom values
helm install postgres-operator postgres-operator-charts/postgres-operator \
  --namespace postgres-operator \
  --set configKubernetes.enable_pod_antiaffinity=true \
  --set configKubernetes.pod_environment_configmap=postgres-pod-config \
  --set configAwsOrGcp.aws_region=us-east-1 \
  --set configLoadBalancer.db_hosted_zone=db.example.com \
  --set configConnectionPooler.connection_pooler_default_cpu_request=500m \
  --set configConnectionPooler.connection_pooler_default_memory_request=100Mi

# Optionally install the operator UI for visual management
helm install postgres-operator-ui postgres-operator-ui-charts/postgres-operator-ui \
  --namespace postgres-operator

Controleer of de operator actief is:

kubectl get pods -n postgres-operator
# Expected output:
# NAME                                 READY   STATUS    RESTARTS   AGE
# postgres-operator-7f8b9c6d4-x2k9j   1/1     Running   0          2m

AWS EKS-implementatiespecificaties

Amazon EKS vereist specifieke configuratie voor optimale PostgreSQL-prestaties:

# EKS-specific Helm values (eks-values.yaml)
configAwsOrGcp:
  aws_region: us-east-1
  enable_ebs_gp3_migration: true
  additional_secret_mount: "aws-iam-token"

configKubernetes:
  enable_pod_antiaffinity: true
  pod_environment_configmap: "postgres-pod-config"
  spilo_privileged: false
  storage_resize_mode: pvc

# Use EBS gp3 StorageClass for better performance
# Create the StorageClass first:
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: ebs-gp3-postgres
provisioner: ebs.csi.aws.com
parameters:
  type: gp3
  iops: "6000"
  throughput: "400"
  encrypted: "true"
reclaimPolicy: Retain
volumeBindingMode: WaitForFirstConsumer
allowVolumeExpansion: true

Voor WAL-G-back-ups op EKS configureert u IAM-rollen voor serviceaccounts (IRSA):

# Create IAM policy for WAL-G S3 access
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:PutObject",
        "s3:GetObject",
        "s3:ListBucket",
        "s3:DeleteObject",
        "s3:GetBucketLocation"
      ],
      "Resource": [
        "arn:aws:s3:::my-pg-backups",
        "arn:aws:s3:::my-pg-backups/*"
      ]
    }
  ]
}

Azure AKS-implementatie

Azure AKS gebruikt Azure-schijf voor permanente opslag en beheerde identiteit voor back-upverificatie:

# AKS-specific StorageClass
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: managed-premium-postgres
provisioner: disk.csi.azure.com
parameters:
  skuName: Premium_LRS
  cachingMode: ReadOnly
reclaimPolicy: Retain
volumeBindingMode: WaitForFirstConsumer
allowVolumeExpansion: true
---
# WAL-G backup to Azure Blob Storage environment variables
apiVersion: v1
kind: ConfigMap
metadata:
  name: postgres-pod-config
  namespace: default
data:
  AZURE_STORAGE_ACCOUNT: "pgbackupsstorage"
  AZURE_STORAGE_ACCESS_KEY: "" # Use Managed Identity instead
  WALG_AZ_PREFIX: "azure://pg-wal-backups/$(SCOPE)"
  USE_WALG_BACKUP: "true"
  USE_WALG_RESTORE: "true"
  BACKUP_SCHEDULE: "0 2 * * *"
  BACKUP_NUM_TO_RETAIN: "7"

Google GKE-implementatie

Google Kubernetes Engine gebruikt Persistent Disk en Workload Identity voor GCS-back-uptoegang:

# GKE StorageClass for SSD Persistent Disks
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: ssd-postgres
provisioner: pd.csi.storage.gke.io
parameters:
  type: pd-ssd
reclaimPolicy: Retain
volumeBindingMode: WaitForFirstConsumer
allowVolumeExpansion: true
---
# GCS backup configuration
apiVersion: v1
kind: ConfigMap
metadata:
  name: postgres-pod-config
  namespace: default
data:
  WALG_GS_PREFIX: "gs://my-pg-backups/$(SCOPE)"
  USE_WALG_BACKUP: "true"
  USE_WALG_RESTORE: "true"
  GOOGLE_APPLICATION_CREDENTIALS: "/var/secrets/google/key.json"
  BACKUP_SCHEDULE: "0 2 * * *"
  BACKUP_NUM_TO_RETAIN: "7"

Blank metaal k3s/Rancher met Longhorn-opslag

Voor implementaties op locatie biedt k3s een lichtgewicht Kubernetes-distributie en Longhorn biedt gedistribueerde blokopslag. Deze combinatie is ideaal wanneer u volledige controle over uw infrastructuur nodig heeft zonder dat u gebonden bent aan een cloudleverancier.

# Install k3s on all nodes
# Master node:
curl -sfL https://get.k3s.io | sh -s - server \
  --cluster-init \
  --disable traefik \
  --write-kubeconfig-mode 644

# Worker nodes:
curl -sfL https://get.k3s.io | sh -s - agent \
  --server https://master-ip:6443 \
  --token $(cat /var/lib/rancher/k3s/server/node-token)

# Install Longhorn for persistent storage
helm repo add longhorn https://charts.longhorn.io
helm install longhorn longhorn/longhorn \
  --namespace longhorn-system \
  --create-namespace \
  --set defaultSettings.defaultReplicaCount=3 \
  --set defaultSettings.defaultDataPath=/mnt/longhorn

# Install MetalLB for LoadBalancer services
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.14.5/config/manifests/metallb-native.yaml

# Configure MetalLB IP pool
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: postgres-pool
  namespace: metallb-system
spec:
  addresses:
  - 192.168.1.200-192.168.1.210
k3s / Rancher Bare Metal-implementatieRancher-beheerserverKnooppunt 1 (k3s-server)PostgreSQL PrimaireSpilo + PatroniZalando-operatorPgBouncer-poolLanghoornvolume/mnt/longhorn (3 replica's)Knooppunt 2 (k3s-server)PostgreSQL-replicaSpilo + PatroniPgBouncer-poolPrometheus ExporteurLanghoornvolume/mnt/longhorn (3 replica's)Knooppunt 3 (k3s-agent)PostgreSQL-replicaSpilo + PatroniPgBouncer-poolGrafana DashboardLanghoornvolume/mnt/longhorn (3 replica's)HAProxy / MetalLB LoadBalancerWAL-G Back-upsNFS / MinIO S3-compatibelePrimaireReplicaPgBouncerLanghoornStreamingreplicatie

PostgreSQL Cluster CRD Specificatie

De kern van het inzetten van een PostgreSQL-cluster met de Zalando-operator is depostgresqlCustom Resource. Dit YAML-manifest geeft de gewenste status van uw cluster aan, en de operator stemt dit af met de realiteit. Hieronder vindt u een uitgebreide, productieklare CRD-specificatie:

apiVersion: acid.zalan.do/v1
kind: postgresql
metadata:
  name: pg-production-cluster
  namespace: databases
  labels:
    team: platform
    environment: production
spec:
  teamId: "platform"
  volume:
    size: 100Gi
    storageClass: ebs-gp3-postgres
  numberOfInstances: 3
  enableConnectionPooler: true
  enableReplicaConnectionPooler: true
  connectionPooler:
    numberOfInstances: 2
    mode: transaction
    schema: pooler
    user: pooler
    resources:
      requests:
        cpu: 500m
        memory: 100Mi
      limits:
        cpu: "1"
        memory: 256Mi
  users:
    app_user:
    - superuser
    - createdb
    readonly_user: []
  databases:
    app_database: app_user
  postgresql:
    version: "16"
    parameters:
      shared_buffers: "2GB"
      max_connections: "200"
      work_mem: "64MB"
      maintenance_work_mem: "512MB"
      effective_cache_size: "6GB"
      random_page_cost: "1.1"
      effective_io_concurrency: "200"
      wal_buffers: "64MB"
      max_wal_size: "4GB"
      min_wal_size: "1GB"
      checkpoint_completion_target: "0.9"
      default_statistics_target: "100"
      log_statement: "ddl"
      log_min_duration_statement: "1000"
      idle_in_transaction_session_timeout: "600000"
      lock_timeout: "30000"
      statement_timeout: "60000"
  patroni:
    initdb:
      encoding: "UTF8"
      locale: "en_US.UTF-8"
      data-checksums: "true"
    pg_hba:
    - hostssl all all 0.0.0.0/0 md5
    - host    all all 0.0.0.0/0 md5
    ttl: 30
    loop_wait: 10
    retry_timeout: 10
    synchronous_mode: false
    synchronous_mode_strict: false
    maximum_lag_on_failover: 33554432
  resources:
    requests:
      cpu: "2"
      memory: 8Gi
    limits:
      cpu: "4"
      memory: 16Gi
  podAnnotations:
    prometheus.io/scrape: "true"
    prometheus.io/port: "9187"
  tolerations:
  - key: "database"
    operator: "Equal"
    value: "postgres"
    effect: "NoSchedule"
  nodeAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
      nodeSelectorTerms:
      - matchExpressions:
        - key: workload-type
          operator: In
          values:
          - database
  enableShmVolume: true
  spiloRunAsUser: 101
  spiloRunAsGroup: 103
  spiloFSGroup: 103

-sleutel CRD-velden uitgelegd

  • numberOfInstances— Totaal aantal peulen. De operator wijst er automatisch één aan als primair en de rest als streaming-replica's.
  • enableConnectionPooler— Implementeert PgBouncer zijspan voor de primaire service, waardoor de verbindingsoverhead wordt verminderd.
  • enableReplicaConnectionPooler— Implementeert een afzonderlijke PgBouncer voor de replicaservice, essentieel voor leesintensieve werklasten.
  • postgresql.parameters— Directe PostgreSQL-configuratieparameters doorgegeven aanpostgresql.conf.
  • patroni— Configureert Patroni-gedrag inclusief TTL, luswachttijd, time-out voor opnieuw proberen en synchrone replicatiemodus.
  • volume.storageClass— Wordt toegewezen aan de platformspecifieke StorageClass (EBS gp3 op AWS, Premium SSD op Azure, SSD PD op GCP, Longhorn op k3s).
  • enableShmVolume— Mounts eentmpfsop/dev/shmvoor PostgreSQL gedeeld geheugen, cruciaal voor prestaties.

Verbindingspooling met PgBouncer

Het proces-per-verbindingsmodel van de PostgreSQL maakt het duur om grote aantallen clientverbindingen te verwerken. Elke verbinding verbruikt ongeveer 10 MB RAM. PgBouncer lost dit op door duizenden clientverbindingen te multiplexen over een kleine pool van daadwerkelijke PostgreSQL-verbindingen.

De Zalando-operator ondersteunt standaard de implementatie van PgBouncer. Wanneer uenableConnectionPooler: truein de CRD instelt, maakt de operator:

  • Een PgBouncer-implementatie met configureerbaar aantal replica's
  • Een speciale service (<cluster-name>-pooler) voor gepoolde verbindingen
  • Automatische identificatiesynchronisatie met PostgreSQL

PgBouncer-configuratiemodi

# PgBouncer connection pooler modes:
#
# transaction (recommended for most workloads)
#   - Connection returned to pool after each transaction
#   - Best balance of efficiency and compatibility
#   - Cannot use session-level features (prepared statements, temp tables)
#
# session
#   - Connection held for entire client session
#   - Full PostgreSQL compatibility
#   - Lower pooling efficiency
#
# statement
#   - Connection returned after each statement
#   - Most efficient but most restrictive
#   - Only works with autocommit queries

# Custom PgBouncer configuration via operator
spec:
  connectionPooler:
    numberOfInstances: 3
    mode: transaction
    schema: pooler
    user: pooler
    defaultPoolSize: 25
    maxDBConnections: 100
    resources:
      requests:
        cpu: 250m
        memory: 128Mi
      limits:
        cpu: "1"
        memory: 256Mi

Voor toepassingen die voorbereide instructies of functies op sessieniveau nodig hebben, kunt u rechtstreeks verbinding maken met de PostgreSQL-services en PgBouncer omzeilen, of desession-poolingmodus gebruiken met als wisselwerking een lagere verbindingsefficiëntie.

PostgreSQL-replicatie voor meerdere regio's

Voor mondiale toepassingen die leesbewerkingen met lage latentie vanaf meerdere geografische locaties of noodherstel tussen regio's vereisen, is replicatie in meerdere regio's essentieel. De Zalando-operator ondersteunt dit via standby-clusters die repliceren vanuit een primair cluster via streaming-replicatie of WAL-G-archieven.

PostgreSQL streamingreplicatie voor meerdere regio'sUS-OOST-1 (AWS EKS)PRIMAIRE CLUSTERpg-prod-us (3 pods)PrimaireReplicaSynchronisatiereplicatie binnen AZWAL-G → S3 (continu)PgBouncer PoolerEU-WEST-1 (Azure AKS)STANDBY-CLUSTERpg-standby-eu (2 pods)Stand-byReplicaCascading-replicatieWAL-G → Azure BlobPgBouncer (alleen-lezen)AP-ZUIDOOST (GCP GKE)STANDBY-CLUSTERpg-standby-ap (2 pods)Stand-byReplicaCascading-replicatieWAL-G → GCS-bakPgBouncer (alleen-lezen)ASYNCASYNC (WAL-verzending)ReplicatietopologiePrimair (VS-OOST) → Asynchrone streaming naar EU-WEST & AP-SOUTHEAST standby-clusters | RPO: ~seconden | RTO: <5 min met handmatige promotieSynchronisatiereplicatieAsynchrone replicatiePrimaireStand-by leiderLeesreplica

Streamingreplicatieconfiguratie

PostgreSQL-streamingreplicatie vormt de basis van HA in de Zalando-operator. Het werkt door Write-Ahead Log (WAL)-records in bijna realtime van de primaire naar replica's te verzenden. De operator configureert dit automatisch, maar het begrijpen van de details helpt bij het afstemmen en oplossen van problemen.

  • Synchrone replicatie— De primaire wacht op ten minste één replica om de WAL-ontvangst te bevestigen voordat een transactie wordt vastgelegd. Dit garandeert geen gegevensverlies (RPO=0), maar voegt latentie toe. Inschakelen metpatroni.synchronous_mode: true.
  • Asynchrone replicatie— De primaire commit wordt onmiddellijk doorgevoerd en WAL asynchroon verzonden. Iets lagere latentie maar potentieel gegevensverlies tijdens failover. Dit is de standaardinstelling.
  • Trapsgewijze replicatie— Replica's kunnen repliceren vanaf andere replica's in plaats van de primaire, waardoor de belasting van de primaire in grote clusters wordt verminderd.
# Enable synchronous replication for zero data loss
spec:
  patroni:
    synchronous_mode: true
    synchronous_mode_strict: false  # Allow async if no sync replica available
    synchronous_node_count: 1       # Number of sync replicas required
  postgresql:
    parameters:
      synchronous_commit: "on"      # Matches Patroni synchronous_mode
      max_wal_senders: "10"         # Maximum WAL sender processes
      wal_keep_size: "1GB"          # WAL retention for replica catch-up
      hot_standby: "on"             # Allow queries on replicas
      hot_standby_feedback: "on"    # Reduce query conflicts on replicas

Back-up en herstel met WAL-G

WAL-G Back-upconfiguratie

Een juiste back-upconfiguratie is van cruciaal belang voor noodherstel. De Zalando-operator integreert WAL-G voor continue back-up naar objectopslag. Hier is een volledige configuratie voor S3-compatibele opslag:

# ConfigMap for WAL-G backup configuration
apiVersion: v1
kind: ConfigMap
metadata:
  name: postgres-pod-config
  namespace: databases
data:
  # S3 backup configuration
  AWS_ENDPOINT: "https://s3.us-east-1.amazonaws.com"
  AWS_S3_FORCE_PATH_STYLE: "false"
  AWS_REGION: "us-east-1"
  WALG_S3_PREFIX: "s3://my-pg-backups/$(SCOPE)"
  WALG_DISABLE_S3_SSE: "false"
  WALG_S3_SSE: "aws:kms"
  WALG_S3_SSE_KMS_ID: "arn:aws:kms:us-east-1:123456789:key/mrk-abcdef"

  # Backup scheduling and retention
  USE_WALG_BACKUP: "true"
  USE_WALG_RESTORE: "true"
  BACKUP_SCHEDULE: "0 1 * * *"       # Daily at 1 AM UTC
  BACKUP_NUM_TO_RETAIN: "14"          # Keep 14 daily backups

  # WAL archiving
  WALG_COMPRESSION_METHOD: "zstd"     # Better compression than lz4
  WALG_DELTA_MAX_STEPS: "6"           # Delta backups between full backups
  WALG_UPLOAD_CONCURRENCY: "4"        # Parallel upload streams
  WALG_DOWNLOAD_CONCURRENCY: "4"      # Parallel download for restore
  WALG_UPLOAD_DISK_CONCURRENCY: "4"   # Disk read concurrency

  # Clone configuration
  CLONE_AWS_ENDPOINT: "https://s3.us-east-1.amazonaws.com"
  CLONE_AWS_REGION: "us-east-1"
  CLONE_WALG_S3_PREFIX: "s3://my-pg-backups/$(CLONE_SCOPE)"
  CLONE_METHOD: "CLONE_WITH_WALG"
  CLONE_USE_WALG_RESTORE: "true"

Point-in-Time-herstel (PITR)

Met

PITR kunt u uw database op elk specifiek moment herstellen, wat van cruciaal belang is voor herstel na het per ongeluk verwijderen of beschadigen van gegevens. De Zalando-operator ondersteunt PITR via het kloonmechanisme:

# Clone a cluster with PITR
apiVersion: acid.zalan.do/v1
kind: postgresql
metadata:
  name: pg-restored-cluster
  namespace: databases
spec:
  teamId: "platform"
  volume:
    size: 100Gi
    storageClass: ebs-gp3-postgres
  numberOfInstances: 3
  postgresql:
    version: "16"
  clone:
    cluster: "pg-production-cluster"
    timestamp: "2026-04-11T14:30:00+00:00"  # Restore to this exact moment
    s3_wal_path: "s3://my-pg-backups/wal/16/pg-production-cluster"
    s3_endpoint: "https://s3.us-east-1.amazonaws.com"
    s3_access_key_id: ""      # Use IAM role instead
    s3_secret_access_key: ""  # Use IAM role instead

Wanneer deze CRD wordt toegepast, voert de operator de volgende stappen uit:

  1. Vindt de nieuwste basisback-up vóór de doeltijdstempel
  2. Herstelt de basisback-up naar de primaire pod
  3. van de nieuwe StatefulSet
  4. Speelt WAL-segmenten opnieuw af tot de opgegeven tijdstempel
  5. Opent de database voor lees-schrijfbewerkingen
  6. Stelt streaming-replicatie in op de replica-pods

Stand-bycluster voor noodherstel

Een stand-bycluster repliceert voortdurend vanuit een primair cluster, waardoor een warme stand-by wordt geboden die tijdens een ramp kan worden bevorderd. Dit verschilt van replica's binnen een cluster: een standby-cluster is een volledig onafhankelijke Kubernetes-bron die in een andere naamruimte, cluster of zelfs regio kan worden uitgevoerd.

# Standby cluster in a different region
apiVersion: acid.zalan.do/v1
kind: postgresql
metadata:
  name: pg-standby-eu
  namespace: databases
spec:
  teamId: "platform"
  volume:
    size: 100Gi
    storageClass: managed-premium-postgres
  numberOfInstances: 2
  postgresql:
    version: "16"
  standby:
    standby_host: "pg-production-cluster.databases.svc.cluster.local"
    standby_port: "5432"
    # Alternative: replicate from S3 WAL archive
    # s3_wal_path: "s3://my-pg-backups/wal/16/pg-production-cluster"
  enableConnectionPooler: true
  enableReplicaConnectionPooler: true

Om een standby-cluster te promoveren naar een onafhankelijke primaire cluster (tijdens noodherstel), verwijdert u eenvoudigweg destandby-sectie van de CRD en past u het volgende toe:

# Edit the standby cluster CRD to remove standby section
kubectl patch postgresql pg-standby-eu -n databases --type json \
  -p '[{"op": "remove", "path": "/spec/standby"}]'

# The operator will promote the standby to primary
# Update your application DNS/service mesh to point to the new primary

-bewaking met Prometheus en Grafana

Uitgebreide monitoring is niet onderhandelbaar voor productie-PostgreSQL-implementaties. De Zalando-operator ondersteunt de export van Prometheus-statistieken via depostgres_exporter-zijspan. Hier ziet u hoe u een complete monitoringstack instelt:

ServiceMonitor voor Prometheus

# ServiceMonitor for PostgreSQL metrics
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: postgres-monitor
  namespace: databases
  labels:
    team: platform
    release: prometheus
spec:
  selector:
    matchLabels:
      team: platform
  namespaceSelector:
    matchNames:
    - databases
  endpoints:
  - port: exporter
    interval: 15s
    scrapeTimeout: 10s
    path: /metrics
    relabelings:
    - sourceLabels: [__meta_kubernetes_pod_label_spilo_role]
      targetLabel: role
    - sourceLabels: [__meta_kubernetes_pod_label_cluster_name]
      targetLabel: cluster
---
# PodMonitor alternative (scrapes pods directly)
apiVersion: monitoring.coreos.com/v1
kind: PodMonitor
metadata:
  name: postgres-pod-monitor
  namespace: databases
spec:
  selector:
    matchLabels:
      application: spilo
  podMetricsEndpoints:
  - port: exporter
    interval: 15s
    path: /metrics

Belangrijke statistieken om

te monitoren

Dit zijn de meest kritische PostgreSQL-statistieken om bij te houden in uw Grafana-dashboards:

  • pg_stat_replication_lag— Replicatievertraging in bytes en seconden. Waarschuw als de vertraging uw RPO-drempel overschrijdt.
  • pg_stat_activity_count— Actieve verbindingen per staat. Waarschuwing bij uitputting van de verbindingspool.
  • pg_stat_database_tup_fetched/returned/inserted/updated/deleted— Querydoorvoerstatistieken.
  • pg_stat_bgwriter_buffers_checkpoint/clean/backend— Efficiëntie van bufferbeheer.
  • pg_database_size_bytes— Groei van databasegrootte in de loop van de tijd voor capaciteitsplanning.
  • pg_locks_count— Vergrendeling van conflicten. Waarschuw bij overmatige wachtsloten.
  • pg_stat_statements_calls/mean_time— Prestatiestatistieken opvragen voor optimalisatie.
  • patroni_postgres_running— Patroni-gezondheidsstatus (1 = actief, 0 = uitgeschakeld).
  • patroni_master— Welke pod is de huidige primaire (1 = master, 0 = replica).
  • pg_up— Basis PostgreSQL beschikbaarheidssonde.

Waarschuwingsregels

# PrometheusRule for PostgreSQL alerts
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  name: postgres-alerts
  namespace: databases
spec:
  groups:
  - name: postgresql.rules
    rules:
    - alert: PostgreSQLDown
      expr: pg_up == 0
      for: 1m
      labels:
        severity: critical
      annotations:
        summary: "PostgreSQL instance {{ $labels.instance }} is down"
    - alert: PostgreSQLReplicationLag
      expr: pg_stat_replication_pg_wal_lsn_diff > 100000000
      for: 5m
      labels:
        severity: warning
      annotations:
        summary: "Replication lag is {{ $value }} bytes on {{ $labels.instance }}"
    - alert: PostgreSQLHighConnections
      expr: sum(pg_stat_activity_count) by (instance) > 180
      for: 5m
      labels:
        severity: warning
      annotations:
        summary: "{{ $value }} active connections on {{ $labels.instance }}"
    - alert: PostgreSQLDeadlocks
      expr: rate(pg_stat_database_deadlocks[5m]) > 0
      for: 1m
      labels:
        severity: warning
      annotations:
        summary: "Deadlocks detected on {{ $labels.datname }}"
    - alert: PatroniFailover
      expr: changes(patroni_master[5m]) > 0
      labels:
        severity: critical
      annotations:
        summary: "Patroni failover occurred in cluster {{ $labels.cluster }}"

Productieafstemmingsgids

Een goede afstemming is essentieel om maximale prestaties uit de PostgreSQL op de Kubernetes te halen. De volgende parameters moeten worden aangepast op basis van de resourcelimieten en werkbelastingkenmerken van uw pod.

Geheugenconfiguratie

# For a pod with 16GB memory limit:
postgresql:
  parameters:
    # shared_buffers: 25% of total memory
    shared_buffers: "4GB"

    # effective_cache_size: 75% of total memory
    # (tells planner how much OS cache to expect)
    effective_cache_size: "12GB"

    # work_mem: shared_buffers / (max_connections * 2)
    # Conservative to prevent OOM
    work_mem: "10MB"

    # maintenance_work_mem: 5-10% of total memory
    # Used for VACUUM, CREATE INDEX, ALTER TABLE
    maintenance_work_mem: "1GB"

    # temp_buffers: memory for temp tables per session
    temp_buffers: "32MB"

    # huge_pages: try to use huge pages (requires OS config)
    huge_pages: "try"

WAL en Checkpoint-configuratie

postgresql:
  parameters:
    # WAL settings
    wal_buffers: "64MB"           # 1/32 of shared_buffers, max 64MB
    wal_compression: "zstd"        # Compress WAL (PG 15+)
    max_wal_size: "8GB"            # Before forced checkpoint
    min_wal_size: "2GB"            # WAL disk reservation
    wal_level: "replica"           # Required for replication

    # Checkpoint settings
    checkpoint_completion_target: "0.9"  # Spread I/O over 90% of interval
    checkpoint_timeout: "15min"          # Max time between checkpoints

Queryplanner en I/O

postgresql:
  parameters:
    # Cost parameters for SSD storage
    random_page_cost: "1.1"          # SSD: close to seq_page_cost
    seq_page_cost: "1.0"             # Sequential I/O baseline
    effective_io_concurrency: "200"   # Concurrent I/O for SSD

    # Planner behavior
    default_statistics_target: "200"  # More accurate statistics
    from_collapse_limit: 12           # JOIN planning threshold
    join_collapse_limit: 12           # JOIN planning threshold

    # Parallel queries
    max_parallel_workers_per_gather: "4"
    max_parallel_workers: "8"
    max_parallel_maintenance_workers: "4"
    parallel_tuple_cost: "0.01"
    parallel_setup_cost: "1000"

Verbinding en loggen

postgresql:
  parameters:
    # Connection limits
    max_connections: "200"                   # Keep low, use PgBouncer
    superuser_reserved_connections: "5"       # Reserve for admin access

    # Logging for troubleshooting
    log_statement: "ddl"                     # Log DDL statements
    log_min_duration_statement: "500"         # Log queries > 500ms
    log_checkpoints: "on"                    # Log checkpoint activity
    log_connections: "off"                   # Too noisy in production
    log_disconnections: "off"                # Too noisy in production
    log_lock_waits: "on"                     # Log lock waits
    log_temp_files: "0"                      # Log all temp file usage
    log_autovacuum_min_duration: "1000"       # Log slow autovacuum

    # Statement timeouts
    statement_timeout: "60000"               # 60 second query timeout
    lock_timeout: "30000"                    # 30 second lock timeout
    idle_in_transaction_session_timeout: "600000"  # 10 min idle txn timeout

Rolling Updates en versie-upgrades

Kleine versie-upgrades

Kleine versie-upgrades (bijvoorbeeld 16.2 naar 16.3) worden automatisch afgehandeld door de operator wanneer u de Spilo-afbeeldingstag bijwerkt. De operator voert een rollende herstart uit:

# Update the operator configuration to use a new Spilo image
helm upgrade postgres-operator postgres-operator-charts/postgres-operator \
  --namespace postgres-operator \
  --set configGeneral.docker_image=ghcr.io/zalando/spilo-16:3.1-p1 \
  --reuse-values

# The operator will perform rolling updates:
# 1. Restart replicas one at a time
# 2. Failover the primary to a freshly updated replica
# 3. Restart the old primary (now a replica)

Grote versie-upgrades

Grote versie-upgrades (bijv. PostgreSQL 15 naar 16) vereisen een zorgvuldigere planning. De Zalando-operator ondersteunt grote upgrades ter plaatse met behulp vanpg_upgrade:

# Step 1: Update the CRD to the new major version
spec:
  postgresql:
    version: "16"  # Changed from "15"

# Step 2: The operator detects the version change and:
# a) Scales down the StatefulSet to 1 replica
# b) Runs pg_upgrade on the primary pod
# c) Scales back up to the desired numberOfInstances
# d) Replicas are rebuilt from the upgraded primary

# Step 3: Verify the upgrade
kubectl exec -it pg-production-cluster-0 -n databases -- \
  su postgres -c "psql -c 'SELECT version()'"

# Step 4: Run ANALYZE to update statistics after upgrade
kubectl exec -it pg-production-cluster-0 -n databases -- \
  su postgres -c "psql -c 'ANALYZE VERBOSE'"

Belangrijke overwegingen voor grote upgrades:

  • Maak altijd een nieuwe back-up voordat u een upgrade uitvoert van
  • Test de upgrade eerst op een gekloond cluster
  • Grote upgrades vereisen downtime (doorgaans 5-30 minuten, afhankelijk van de databasegrootte)
  • Bekijk de releaseopmerkingen van de PostgreSQL voor de belangrijkste wijzigingen in
  • Houd de replicatievertraging nauwlettend in de gaten na het opnieuw opbouwen van de
  • VoerANALYZEuit op alle databases om de statistieken van de queryplanner opnieuw te genereren

Geavanceerde operationele patronen

Logische back-ups

Naast fysieke WAL-G-back-ups ondersteunt de operator logische back-ups met behulp vanpg_dump. Logische back-ups zijn handig voor migraties tussen versies en selectief tabelherstel:

# Enable logical backups in the operator configuration
helm upgrade postgres-operator postgres-operator-charts/postgres-operator \
  --namespace postgres-operator \
  --set configLogicalBackup.logical_backup_schedule="0 3 * * *" \
  --set configLogicalBackup.logical_backup_s3_bucket="my-pg-logical-backups" \
  --set configLogicalBackup.logical_backup_s3_region="us-east-1" \
  --set configLogicalBackup.logical_backup_s3_sse="AES256" \
  --reuse-values

# The operator creates a CronJob for each cluster that:
# 1. Connects to the primary PostgreSQL instance
# 2. Runs pg_dumpall (or pg_dump per database)
# 3. Compresses and uploads to S3

Aangepaste pod-omgevingsvariabelen

U kunt omgevingsvariabelen in Spilo-pods injecteren met behulp van een ConfigMap. Dit is handig voor het configureren van WAL-G, aangepaste scripts of het afstemmen van parameters op besturingssysteemniveau:

apiVersion: v1
kind: ConfigMap
metadata:
  name: postgres-pod-config
  namespace: databases
data:
  # Custom Spilo configurations
  SPILO_CONFIGURATION: |
    bootstrap:
      dcs:
        ttl: 30
        loop_wait: 10
        retry_timeout: 10
        maximum_lag_on_failover: 33554432
        postgresql:
          use_pg_rewind: true
          use_slots: true
          parameters:
            archive_mode: "on"
            archive_timeout: 1800s
  # Enable pg_stat_statements
  POSTGRESQL_SHARED_PRELOAD_LIBRARIES: "bg_mon,pg_stat_statements,pgextwlist,pg_auth_mon,set_user,timescaledb,pg_cron,pg_stat_kcache"
  # Cron jobs inside PostgreSQL
  ENABLE_PG_CRON: "true"

Netwerkbeleid voor beveiliging

Beperk in productie de netwerktoegang tot PostgreSQL-pods met behulp van Kubernetes Netwerkbeleid:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: postgres-network-policy
  namespace: databases
spec:
  podSelector:
    matchLabels:
      application: spilo
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          name: app-namespace
    - podSelector:
        matchLabels:
          app: backend
    ports:
    - protocol: TCP
      port: 5432
    - protocol: TCP
      port: 8008   # Patroni REST API
  - from:
    - namespaceSelector:
        matchLabels:
          name: monitoring
    ports:
    - protocol: TCP
      port: 9187   # Prometheus exporter
  egress:
  - to:
    - ipBlock:
        cidr: 0.0.0.0/0
    ports:
    - protocol: TCP
      port: 443    # S3/GCS/Azure for backups

Problemen oplossen Veelvoorkomende problemen

Zelfs bij automatisering ontstaan er problemen. Hier zijn de meest voorkomende problemen en hun oplossingen bij het uitvoeren van PostgreSQL met de Zalando-operator:

1. Pod zit vast in de status 'In behandeling'

# Check events for the pod
kubectl describe pod pg-production-cluster-0 -n databases

# Common causes:
# - No nodes with matching tolerations/affinity
# - Insufficient CPU or memory on nodes
# - PVC cannot be provisioned (check StorageClass)

# Fix: Check node resources and storage availability
kubectl get nodes -o custom-columns=NAME:.metadata.name,CPU:.status.allocatable.cpu,MEM:.status.allocatable.memory
kubectl get pvc -n databases

2. Replicatievertraging bij het groeien van

# Check replication status on the primary
kubectl exec -it pg-production-cluster-0 -n databases -- \
  su postgres -c "psql -c 'SELECT client_addr, state, sent_lsn, write_lsn, flush_lsn, replay_lsn, write_lag, flush_lag, replay_lag FROM pg_stat_replication'"

# Common causes:
# - Replica CPU/IO saturation
# - Network bandwidth limits
# - Long-running queries on replica blocking WAL replay
# - Insufficient wal_keep_size

# Fix: Check replica resources and cancel blocking queries
kubectl exec -it pg-production-cluster-1 -n databases -- \
  su postgres -c "psql -c 'SELECT pg_cancel_backend(pid) FROM pg_stat_activity WHERE state = \"active\" AND query_start < now() - interval \"5 minutes\"'"

3. Failover activeert

niet
# Check Patroni cluster status
kubectl exec -it pg-production-cluster-0 -n databases -- \
  su postgres -c "patronictl list"

# Check Patroni logs
kubectl logs pg-production-cluster-0 -n databases -c postgres | grep -i patroni

# Manual failover (if auto-failover is stuck)
kubectl exec -it pg-production-cluster-0 -n databases -- \
  su postgres -c "patronictl failover --candidate pg-production-cluster-1 --force"

4. Back-upfouten

# Check WAL-G backup status
kubectl exec -it pg-production-cluster-0 -n databases -- \
  su postgres -c "envdir /run/etc/wal-e.d/env wal-g backup-list"

# Check backup CronJob logs
kubectl logs -l application=spilo,cluster-name=pg-production-cluster -n databases | grep -i wal-g

# Verify S3/GCS credentials
kubectl exec -it pg-production-cluster-0 -n databases -- \
  su postgres -c "envdir /run/etc/wal-e.d/env aws s3 ls s3://my-pg-backups/"

Beste beveiligingspraktijken

Het beveiligen van PostgreSQL op Kubernetes vereist een diepgaande verdedigingsaanpak:

  • TLS-codering— Schakel SSL in voor alle clientverbindingen. De operator kan certificaten automatisch inrichten met behulp van cert-manager.
  • Geheimenbeheer— Gebruik Kubernetes Secrets (of externe geheimmanagers zoals Vault) voor databasereferenties. Bewaar nooit wachtwoorden in ConfigMaps.
  • RBAC— Beperk de ServiceAccount-machtigingen van de operator. Gebruik toegang met de minste bevoegdheden voor gebruikers van de applicatiedatabase.
  • Netwerkbeleid— Beperk pod-tot-pod-communicatie zoals weergegeven in de vorige sectie.
  • pg_hba.conf— Configureer hostgebaseerde authenticatie om te beperken welke IP's en gebruikers verbinding kunnen maken.
  • Auditregistratie— Schakel depgaudit-extensie in voor SQL-auditregistratie in gereguleerde omgevingen.
  • Gecodeerde opslag— Gebruik gecodeerde StorageClasses (EBS-codering, Azure-schijfcodering, enz.).
  • Pod-beveiligingsnormen— Voer Spilo-pods uit als niet-root met beperkte beveiligingscontexten.
# Security-hardened CRD settings
spec:
  spiloRunAsUser: 101
  spiloRunAsGroup: 103
  spiloFSGroup: 103
  enableShmVolume: true
  patroni:
    pg_hba:
    - hostssl all all 0.0.0.0/0 md5
    - host    replication standby all md5
    - hostssl replication standby all md5
  postgresql:
    parameters:
      ssl: "on"
      ssl_min_protocol_version: "TLSv1.3"
      password_encryption: "scram-sha-256"
  additionalVolumes:
  - name: postgres-tls
    mountPath: /tls
    secret:
      secretName: pg-tls-cert
      defaultMode: 0640

Capaciteitsplanning en dimensionering

De juiste maatvoering zorgt voor stabiele prestaties en kostenefficiëntie. Gebruik deze richtlijnen als uitgangspunt en pas deze aan op basis van uw werklastmonitoringsgegevens:

WerklastCPUGeheugenOpslag-instanties
Ontwikkeling500m1Gi10Gi1
Kleine productie2 kernen8Gi50Gi SSD3
Middelgrote productie4 kernen16Gi200Gi SSD3
Grote productie8 kernen32Gi500Gi SSD5
Enterprise/Analytics16+ kernen64Gi+1Ti+ SSD5+

Compleet end-to-end implementatievoorbeeld

Laten we alles samenvoegen met een volledige implementatie vanaf het begin op een nieuw Kubernetes-cluster:

# Step 1: Create namespace and configure storage
kubectl create namespace databases
kubectl create namespace postgres-operator

# Step 2: Install the Zalando Postgres Operator
helm repo add postgres-operator-charts \
  https://opensource.zalando.com/postgres-operator/charts/postgres-operator
helm repo update

helm install postgres-operator postgres-operator-charts/postgres-operator \
  --namespace postgres-operator \
  --set configKubernetes.enable_pod_antiaffinity=true \
  --set configKubernetes.pod_environment_configmap=databases/postgres-pod-config

# Step 3: Create backup configuration
kubectl apply -f - <<EOF
apiVersion: v1
kind: ConfigMap
metadata:
  name: postgres-pod-config
  namespace: databases
data:
  USE_WALG_BACKUP: "true"
  USE_WALG_RESTORE: "true"
  WALG_S3_PREFIX: "s3://my-pg-backups/\$(SCOPE)"
  BACKUP_SCHEDULE: "0 1 * * *"
  BACKUP_NUM_TO_RETAIN: "14"
EOF

# Step 4: Deploy the PostgreSQL cluster
kubectl apply -f - <<EOF
apiVersion: acid.zalan.do/v1
kind: postgresql
metadata:
  name: pg-app-cluster
  namespace: databases
  labels:
    team: platform
spec:
  teamId: "platform"
  volume:
    size: 50Gi
  numberOfInstances: 3
  enableConnectionPooler: true
  enableReplicaConnectionPooler: true
  users:
    app_user:
    - superuser
    - createdb
  databases:
    app_db: app_user
  postgresql:
    version: "16"
    parameters:
      shared_buffers: "2GB"
      work_mem: "64MB"
      effective_cache_size: "6GB"
  resources:
    requests:
      cpu: "2"
      memory: 8Gi
    limits:
      cpu: "4"
      memory: 16Gi
EOF

# Step 5: Wait for cluster readiness
kubectl wait --for=condition=Running postgresql/pg-app-cluster \
  -n databases --timeout=300s

# Step 6: Verify cluster status
kubectl get postgresql -n databases
kubectl get pods -n databases -l cluster-name=pg-app-cluster
kubectl get svc -n databases -l cluster-name=pg-app-cluster

# Step 7: Get connection credentials
export PGPASSWORD=$(kubectl get secret app-user.pg-app-cluster.credentials.postgresql.acid.zalan.do \
  -n databases -o jsonpath='{.data.password}' | base64 -d)

# Step 8: Connect and verify
kubectl run pg-client --rm -it --image=postgres:16 -n databases -- \
  psql -h pg-app-cluster-pooler -U app_user -d app_db -c "SELECT version();"

Conclusie

De Zalando Postgres Operator transformeert PostgreSQL op Kubernetes van een complexe operationele uitdaging naar een beheersbare, geautomatiseerde implementatie. Door gebruik te maken van Patroni voor op consensus gebaseerde failover, Spilo voor een containerimage met batterijen, WAL-G voor continue back-up en herstel, en PgBouncer voor efficiënte pooling van verbindingen, krijgt u een databaseplatform van productiekwaliteit dat consistent werkt in AWS EKS, Azure AKS, Google GKE en bare-metal k3s-clusters.

De belangrijkste punten uit deze handleiding zijn:

  • Automatiseer alles— Laat de operator het StatefulSet-beheer, failover en back-upplanning afhandelen. Handmatige interventie zou de uitzondering moeten zijn.
  • Agressief monitoren— Implementeer Prometheus en Grafana vanaf de eerste dag. Replicatievertraging, aantal verbindingen en vergrendelingsconflicten zijn uw vroege waarschuwingssignalen.
  • Plan voor rampen— Configureer WAL-G-back-ups, test PITR regelmatig en onderhoud een standby-cluster voor kritieke werklasten.
  • Stem af op uw werklast— Standaard PostgreSQL-parameters zijn conservatief. Pas de instellingen voor shared_buffers, work_mem en checkpoint aan op basis van uw resourcetoewijzing en querypatronen.
  • Standaard beveiligd— Schakel TLS in, gebruik SCRAM-SHA-256-authenticatie, beperk netwerktoegang en versleutel opslag in rust.
  • Testupgrades— Kloon altijd uw cluster en test belangrijke versie-upgrades voordat u ze in productie gebruikt.

Met deze uitgebreide basis bent u goed uitgerust om PostgreSQL-clusters met hoge beschikbaarheid op elk Kubernetes-platform te implementeren en te gebruiken, voor toepassingen die betrouwbaarheid, prestaties en gegevensintegriteit op schaal vereisen.