Workstation Logo
Produits
Labs IAAgents OpenAIAgents ClaudeGrok BotWorkstation CRM (WSL CRM)MarketingTous les Produits
Solutions IA
Stations de Travail IAAI SME PackagesIA PrivéeClusters GPUIA EdgeLaboratoire IA EntrepriseIA par Industrie
Services
Modernisation de plateformeIngénierie numériqueDonnées et activation IAOpérations autonomesConseil IAAutomatisation DevOpsCybersécuritéDéveloppement logicielCréation d'agentsMise en place MLOps
À Propos
PartenairesTémoignages Clients
Articles
Documentation
WSL ProxyRing PromoterWSL VaultJobshoutSysOps 24/7
Blog
Nous ContacterLogin
Workstation

Stations de travail IA, logiciels multi-agents IA, infrastructure GPU et solutions d'agents intelligents pour les entreprises modernes.

Nous Contacter

Solutions IA

Stations de Travail IAAI SME PackagesIA PrivéeClusters GPUIA EdgeLaboratoire IA EntrepriseIA par Industrie

Produits

Tous les ProduitsWSL CRM & ERPMarketingAgents OpenAIWSL ProxyRing PromoterWSL VaultJobshoutSysOps 24/7

Entreprise

À ProposPourquoi WorkstationPartenairesTémoignages ClientsTarificationContact

Ressources

ArticlesDocumentationBlogRechercherPlan du Site
Bureau Royaume-Uni
77-79 Marlowes, Hemel Hempstead HP1 1LFItinéraire : prenez la sortie 20 de la M25, Outer LondonN° d'entreprise: 11641870Lun - Ven : 9h00 - 18h00 GMT
+44 7515 356 146
Bureau Belgique
Workstation SRL, Rue Vanderkindere 34, 1180 Uccle, BrusselsBE 0751.518.683Lun - Ven : 9h00 - 18h00 CET
+32 492 45 67 46
Bureau Inde
#159 Sector 9, Pocket 1, DDA Flats, 110077 Dwarka, New Delhi
+91 98881 98841

© 2026 Workstation AI. Tous droits réservés.

ConfidentialitéCookiesConditions d'UtilisationPlan du site web

Loading blog...

Home / Blog
DatabaseKubernetesDevOpsBackend

Haute disponibilité PostgreSQL avec l'opérateur Zalando Postgres : guide de déploiement multi-cloud Kubernetes

Déployez PostgreSQL HA de qualité production avec Zalando Operator sur n'importe quelle plateforme Kubernetes

Balinder Walia12 avril 202629 min read
Introduction à

: pourquoi la haute disponibilité de PostgreSQL sur Kubernetes est importante

L'exécution de PostgreSQL en production nécessite une haute disponibilité (HA). Les temps d'arrêt mesurés en minutes peuvent coûter aux entreprises des millions de dollars en perte de revenus, en érosion de la confiance des clients et en violation des accords de niveau de service. Kubernetes est devenu la plate-forme de facto pour orchestrer les charges de travail conteneurisées, mais l'exécution de services avec état comme PostgreSQL sur Kubernetes présente des défis uniques : gestion du stockage persistant, élection du leader, basculement automatique, orchestration des sauvegardes et pooling de connexions.

L'opérateurZalando Postgresest une solution open source éprouvée que Zalando, le plus grand détaillant de mode en ligne d'Europe, a conçue pour gérer des centaines de clusters PostgreSQL en production. Il exploitePatronipour l'élection des dirigeants par consensus,Spilocomme image de conteneur PostgreSQL,WAL-Gpour l'archivage continu et la récupération ponctuelle, etPgBouncerpour le pooling de connexions. Ensemble, ces composants offrent un déploiement PostgreSQL entièrement automatisé et auto-réparateur qui fonctionne sur n'importe quelle distribution Kubernetes, des services cloud gérés tels que AWS EKS, Azure AKS et Google GKE aux clusters nus exécutant k3s avec Rancher.

Dans ce guide complet, nous explorerons l'architecture de l'opérateur Zalando Postgres, passerons en revue l'installation et la configuration sur plusieurs plates-formes Kubernetes, approfondirons la réplication, les sauvegardes, la reprise après sinistre, la surveillance et le réglage de la production. À la fin, vous aurez les connaissances nécessaires pour déployer et exploiter des clusters PostgreSQL HA de qualité production sur n'importe quelle infrastructure Kubernetes.

Architecture opérateur Zalando Postgres

Comprendre l'architecture est essentiel avant le déploiement. L'opérateur Zalando Postgres suit le modèle d'opérateur Kubernetes : il surveille les définitions de ressources personnalisées (CRD) de typepostgresqlet rapproche l'état souhaité avec les ressources Kubernetes réelles. Voici comment les composants s'assemblent :

Architecture opérateur Zalando PostgresPostgreSQL CRDType: postgresqlPostgres OpérateurMontres et accessoiresRéconcilieEnsemble d'étatsgère le cycle de vie des podsPod principalSpilo (PostgreSQL)Agent PatroniRéplique Pod 1Spilo (PostgreSQL)Agent PatronRéplique Pod 2Spilo (PostgreSQL)Agent PatronPatron DCS (Kubernetes API)Élection et campagne du leaderÉtat du clusterPgBouncerRegroupement de connexionsWAL-GSauvegardes sur S3/GCS/AzurePrimaireRépliqueConsensus/DCSSauvegardePool de connexions

Spilo : Le conteneur PostgreSQL Image

Spiloest l'image Docker de Zalando qui regroupe PostgreSQL avec Patroni, WAL-G et des extensions essentielles. Chaque pod du StatefulSet exécute un conteneur Spilo. Poignées Spilo :

  • Serveur PostgreSQL— le moteur de base de données lui-même, prenant en charge les versions 13 à 16
  • Patroni— l'agent HA qui gère l'élection du leader, la réplication et le basculement
  • WAL-G— outil d'archivage continu des WAL et de sauvegarde de base
  • pg_cron, pg_stat_statements, PostGIS— extensions couramment nécessaires préinstallées
Patroni

: élection du leader et basculement automatique

Patroni est le cœur du mécanisme HA. Il utilise un magasin de configuration distribué (DCS) pour maintenir l'état du cluster et procéder à l'élection du leader. Dans le contexte de l'opérateur Zalando, Patroni utilise leKubernetes APIlui-même comme DCS (via Endpoints ou ConfigMaps), éliminant ainsi le besoin d'un cluster etcd ou ZooKeeper externe.

Voici comment fonctionne le processus de basculement de Patroni :

  1. Vérifications de l'état— Chaque agent Patroni surveille en permanence son instance PostgreSQL locale et signale l'état de santé au DCS.
  2. Verrouillage de leader— Le principal détient un verrouillage de leader dans le DCS (un objet de point de terminaison Kubernetes). Le verrou a un TTL (30 secondes par défaut).
  3. Détection de panne— Si le serveur principal ne parvient pas à renouveler son verrou dans la durée de vie, les réplicas détectent l'absence.
  4. Élection— Les répliques éligibles concourent pour le verrouillage du leader. La réplique avec le moins de retard de réplication gagne.
  5. Promotion
  6. — La réplique gagnante se promeut au rang de réplica principal, met à jour le DCS et le point de terminaison du service Kubernetesmasterse met automatiquement à jour.
  7. Clôture— L'ancien primaire est clôturé (arrêté ou rétrogradé en réplique) pour éviter la division du cerveau.

L'ensemble du processus de basculement s'effectue généralement en15 à 30 secondes, garantissant ainsi un temps d'arrêt minimal pour vos applications.

WAL-G : Archivage et sauvegarde continus

WAL-G est un outil d'archivage de nouvelle génération pour PostgreSQL qui prend en charge la sauvegarde sur S3, Google Cloud Storage (GCS) et Azure Blob Storage. Il fournit :

  • Sauvegardes de base— Sauvegardes physiques complètes utilisantpg_basebackup
  • Archivage WAL— Envoi continu de journaux avec écriture anticipée pour une récupération ponctuelle
  • Sauvegardes Delta— Sauvegardes incrémentielles qui stockent uniquement les pages modifiées
  • Chiffrement— Chiffrement AES-256 des sauvegardes au repos
  • Compression— Compression LZ4 ou ZSTD pour réduire les coûts de stockage

Kubernetes Hiérarchie des ressources

Lorsque vous créez une ressource personnaliséepostgresql, l'opérateur crée un ensemble complet de ressources Kubernetes pour gérer le cluster. Comprendre cette hiérarchie est important pour le dépannage et la surveillance :

Hiérarchie des ressources Kubernetes— Opérateur Zalandopostgresql CRDPostgres OpérateurEnsemble d'étatsService(maître)Service(réplique)Points de terminaisonAPBPodsPVCsSecretsPgBouncer DéployerService (pooleur)PrimaireRépliqueRépliqueLignes pleines = création directe | Lignes pointillées = création conditionnelleRessources

créées par l'opérateur

  • StatefulSet— Gère les pods PostgreSQL avec des identités réseau stables et un déploiement ordonné
  • Services— Deux services ClusterIP :<cluster-name>pour le serveur principal et<cluster-name>-replpour les réplicas en lecture
  • Points de terminaison— Patroni met à jour les points de terminaison pour pointer vers le leader actuel pour un basculement transparent
  • PodDisruptionBudgets (PDB)— Garantit qu'au moins une instance reste disponible pendant les interruptions volontaires
  • Secrets— Informations d'identification du superutilisateur, de la réplication et de l'application PostgreSQL stockées en tant que Kubernetes Secrets
  • PersistentVolumeClaims (PVCs)— Un PVC par pod pour PostgreSQL stockage de données
  • Déploiement de PgBouncer— Pool de connexions en option déployé en tant que déploiement distinct avec son propre service
Installation du

sur plusieurs plates-formes Kubernetes

Conditions préalables pour

Avant d'installer l'opérateur Zalando Postgres, assurez-vous d'avoir :

  • Un cluster Kubernetes en cours d'exécution (v1.25+)
  • kubectlconfiguré avec un accès administrateur de cluster
  • helmv3 installé
  • Une StorageClass par défaut configurée
Installation de l'opérateur

via Helm

La méthode d'installation recommandée utilise Helm. Cela fonctionne de manière cohérente sur toutes les plates-formes Kubernetes :

# 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

Vérifiez que l'opérateur est en cours d'exécution :

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

AWS Spécificités du déploiement EKS

Amazon EKS nécessite une configuration spécifique pour des performances PostgreSQL optimales :

# 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

Pour les sauvegardes WAL-G sur EKS, configurez les rôles IAM pour les comptes de service (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 Déploiement AKS

Azure AKS utilise le disque Azure pour le stockage persistant et l'identité gérée pour l'authentification de sauvegarde :

# 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"

Déploiement de Google GKE

Google Kubernetes Engine utilise Persistent Disk et Workload Identity pour l'accès à la sauvegarde GCS :

# 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"

Bare Metal k3s/Rancher avec stockage Longhorn

Pour les déploiements sur site, k3s fournit une distribution Kubernetes légère et Longhorn propose un stockage en bloc distribué. Cette combinaison est idéale lorsque vous avez besoin d’un contrôle total sur votre infrastructure sans être dépendant d’un fournisseur de cloud.

# 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/Déploiement sans système d'exploitation RancherServeur de gestion RancherNœud 1 (serveur k3s)PostgreSQL PrimaireSpilo + PatroniOpérateur ZalandoPgBouncer PiscineVolume Longhorn/mnt/longhorn (3 répliques)Nœud 2 (serveur k3s)PostgreSQL RépliqueSpilo + PatroniPgBouncer PiscinePrometheus ExportateurVolume Longhorn/mnt/longhorn (3 répliques)Nœud 3 (agent k3s)PostgreSQL RépliqueSpilo + PatroniPgBouncer PiscineTableau de bord GrafanaVolume Longhorn/mnt/longhorn (3 répliques)HAProxy / MetalLB LoadBalancerSauvegardes WAL-GCompatible NFS / MinIO S3PrimaireRépliquePgBouncerLongue corneRéplication en continu

PostgreSQL Cluster CRD Spécification

Le cœur du déploiement d'un Le cluster PostgreSQL avec l'opérateur Zalando est la ressource personnaliséepostgresql. Ce manifeste YAML déclare l'état souhaité de votre cluster et l'opérateur le rapproche de la réalité. Vous trouverez ci-dessous une spécification CRD complète et prête pour la production :

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
Clé

Champs CRD expliqués

  • numberOfInstances— Nombre total de pods. L'opérateur en désigne automatiquement un comme principal et les autres comme répliques en streaming.
  • activateConnectionPooler— Déploie le side-car PgBouncer pour le service principal, réduisant ainsi la surcharge de connexion.
  • activateReplicaConnectionPooler— Déploie un PgBouncer distinct pour le service de réplication, essentiel pour les charges de travail lourdes en lecture.
  • postgresql.parameters— Paramètres de configuration PostgreSQL directs transmis àpostgresql.conf.
  • patroni— Configure le comportement de Patroni, notamment la durée de vie, l'attente de boucle, le délai d'expiration des tentatives et le mode de réplication synchrone.
  • volume.storageClass— Correspond à la StorageClass spécifique à la plate-forme (EBS gp3 sur AWS, SSD Premium sur Azure, SSD PD sur GCP, Longhorn sur k3s).
  • activateShmVolume— Monte untmpfssur/dev/shmpour la mémoire partagée PostgreSQL, essentielle aux performances.
Regroupement de connexions

avec PgBouncer

Le modèle processus par connexion du

PostgreSQL rend coûteuse la gestion d'un grand nombre de connexions client. Chaque connexion consomme environ 10 Mo de RAM. PgBouncer résout ce problème en multiplexant des milliers de connexions client sur un petit pool de connexions PostgreSQL réelles.

L'opérateur Zalando prend en charge nativement le déploiement de PgBouncer. Lorsque vous définissezenableConnectionPooler: truedans le CRD, l'opérateur crée :

  • Un déploiement PgBouncer avec un nombre de répliques configurable
  • Un service dédié (<cluster-name>-pooler) pour les connexions mutualisées
  • Synchronisation automatique des identifiants avec PostgreSQL
Modes de configuration du

PgBouncer

# 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

Pour les applications nécessitant des instructions préparées ou des fonctionnalités au niveau de la session, connectez-vous directement aux services PostgreSQL en contournant PgBouncer, ou utilisez le mode de poolingsessionavec le compromis d'une efficacité de connexion inférieure.

Réplication PostgreSQL multirégion

Pour les applications mondiales qui nécessitent des lectures à faible latence à partir de plusieurs emplacements géographiques ou une reprise après sinistre dans plusieurs régions, la réplication multirégionale est essentielle. L'opérateur Zalando prend en charge cela via des clusters de secours qui se répliquent à partir d'un cluster principal via une réplication en streaming ou des archives WAL-G.

Réplication en streaming PostgreSQL multirégionUS-EAST-1 (AWS EKS)GRAPPE PRIMAIREpg-prod-us (3 pods)PrimaireRépliqueRéplication de synchronisationdans AZWAL-G → S3 (continu)PgBouncer PoolerEU-WEST-1 (Azure AKS)CLUSTER DE RÉVEILpg-standby-eu (2 modules)VeilleRépliqueRéplication en cascadeWAL-G → Azure BlobPgBouncer (lecture seule)AP-SUD-EST (GCP GKE)CLUSTER DE RÉVEILpg-standby-ap (2 modules)VeilleRépliqueRéplication en cascadeWAL-G → Godet GCSPgBouncer (lecture seule)ASYNCASYNC (expédition WAL)Topologie de réplicationPrimaire (US-EST) → Streaming asynchrone vers EU-WEST et amp; Clusters de secours AP-SOUTHEAST | RPO : ~secondes | RTO : <5 min avec promotion manuelleRéplication synchroniséeRéplication asynchronePrimaireLeader de secoursLire la répliqueConfiguration de la réplication en continu

La réplication streaming PostgreSQL est le fondement de la haute disponibilité chez l'opérateur Zalando. Il fonctionne en envoyant les enregistrements WAL (Write-Ahead Log) du serveur principal vers les réplicas en temps quasi réel. L'opérateur le configure automatiquement, mais comprendre les détails facilite le réglage et le dépannage.

  • Réplication synchrone— Le serveur principal attend qu'au moins une réplique confirme la réception des WAL avant de valider une transaction. Cela garantit zéro perte de données (RPO=0) mais ajoute de la latence. Activer avecpatroni.synchronous_mode: true.
  • Réplication asynchrone— Le serveur principal s'engage immédiatement et expédie les WAL de manière asynchrone. Latence légèrement inférieure mais perte de données potentielle lors du basculement. C'est la valeur par défaut.
  • Réplication en cascade— Les réplicas peuvent être répliqués à partir d'autres réplicas au lieu du réplica principal, réduisant ainsi la charge sur le réplica principal dans les grands clusters.
# 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
Sauvegarde et récupération

avec WAL-G

Configuration de sauvegarde WAL-G

Une configuration de sauvegarde appropriée est essentielle pour la reprise après sinistre. L'opérateur Zalando intègre WAL-G pour une sauvegarde continue vers le stockage objet. Voici une configuration complète pour le stockage compatible S3 :

# 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"

Récupération ponctuelle (PITR)

Le

PITR vous permet de restaurer votre base de données à tout moment précis, ce qui est critique pour la récupération après une suppression accidentelle ou une corruption de données. L'opérateur Zalando prend en charge PITR via le mécanisme de clonage :

# 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

Lorsque ce CRD est appliqué, l'opérateur effectue les étapes suivantes :

  1. Recherche la dernière sauvegarde de base avant l'horodatage cible
  2. Restaure la sauvegarde de base sur le pod principal du nouveau StatefulSet
  3. Rejoue les segments WAL jusqu'à l'horodatage spécifié
  4. Ouvre la base de données pour les opérations de lecture-écriture
  5. Configure la réplication en continu vers les pods de réplique

Cluster de secours pour la reprise après sinistre

Un cluster de secours se réplique en continu à partir d'un cluster principal, fournissant ainsi une réserve à chaud qui peut être favorisée en cas de sinistre. Ceci est différent des réplicas au sein d'un cluster : un cluster de secours est une ressource Kubernetes complètement indépendante qui peut s'exécuter dans un espace de noms, un cluster ou même une région différent.

# 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

Pour promouvoir un cluster de secours en cluster principal indépendant (lors d'une reprise après sinistre), supprimez simplement la sectionstandbydu CRD et appliquez :

# 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
Surveillance

avec Prometheus et Grafana

Une surveillance complète n'est pas négociable pour les déploiements de production PostgreSQL. L'opérateur Zalando prend en charge l'exportation des métriques Prometheus via le side-carpostgres_exporter. Voici comment mettre en place une pile de surveillance complète :

Moniteur de service

pour 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
Indicateurs clés du

pour surveiller le

Voici les métriques PostgreSQL les plus critiques à suivre dans vos tableaux de bord Grafana :

  • pg_stat_replication_lag— Délai de réplication en octets et secondes. Alerte si le décalage dépasse votre seuil RPO.
  • pg_stat_activity_count— Connexions actives par état. Alerte sur épuisement du pool de connexions.
  • pg_stat_database_tup_fetched/returned/inserted/updated/deleted— Mesures de débit de requête.
  • pg_stat_bgwriter_buffers_checkpoint/clean/backend— Efficacité de la gestion des tampons.
  • pg_database_size_bytes— Croissance de la taille de la base de données au fil du temps pour la planification de la capacité.
  • pg_locks_count— Conflit de verrouillage. Alerte sur les verrous en attente excessive.
  • pg_stat_statements_calls/mean_time— Interrogez les statistiques de performances pour l'optimisation.
  • patroni_postgres_running— État de santé du Patroni (1 = en cours d'exécution, 0 = en panne).
  • patroni_master— Quel pod est le principal actuel (1 = maître, 0 = réplique).
  • pg_up— Sonde de disponibilité PostgreSQL de base.

Règles d'alerte

# 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 }}"
Guide de réglage de la production du

Un réglage approprié est essentiel pour extraire des performances maximales du PostgreSQL sur le Kubernetes. Les paramètres suivants doivent être ajustés en fonction des limites de ressources de votre pod et des caractéristiques de votre charge de travail.

Configuration de la mémoire

# 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"

Configuration des WAL et des points de contrôle

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
Planificateur de requêtes

et E/S

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"

Connexion et journalisation

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

Mises à jour progressives et mises à niveau de version

Mises à niveau de la version mineure du

Les mises à niveau de versions mineures du

(par exemple, 16.2 à 16.3) sont gérées automatiquement par l'opérateur lorsque vous mettez à jour la balise d'image Spilo. L'opérateur effectue un redémarrage progressif :

# 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)
Mises à niveau majeures de la version

Les mises à niveau des versions majeures du

(par exemple, PostgreSQL 15 à 16) nécessitent une planification plus minutieuse. L'opérateur Zalando prend en charge les mises à niveau majeures sur place à l'aide dupg_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'"

Considérations importantes pour les mises à niveau majeures :

  • Effectuez toujours une nouvelle sauvegarde avant de mettre à niveau le
  • .
  • Testez d'abord la mise à niveau sur un cluster cloné
  • Les mises à niveau majeures nécessitent un temps d'arrêt (généralement 5 à 30 minutes selon la taille de la base de données)
  • Consultez les notes de version de PostgreSQL pour connaître les modifications majeures
  • Surveiller de près le décalage de réplication après la reconstruction de la réplique
  • ExécutezANALYZEsur toutes les bases de données pour régénérer les statistiques du planificateur de requêtes

Modèles opérationnels avancés

Sauvegardes logiques

En plus des sauvegardes physiques WAL-G, l'opérateur prend en charge les sauvegardes logiques à l'aide depg_dump. Les sauvegardes logiques sont utiles pour les migrations entre versions et les restaurations sélectives de tables :

# 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

Variables d'environnement de pod personnalisées

Vous pouvez injecter des variables d'environnement dans les pods Spilo à l'aide d'un ConfigMap. Ceci est utile pour configurer WAL-G, des scripts personnalisés ou régler les paramètres au niveau du système d'exploitation :

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"
Politiques réseau

pour la sécurité

En production, limitez l'accès réseau aux pods PostgreSQL à l'aide des stratégies de réseau Kubernetes :

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

Dépannage des problèmes courants

Même avec l'automatisation, des problèmes surviennent. Voici les problèmes les plus courants et leurs solutions lors de l'exécution de PostgreSQL avec l'opérateur Zalando :

1. Pod bloqué en état d'attente

# 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. Retard de réplication croissant

# 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. Le basculement ne déclenche pas

# 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. Échecs de sauvegarde

# 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/"

Meilleures pratiques de sécurité

La sécurisation de PostgreSQL sur Kubernetes nécessite une approche de défense en profondeur :

  • Chiffrement TLS— Activez SSL pour toutes les connexions client. L'opérateur peut automatiquement fournir des certificats à l'aide de cert-manager.
  • Gestion des secrets— Utilisez les secrets Kubernetes (ou des gestionnaires de secrets externes comme Vault) pour les informations d'identification de la base de données. Ne stockez jamais les mots de passe dans ConfigMaps.
  • RBAC— Limite les autorisations du compte de service de l'opérateur. Utilisez l'accès avec le moindre privilège pour les utilisateurs de la base de données d'application.
  • NetworkPolicies— Restreindre la communication entre pods, comme indiqué dans la section précédente.
  • pg_hba.conf— Configurez l'authentification basée sur l'hôte pour restreindre les adresses IP et les utilisateurs pouvant se connecter.
  • Journalisation d'audit— Activez l'extensionpgauditpour la journalisation d'audit SQL dans les environnements réglementés.
  • Stockage crypté— Utilisez des StorageClasses cryptées (cryptage EBS, cryptage de disque Azure, etc.).
  • Normes de sécurité des pods— Exécutez les pods Spilo en tant que non root avec des contextes de sécurité restreints.
# 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

Planification et dimensionnement des capacités

Un dimensionnement approprié garantit des performances stables et une rentabilité. Utilisez ces directives comme point de départ et ajustez en fonction des données de surveillance de votre charge de travail :

Charge de travailCPUMémoireStockageInstances
Développement500m1Gi10Gi1
Petite production2 cœurs8GiSSD 50Gi3
Production moyenne4 cœurs16GiSSD 200Gi3
Grande production8 cœurs32GiSSD 500Gi5
Entreprise/Analyse16+ cœurs64Gi+1Ti+SSD5+

Exemple de déploiement complet de bout en bout

Mettons le tout en place avec un déploiement complet à partir de zéro sur un nouveau cluster Kubernetes :

# 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();"

Conclusion

L'opérateur Zalando Postgres transforme PostgreSQL sur Kubernetes d'un défi opérationnel complexe en un déploiement automatisé et gérable. En tirant parti de Patroni pour un basculement basé sur un consensus, Spilo pour une image de conteneur incluant des batteries, WAL-G pour une sauvegarde et une restauration continues et PgBouncer pour un pooling de connexions efficace, vous obtenez une plate-forme de base de données de qualité production qui fonctionne de manière cohérente sur les clusters AWS EKS, Azure AKS, Google GKE et k3s nus.

Les principaux points à retenir de ce guide sont :

  • Automatisez tout— Laissez l'opérateur gérer la gestion StatefulSet, le basculement et la planification des sauvegardes. L’intervention manuelle devrait être l’exception.
  • Surveillez de manière agressive— Déployez Prometheus et Grafana dès le premier jour. Le délai de réplication, le nombre de connexions et les conflits de verrouillage sont vos premiers signaux d'alerte.
  • Planifier en cas de sinistre— Configurez les sauvegardes WAL-G, testez régulièrement PITR et maintenez un cluster de secours pour les charges de travail critiques.
  • Adaptez votre charge de travail— Les paramètres PostgreSQL par défaut sont prudents. Ajustez les paramètres shared_buffers, work_mem et checkpoint en fonction de votre allocation de ressources et de vos modèles de requête.
  • Sécurisé par défaut— Activez TLS, utilisez l'authentification SCRAM-SHA-256, restreignez l'accès au réseau et chiffrez le stockage au repos.
  • Testez les mises à niveau— Clonez toujours votre cluster et testez les mises à niveau des versions majeures avant de les appliquer en production.

Grâce à cette base complète, vous êtes bien équipé pour déployer et exploiter des clusters PostgreSQL hautement disponibles sur n'importe quelle plate-forme Kubernetes, au service d'applications qui exigent fiabilité, performances et intégrité des données à grande échelle.