Skip to content

Latest commit

 

History

History
1305 lines (1104 loc) · 76.7 KB

File metadata and controls

1305 lines (1104 loc) · 76.7 KB

🔝 Retour au Sommaire

21.2.3 Cloud-Native et Distributed PostgreSQL

Introduction

L'adoption massive du cloud computing a transformé la façon dont nous déployons et gérons les bases de données. PostgreSQL, traditionnellement conçu pour fonctionner sur un seul serveur, s'est adapté à cette nouvelle réalité grâce à des solutions cloud-natives et distribuées.

Ce chapitre explore comment PostgreSQL s'intègre dans les architectures cloud modernes, des services managés aux déploiements Kubernetes, en passant par les solutions qui étendent PostgreSQL pour une distribution horizontale à grande échelle.


Partie 1 : Comprendre les Concepts Cloud-Native

1.1 Qu'est-ce que Cloud-Native ?

Cloud-native désigne une approche de conception d'applications qui tire pleinement parti des avantages du cloud computing :

┌─────────────────────────────────────────────────────────────────────────┐
│                    Principes Cloud-Native                               │
│                                                                         │
│   ┌─────────────────┐  ┌─────────────────┐  ┌─────────────────┐         │
│   │  Conteneurs     │  │  Microservices  │  │  Orchestration  │         │
│   │                 │  │                 │  │                 │         │
│   │  Packaging      │  │  Architecture   │  │  Kubernetes     │         │
│   │  portable et    │  │  découplée et   │  │  gestion        │         │
│   │  reproductible  │  │  scalable       │  │  automatisée    │         │
│   └─────────────────┘  └─────────────────┘  └─────────────────┘         │
│                                                                         │
│   ┌─────────────────┐  ┌─────────────────┐  ┌─────────────────┐         │
│   │  DevOps/GitOps  │  │  Élasticité     │  │  Résilience     │         │
│   │                 │  │                 │  │                 │         │
│   │  Infrastructure │  │  Scale up/down  │  │  Tolérance aux  │         │
│   │  as Code        │  │  automatique    │  │  pannes         │         │
│   └─────────────────┘  └─────────────────┘  └─────────────────┘         │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

1.2 Les Défis de PostgreSQL dans le Cloud

PostgreSQL a été conçu à l'origine comme une base de données monolithique. Son adaptation au cloud présente des défis spécifiques :

Défi Description Solutions
État persistant Les conteneurs sont éphémères, les données ne le sont pas Volumes persistants, StatefulSets
Haute disponibilité Un pod qui redémarre = indisponibilité Réplication, failover automatique
Scalabilité horizontale PostgreSQL ne scale pas nativement Citus, read replicas, sharding
Gestion des connexions Connexions coûteuses en ressources Connection pooling (PgBouncer)
Sauvegarde/Restauration Complexité dans les environnements distribués Outils spécialisés (pgBackRest)

1.3 Modèles de Déploiement

┌─────────────────────────────────────────────────────────────────────────┐
│                    Spectre des Options de Déploiement                   │
│                                                                         │
│   Self-Managed                                              Fully       │
│   (Control total)                                          Managed      │
│   ◄─────────────────────────────────────────────────────────────────►   │
│                                                                         │
│   ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────────┐  │
│   │   VM /   │  │ Docker / │  │Kubernetes│  │ Managed  │  │Serverless│  │
│   │   Bare   │  │ Compose  │  │ Operators│  │   DBaaS  │  │   DB     │  │
│   │  Metal   │  │          │  │          │  │          │  │          │  │
│   └──────────┘  └──────────┘  └──────────┘  └──────────┘  └──────────┘  │
│                                                                         │
│   Plus de        ◄───────────────────────────────────►    Moins de      │
│   contrôle                                                contrôle      │
│                                                                         │
│   Plus de        ◄───────────────────────────────────►    Moins de      │
│   maintenance                                             maintenance   │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

Partie 2 : PostgreSQL Managé dans le Cloud

2.1 Vue d'Ensemble des Services Managés

Les principaux fournisseurs cloud proposent des services PostgreSQL managés :

Service Fournisseur Points Forts
Amazon RDS AWS Mature, large écosystème
Amazon Aurora AWS Compatible PostgreSQL, très performant
Azure Database Microsoft Intégration Azure, Flexible Server
Cloud SQL Google Simple, intégré GCP
AlloyDB Google Haute performance, compatible PostgreSQL
Neon Neon Serverless, branching
Supabase Supabase Backend-as-a-Service, temps réel
PlanetScale - MySQL (mentionné pour comparaison)
CockroachDB Cockroach Labs Distribué, compatible PostgreSQL

2.2 Amazon RDS pour PostgreSQL

Amazon RDS (Relational Database Service) est le service managé PostgreSQL le plus utilisé.

Caractéristiques

┌─────────────────────────────────────────────────────────────────────────┐
│                    Architecture RDS PostgreSQL                          │
│                                                                         │
│   ┌─────────────────────────────────────────────────────────────────┐   │
│   │                         VPC Client                              │   │
│   │                                                                 │   │
│   │   Application ─────► Security Group ─────► RDS Endpoint         │   │
│   │                                                                 │   │
│   └─────────────────────────────────────────────────────────────────┘   │
│                                      │                                  │
│                                      ▼                                  │
│   ┌─────────────────────────────────────────────────────────────────┐   │
│   │                    AWS Managed Infrastructure                   │   │
│   │                                                                 │   │
│   │   ┌─────────────┐    Réplication     ┌─────────────┐            │   │
│   │   │   Primary   │ ─────synchrone────► │   Standby   │  Multi-AZ │   │
│   │   │   (AZ-a)    │                     │   (AZ-b)    │           │   │
│   │   └──────┬──────┘                     └─────────────┘           │   │
│   │          │                                                      │   │
│   │          │  Réplication asynchrone                              │   │
│   │          ▼                                                      │   │
│   │   ┌─────────────┐  ┌─────────────┐                              │   │
│   │   │ Read Replica│  │ Read Replica│   (jusqu'à 15)               │   │
│   │   │   (AZ-c)    │  │  (Région 2) │   Cross-Region               │   │
│   │   └─────────────┘  └─────────────┘                              │   │
│   │                                                                 │   │
│   │   ┌─────────────────────────────────────────────────────────┐   │   │
│   │   │  Stockage EBS (SSD gp3/io2) avec réplication automatique│   │   │
│   │   └─────────────────────────────────────────────────────────┘   │   │
│   │                                                                 │   │
│   └─────────────────────────────────────────────────────────────────┘   │
│                                                                         │
│   Géré par AWS :                                                        │
│   ✓ Provisioning    ✓ Patching    ✓ Backups    ✓ Monitoring             │
│   ✓ Failover        ✓ Scaling     ✓ Encryption ✓ Compliance             │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

Configuration Typique

# Exemple Terraform pour RDS PostgreSQL
resource "aws_db_instance" "postgres" {
  identifier     = "my-postgres-db"
  engine         = "postgres"
  engine_version = "16.3"

  instance_class    = "db.r6g.xlarge"
  allocated_storage = 100
  storage_type      = "gp3"
  storage_encrypted = true

  db_name  = "myapp"
  username = "admin"
  password = var.db_password

  # Haute disponibilité
  multi_az = true

  # Réseau
  db_subnet_group_name   = aws_db_subnet_group.main.name
  vpc_security_group_ids = [aws_security_group.postgres.id]
  publicly_accessible    = false

  # Sauvegardes
  backup_retention_period = 7
  backup_window          = "03:00-04:00"

  # Maintenance
  maintenance_window         = "Mon:04:00-Mon:05:00"
  auto_minor_version_upgrade = true

  # Performance Insights
  performance_insights_enabled = true

  # Paramètres PostgreSQL
  parameter_group_name = aws_db_parameter_group.postgres.name
}

resource "aws_db_parameter_group" "postgres" {
  family = "postgres16"
  name   = "my-postgres-params"

  parameter {
    name  = "shared_preload_libraries"
    value = "pg_stat_statements"
  }

  parameter {
    name  = "log_min_duration_statement"
    value = "1000"
  }
}

2.3 Amazon Aurora PostgreSQL

Aurora est une réécriture du moteur de stockage PostgreSQL par AWS, optimisée pour le cloud.

Architecture Aurora

┌─────────────────────────────────────────────────────────────────────────┐
│                    Architecture Aurora PostgreSQL                       │
│                                                                         │
│   ┌─────────────────────────────────────────────────────────────────┐   │
│   │                      Couche Compute                             │   │
│   │                                                                 │   │
│   │   ┌─────────────┐  ┌─────────────┐  ┌─────────────┐             │   │
│   │   │   Writer    │  │   Reader    │  │   Reader    │             │   │
│   │   │  Instance   │  │  Instance   │  │  Instance   │             │   │
│   │   └──────┬──────┘  └──────┬──────┘  └──────┬──────┘             │   │
│   │          │                │                │                    │   │
│   └──────────┼────────────────┼────────────────┼────────────────────┘   │
│              │                │                │                        │
│              └────────────────┼────────────────┘                        │
│                               ▼                                         │
│   ┌─────────────────────────────────────────────────────────────────┐   │
│   │              Couche Stockage Distribuée Aurora                  │   │
│   │                                                                 │   │
│   │   ┌─────────┐  ┌─────────┐  ┌─────────┐  ┌─────────┐            │   │
│   │   │ Storage │  │ Storage │  │ Storage │  │ Storage │  ...       │   │
│   │   │  Node   │  │  Node   │  │  Node   │  │  Node   │            │   │
│   │   │  (AZ-a) │  │  (AZ-a) │  │  (AZ-b) │  │  (AZ-c) │            │   │
│   │   └─────────┘  └─────────┘  └─────────┘  └─────────┘            │   │
│   │                                                                 │   │
│   │   • 6 copies des données sur 3 AZs                              │   │
│   │   • Réplication synchrone au niveau stockage                    │   │
│   │   • Auto-scaling jusqu'à 128 TB                                 │   │
│   │   • Réparation automatique des blocs corrompus                  │   │
│   │                                                                 │   │
│   └─────────────────────────────────────────────────────────────────┘   │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

Avantages d'Aurora

Caractéristique Aurora RDS Standard
Performance 3× plus rapide Baseline
Réplication < 10ms (stockage) Secondes (streaming)
Failover < 30 secondes 1-2 minutes
Stockage Auto-scale 128 TB Manuel, max 64 TB
Backups Continus, PITR Snapshots planifiés
Coût ~20% plus cher Baseline

Aurora Serverless v2

Aurora Serverless ajuste automatiquement la capacité compute :

# Exemple de configuration Aurora Serverless v2
resource "aws_rds_cluster" "aurora_serverless" {
  cluster_identifier = "my-aurora-serverless"
  engine            = "aurora-postgresql"
  engine_mode       = "provisioned"  # Serverless v2 utilise provisioned
  engine_version    = "15.4"

  serverlessv2_scaling_configuration {
    min_capacity = 0.5   # 0.5 ACU minimum (peut descendre à 0 avec pause)
    max_capacity = 16    # 16 ACU maximum
  }

  # ... autres configurations
}

resource "aws_rds_cluster_instance" "aurora_instance" {
  identifier         = "my-aurora-serverless-instance"
  cluster_identifier = aws_rds_cluster.aurora_serverless.id
  instance_class     = "db.serverless"  # Classe spéciale pour Serverless v2
  engine             = "aurora-postgresql"
}

2.4 Google Cloud SQL et AlloyDB

Cloud SQL

Service PostgreSQL managé simple et fiable de Google Cloud.

# Exemple Terraform pour Cloud SQL
resource "google_sql_database_instance" "postgres" {
  name             = "my-postgres-instance"
  database_version = "POSTGRES_16"
  region           = "europe-west1"

  settings {
    tier = "db-custom-4-16384"  # 4 vCPU, 16 GB RAM

    availability_type = "REGIONAL"  # Haute disponibilité

    backup_configuration {
      enabled                        = true
      point_in_time_recovery_enabled = true
      start_time                     = "03:00"
    }

    ip_configuration {
      ipv4_enabled    = false
      private_network = google_compute_network.vpc.id
    }

    database_flags {
      name  = "log_min_duration_statement"
      value = "1000"
    }

    insights_config {
      query_insights_enabled  = true
      record_application_tags = true
    }
  }
}

AlloyDB

AlloyDB est la réponse de Google à Aurora : un PostgreSQL réinventé pour le cloud.

┌─────────────────────────────────────────────────────────────────────────┐
│                    Architecture AlloyDB                                 │
│                                                                         │
│   Caractéristiques clés :                                               │
│                                                                         │
│   • 4× plus rapide que PostgreSQL standard (transactions)               │
│   • 100× plus rapide pour les requêtes analytiques                      │
│   • Séparation compute/stockage (comme Aurora)                          │
│   • Columnar engine intégré pour l'analytique                           │
│   • Machine Learning intégré (AlloyDB AI)                               │
│   • 99.99% SLA disponibilité                                            │
│                                                                         │
│   ┌─────────────────────────────────────────────────────────────────┐   │
│   │   Primary Instance    Read Pool (auto-scaling)                  │   │
│   │   ┌─────────┐        ┌─────────┐ ┌─────────┐ ┌─────────┐        │   │
│   │   │ Compute │        │ Reader  │ │ Reader  │ │ Reader  │        │   │
│   │   │  (R/W)  │        │   #1    │ │   #2    │ │   #N    │        │   │
│   │   └────┬────┘        └────┬────┘ └────┬────┘ └────┬────┘        │   │
│   │        │                  │           │           │             │   │
│   │        └──────────────────┴───────────┴───────────┘             │   │
│   │                           │                                     │   │
│   │                           ▼                                     │   │
│   │   ┌─────────────────────────────────────────────────────────┐   │   │
│   │   │            Stockage Distribué Intelligent               │   │   │
│   │   │   • Log-structured storage                              │   │   │
│   │   │   • Columnar cache pour analytics                       │   │   │
│   │   │   • Réplication synchrone multi-zone                    │   │   │
│   │   └─────────────────────────────────────────────────────────┘   │   │
│   └─────────────────────────────────────────────────────────────────┘   │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

2.5 Azure Database for PostgreSQL

Microsoft propose deux options principales :

Flexible Server (Recommandé)

# Exemple Terraform pour Azure Flexible Server
resource "azurerm_postgresql_flexible_server" "postgres" {
  name                   = "my-postgres-flexible"
  resource_group_name    = azurerm_resource_group.main.name
  location               = "West Europe"
  version                = "16"

  administrator_login    = "adminuser"
  administrator_password = var.db_password

  sku_name               = "GP_Standard_D4s_v3"
  storage_mb             = 131072

  delegated_subnet_id    = azurerm_subnet.postgres.id
  private_dns_zone_id    = azurerm_private_dns_zone.postgres.id

  high_availability {
    mode                      = "ZoneRedundant"
    standby_availability_zone = "2"
  }

  backup_retention_days = 7

  maintenance_window {
    day_of_week  = 0
    start_hour   = 3
    start_minute = 0
  }
}

2.6 Comparaison des Services Managés

Critère RDS Aurora Cloud SQL AlloyDB Azure Flexible
Performance ★★★ ★★★★★ ★★★ ★★★★★ ★★★★
Coût $$ $$$ $$ $$$ $$
Serverless Non Oui (v2) Non Oui Oui (preview)
Max stockage 64 TB 128 TB 64 TB 128+ TB 32 TB
Read replicas 15 15 10 Pool auto 5
Cross-region Oui Oui (Global DB) Oui Oui Oui

Partie 3 : PostgreSQL sur Kubernetes

3.1 Pourquoi Kubernetes pour PostgreSQL ?

Kubernetes offre des avantages pour les bases de données stateful :

  • Déclaratif : Infrastructure as Code native
  • Auto-healing : Redémarrage automatique des pods défaillants
  • Portabilité : Même configuration sur n'importe quel cloud
  • Écosystème : Operators spécialisés pour PostgreSQL

3.2 Concepts Kubernetes pour les Bases de Données

┌─────────────────────────────────────────────────────────────────────────┐
│                    Concepts Kubernetes pour PostgreSQL                  │
│                                                                         │
│   StatefulSet (pas Deployment!)                                         │
│   ┌─────────────────────────────────────────────────────────────────┐   │
│   │                                                                 │   │
│   │   Pod postgres-0         Pod postgres-1         Pod postgres-2  │   │
│   │   ┌───────────────┐     ┌───────────────┐     ┌───────────────┐ │   │
│   │   │   Container   │     │   Container   │     │   Container   │ │   │
│   │   │   PostgreSQL  │     │   PostgreSQL  │     │   PostgreSQL  │ │   │
│   │   └───────┬───────┘     └───────┬───────┘     └───────┬───────┘ │   │
│   │           │                     │                     │         │   │
│   │   ┌───────▼───────┐     ┌───────▼───────┐     ┌───────▼───────┐ │   │
│   │   │      PVC      │     │      PVC      │     │      PVC      │ │   │
│   │   │  postgres-0   │     │  postgres-1   │     │  postgres-2   │ │   │
│   │   └───────────────┘     └───────────────┘     └───────────────┘ │   │
│   │                                                                 │   │
│   └─────────────────────────────────────────────────────────────────┘   │
│                                                                         │
│   Services                                                              │
│   ┌─────────────────────────────────────────────────────────────────┐   │
│   │                                                                 │   │
│   │   postgres-rw (ClusterIP)  ──► Pointe vers le Primary           │   │
│   │   postgres-ro (ClusterIP)  ──► Load balance vers les Replicas   │   │
│   │   postgres-0 (Headless)    ──► Accès direct au pod 0            │   │
│   │                                                                 │   │
│   └─────────────────────────────────────────────────────────────────┘   │
│                                                                         │
│   Différences avec Deployment :                                         │
│   • Identité stable (postgres-0, postgres-1...)                         │
│   • Stockage persistant par pod (PVC individuels)                       │
│   • Démarrage/arrêt ordonnés                                            │
│   • Nom DNS stable (postgres-0.postgres-svc.namespace.svc)              │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

3.3 Les Operators PostgreSQL

Un Operator est un contrôleur Kubernetes qui automatise la gestion d'applications complexes. Plusieurs operators PostgreSQL existent :

Operator Mainteneur Points Forts
CloudNativePG CloudNative PG CNCF, très actif, natif K8s
Zalando Postgres Operator Zalando Mature, utilisé en production
Crunchy PGO Crunchy Data Entreprise, fonctionnalités avancées
StackGres OnGres Interface UI, extensions packagées
Percona Operator Percona Multi-cloud, backup intégré

3.4 CloudNativePG (CNPG)

CloudNativePG est l'operator recommandé par la CNCF (Cloud Native Computing Foundation).

Installation

# Installation via kubectl
kubectl apply -f \
  https://raw.githubusercontent.com/cloudnative-pg/cloudnative-pg/release-1.22/releases/cnpg-1.22.0.yaml

# Ou via Helm
helm repo add cnpg https://cloudnative-pg.github.io/charts  
helm install cnpg cnpg/cloudnative-pg -n cnpg-system --create-namespace  

Déployer un Cluster PostgreSQL

# cluster-postgres.yaml
apiVersion: postgresql.cnpg.io/v1  
kind: Cluster  
metadata:  
  name: my-postgres-cluster
  namespace: database
spec:
  instances: 3  # 1 primary + 2 replicas

  imageName: ghcr.io/cloudnative-pg/postgresql:16.2

  # Configuration PostgreSQL
  postgresql:
    parameters:
      shared_buffers: "256MB"
      max_connections: "200"
      log_min_duration_statement: "1000"
      pg_stat_statements.track: all
    pg_hba:
      - host all all 10.0.0.0/8 scram-sha-256

  # Stockage
  storage:
    size: 50Gi
    storageClass: fast-ssd

  # Ressources
  resources:
    requests:
      memory: "1Gi"
      cpu: "500m"
    limits:
      memory: "2Gi"
      cpu: "2"

  # Sauvegardes vers S3
  backup:
    barmanObjectStore:
      destinationPath: s3://my-bucket/backups
      s3Credentials:
        accessKeyId:
          name: aws-creds
          key: ACCESS_KEY_ID
        secretAccessKey:
          name: aws-creds
          key: SECRET_ACCESS_KEY
      wal:
        compression: gzip
    retentionPolicy: "7d"

  # Monitoring
  monitoring:
    enablePodMonitor: true

  # Affinité pour répartir les pods
  affinity:
    topologyKey: topology.kubernetes.io/zone
# Déployer le cluster
kubectl apply -f cluster-postgres.yaml

# Vérifier l'état
kubectl get clusters -n database  
kubectl get pods -n database -l cnpg.io/cluster=my-postgres-cluster  

Se Connecter au Cluster

# Récupérer les credentials
kubectl get secret my-postgres-cluster-app -n database -o jsonpath='{.data.password}' | base64 -d

# Port-forward pour accès local
kubectl port-forward svc/my-postgres-cluster-rw 5432:5432 -n database

# Ou utiliser le plugin kubectl cnpg
kubectl cnpg psql my-postgres-cluster -n database

3.5 Zalando Postgres Operator

L'operator de Zalando est mature et utilisé en production par de nombreuses entreprises.

# postgresql-cluster.yaml (Zalando)
apiVersion: acid.zalan.do/v1  
kind: postgresql  
metadata:  
  name: my-postgres-cluster
  namespace: database
spec:
  teamId: "myteam"
  numberOfInstances: 3

  postgresql:
    version: "16"
    parameters:
      shared_buffers: "256MB"
      max_connections: "200"

  volume:
    size: 50Gi
    storageClass: fast-ssd

  resources:
    requests:
      cpu: 500m
      memory: 1Gi
    limits:
      cpu: 2
      memory: 2Gi

  users:
    myapp:
      - superuser
      - createdb

  databases:
    myappdb: myapp

  patroni:
    synchronous_mode: true
    synchronous_mode_strict: false

  sidecars:
    - name: exporter
      image: quay.io/prometheuscommunity/postgres-exporter:latest
      ports:
        - containerPort: 9187

3.6 Architecture Haute Disponibilité sur Kubernetes

┌─────────────────────────────────────────────────────────────────────────┐
│                    HA PostgreSQL sur Kubernetes                         │
│                                                                         │
│   ┌─────────────────────────────────────────────────────────────────┐   │
│   │                        Ingress / LoadBalancer                   │   │
│   └─────────────────────────────────────────────────────────────────┘   │
│                          │                    │                         │
│                          ▼                    ▼                         │
│   ┌─────────────────────────────┐  ┌─────────────────────────────┐      │
│   │   Service postgres-rw       │  │   Service postgres-ro       │      │
│   │   (Primary uniquement)      │  │   (Read replicas)           │      │
│   └──────────────┬──────────────┘  └──────────────┬──────────────┘      │
│                  │                                │                     │
│                  ▼                                ▼                     │
│   ┌─────────────────────────────────────────────────────────────────┐   │
│   │                        StatefulSet                              │   │
│   │                                                                 │   │
│   │   Zone A              Zone B              Zone C                │   │
│   │   ┌─────────────┐    ┌─────────────┐    ┌─────────────┐         │   │
│   │   │ postgres-0  │    │ postgres-1  │    │ postgres-2  │         │   │
│   │   │  (Primary)  │───►│  (Replica)  │    │  (Replica)  │         │   │
│   │   │             │    │             │◄───│             │         │   │
│   │   │ ┌─────────┐ │    │ ┌─────────┐ │    │ ┌─────────┐ │         │   │
│   │   │ │Patroni/ │ │    │ │Patroni/ │ │    │ │Patroni/ │ │         │   │
│   │   │ │ CNPG    │ │    │ │ CNPG    │ │    │ │ CNPG    │ │         │   │
│   │   │ └─────────┘ │    │ └─────────┘ │    │ └─────────┘ │         │   │
│   │   └──────┬──────┘    └──────┬──────┘    └──────┬──────┘         │   │
│   │          │                  │                  │                │   │
│   │   ┌──────▼──────┐    ┌──────▼──────┐    ┌──────▼──────┐         │   │
│   │   │    PVC      │    │    PVC      │    │    PVC      │         │   │
│   │   │   50Gi      │    │   50Gi      │    │   50Gi      │         │   │
│   │   └─────────────┘    └─────────────┘    └─────────────┘         │   │
│   │                                                                 │   │
│   └─────────────────────────────────────────────────────────────────┘   │
│                                                                         │
│   Failover automatique :                                                │
│   1. Patroni/CNPG détecte la panne du primary                           │
│   2. Élection d'un nouveau primary parmi les replicas                   │
│   3. Mise à jour du Service postgres-rw vers le nouveau primary         │
│   4. Temps de failover : ~10-30 secondes                                │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

Partie 4 : PostgreSQL Distribué

4.1 Qu'est-ce qu'une Base de Données Distribuée ?

Une base de données distribuée répartit les données sur plusieurs nœuds, offrant :

  • Scalabilité horizontale : Ajouter des nœuds pour augmenter la capacité
  • Haute disponibilité : Tolérance aux pannes de nœuds
  • Distribution géographique : Données proches des utilisateurs
┌─────────────────────────────────────────────────────────────────────────┐
│                    PostgreSQL Standard vs Distribué                     │
│                                                                         │
│   PostgreSQL Standard            PostgreSQL Distribué (ex: Citus)       │
│                                                                         │
│   ┌─────────────────┐            ┌──────────────────┐                   │
│   │                 │            │   Coordinator    │                   │
│   │   Single Node   │            │    (routage)     │                   │
│   │                 │            └────────┬─────────┘                   │
│   │  Toutes les     │                     │                             │
│   │  données ici    │            ┌────────┼────────┐                    │
│   │                 │            ▼        ▼        ▼                    │
│   │                 │      ┌─────────┐ ┌─────────┐ ┌─────────┐          │
│   └─────────────────┘      │ Worker  │ │ Worker  │ │ Worker  │          │
│                            │  Node 1 │ │  Node 2 │ │  Node 3 │          │
│                            │ Shard A │ │ Shard B │ │ Shard C │          │
│                            └─────────┘ └─────────┘ └─────────┘          │
│                                                                         │
│   Scale vertical             Scale horizontal                           │
│   (plus gros serveur)        (plus de serveurs)                         │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

4.2 Citus : PostgreSQL Distribué

Citus transforme PostgreSQL en base de données distribuée tout en conservant la compatibilité SQL.

Concepts Citus

┌─────────────────────────────────────────────────────────────────────────┐
│                    Architecture Citus                                   │
│                                                                         │
│   Application                                                           │
│       │                                                                 │
│       ▼                                                                 │
│   ┌─────────────────────────────────────────────────────────────────┐   │
│   │                     Coordinator Node                            │   │
│   │                                                                 │   │
│   │   • Reçoit les requêtes SQL                                     │   │
│   │   • Parse et planifie la distribution                           │   │
│   │   • Agrège les résultats des workers                            │   │
│   │   • Stocke les métadonnées de distribution                      │   │
│   │                                                                 │   │
│   └───────────────────────────┬─────────────────────────────────────┘   │
│                               │                                         │
│           ┌───────────────────┼───────────────────┐                     │
│           ▼                   ▼                   ▼                     │
│   ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐           │
│   │   Worker Node   │ │   Worker Node   │ │   Worker Node   │           │
│   │                 │ │                 │ │                 │           │
│   │  ┌───────────┐  │ │  ┌───────────┐  │ │  ┌───────────┐  │           │
│   │  │ Shard 1   │  │ │  │ Shard 2   │  │ │  │ Shard 3   │  │           │
│   │  │ Shard 4   │  │ │  │ Shard 5   │  │ │  │ Shard 6   │  │           │
│   │  └───────────┘  │ │  └───────────┘  │ │  └───────────┘  │           │
│   │                 │ │                 │ │                 │           │
│   └─────────────────┘ └─────────────────┘ └─────────────────┘           │
│                                                                         │
│   Types de tables :                                                     │
│   • Distributed : Shardées par clé de distribution                      │
│   • Reference : Répliquées sur tous les workers (petites tables)        │
│   • Local : Tables normales sur le coordinator                          │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

Utilisation de Citus

-- Activer l'extension Citus
CREATE EXTENSION citus;

-- Ajouter des workers au cluster
SELECT citus_add_node('worker1.example.com', 5432);  
SELECT citus_add_node('worker2.example.com', 5432);  
SELECT citus_add_node('worker3.example.com', 5432);  

-- Créer une table distribuée
CREATE TABLE events (
    tenant_id INTEGER,
    event_id BIGSERIAL,
    event_type VARCHAR(50),
    event_data JSONB,
    created_at TIMESTAMP DEFAULT NOW(),
    PRIMARY KEY (tenant_id, event_id)
);

-- Distribuer la table par tenant_id (64 shards par défaut)
SELECT create_distributed_table('events', 'tenant_id');

-- Créer une table de référence (répliquée partout)
CREATE TABLE event_types (
    id SERIAL PRIMARY KEY,
    name VARCHAR(50) UNIQUE
);

SELECT create_reference_table('event_types');

-- Les requêtes SQL standard fonctionnent !
INSERT INTO events (tenant_id, event_type, event_data)  
VALUES (1, 'page_view', '{"url": "/home"}');  

SELECT tenant_id, COUNT(*)  
FROM events  
WHERE created_at > NOW() - INTERVAL '1 day'  
GROUP BY tenant_id;  

-- Requête sur un seul tenant (routée vers un seul shard)
SELECT * FROM events WHERE tenant_id = 42;

Citus sur Azure (Hyperscale)

Azure propose Citus en tant que service managé :

Azure Database for PostgreSQL - Hyperscale (Citus)

Caractéristiques :
• Citus managé par Microsoft
• Auto-scaling des workers
• Backups automatiques
• Monitoring intégré
• SLA 99.99%

4.3 YugabyteDB

YugabyteDB est une base de données distribuée compatible PostgreSQL, conçue from scratch pour le cloud.

Architecture

┌─────────────────────────────────────────────────────────────────────────┐
│                    Architecture YugabyteDB                              │
│                                                                         │
│   ┌─────────────────────────────────────────────────────────────────┐   │
│   │                       YSQL Layer                                │   │
│   │              (Compatible PostgreSQL Wire Protocol)              │   │
│   │                                                                 │   │
│   │   • Parser PostgreSQL                                           │   │
│   │   • Optimizer                                                   │   │
│   │   • Extensions PostgreSQL supportées                            │   │
│   │                                                                 │   │
│   └─────────────────────────────────────────────────────────────────┘   │
│                                │                                        │
│                                ▼                                        │
│   ┌─────────────────────────────────────────────────────────────────┐   │
│   │                    DocDB (Storage Layer)                        │   │
│   │                                                                 │   │
│   │   • Inspiré de Google Spanner                                   │   │
│   │   • Stockage clé-valeur distribué                               │   │
│   │   • Consensus Raft pour la réplication                          │   │
│   │   • Transactions distribuées (2PC)                              │   │
│   │   • Sharding automatique                                        │   │
│   │                                                                 │   │
│   │   ┌─────────┐  ┌─────────┐  ┌─────────┐  ┌─────────┐            │   │
│   │   │ Tablet  │  │ Tablet  │  │ Tablet  │  │ Tablet  │   ...      │   │
│   │   │(Shard)  │  │(Shard)  │  │(Shard)  │  │(Shard)  │            │   │
│   │   └─────────┘  └─────────┘  └─────────┘  └─────────┘            │   │
│   │                                                                 │   │
│   └─────────────────────────────────────────────────────────────────┘   │
│                                                                         │
│   Répartition géographique :                                            │
│                                                                         │
│   US-East           EU-West           Asia-Pacific                      │
│   ┌─────────┐      ┌─────────┐       ┌─────────┐                        │
│   │ YB Node │ ◄──► │ YB Node │ ◄───► │ YB Node │                        │
│   │ (RF=3)  │      │ (RF=3)  │       │ (RF=3)  │                        │
│   └─────────┘      └─────────┘       └─────────┘                        │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

Caractéristiques YugabyteDB

Caractéristique Description
Compatibilité PostgreSQL wire protocol + SQL
Distribution Sharding automatique
Réplication Raft consensus (synchrone)
Consistance Strong consistency (CP dans CAP)
Transactions Distribuées ACID
Géo-distribution Multi-région native
-- YugabyteDB utilise la syntaxe PostgreSQL standard
CREATE TABLE users (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    email VARCHAR(255) UNIQUE,
    name VARCHAR(100),
    created_at TIMESTAMP DEFAULT NOW()
);

-- Tablespaces pour le placement géographique
CREATE TABLESPACE eu_west WITH (
    replica_placement = '{"num_replicas": 3, "placement_blocks": [
        {"cloud": "aws", "region": "eu-west-1", "zone": "eu-west-1a", "min_num_replicas": 1},
        {"cloud": "aws", "region": "eu-west-1", "zone": "eu-west-1b", "min_num_replicas": 1},
        {"cloud": "aws", "region": "eu-west-1", "zone": "eu-west-1c", "min_num_replicas": 1}
    ]}'
);

CREATE TABLE eu_users (LIKE users) TABLESPACE eu_west;

4.4 Comparaison des Solutions Distribuées

Critère Citus YugabyteDB CockroachDB Vitess
Base PostgreSQL Custom (compat PG) Custom (compat PG) MySQL
Compatibilité PG ★★★★★ ★★★★ ★★★ N/A
Transactions distribuées Limitées Oui Oui Limitées
Géo-distribution Manuel Native Native Manuel
Complexité Faible Moyenne Moyenne Élevée
Cas d'usage Multi-tenant SaaS Global apps Global apps Large scale

Partie 5 : Architectures Serverless

5.1 Qu'est-ce que Serverless PostgreSQL ?

Le serverless PostgreSQL élimine la gestion de l'infrastructure :

  • Auto-scaling : Capacité ajustée automatiquement à la charge
  • Pay-per-use : Facturation à l'utilisation réelle
  • Scale-to-zero : Aucun coût quand inactif
  • Instant provisioning : Base disponible en secondes

5.2 Neon : Le Leader Serverless

Neon a réinventé PostgreSQL pour le serverless avec une architecture de séparation compute/stockage.

┌─────────────────────────────────────────────────────────────────────────┐
│                    Architecture Neon                                    │
│                                                                         │
│   ┌─────────────────────────────────────────────────────────────────┐   │
│   │                      Compute Layer                              │   │
│   │                                                                 │   │
│   │   ┌─────────────────┐  ┌─────────────────┐                      │   │
│   │   │ Compute Endpoint│  │ Compute Endpoint│  (scale 0→N)         │   │
│   │   │   (PostgreSQL)  │  │   (PostgreSQL)  │                      │   │
│   │   │    "main"       │  │   "dev-branch"  │                      │   │
│   │   └────────┬────────┘  └────────┬────────┘                      │   │
│   │            │                    │                               │   │
│   └────────────┼────────────────────┼───────────────────────────────┘   │
│                │                    │                                   │
│                │     Neon Proxy     │                                   │
│                │  (connection pool) │                                   │
│                │                    │                                   │
│                └─────────┬──────────┘                                   │
│                          │                                              │
│   ┌──────────────────────▼──────────────────────────────────────────┐   │
│   │                    Pageserver                                   │   │
│   │              (Stockage virtualisé)                              │   │
│   │                                                                 │   │
│   │   • Sert les pages à la demande                                 │   │
│   │   • Cache intelligent                                           │   │
│   │   • Copy-on-write pour le branching                             │   │
│   │                                                                 │   │
│   └──────────────────────┬──────────────────────────────────────────┘   │
│                          │                                              │
│   ┌──────────────────────▼──────────────────────────────────────────┐   │
│   │                    Safekeepers                                  │   │
│   │              (WAL distribué, Paxos)                             │   │
│   │                                                                 │   │
│   │   ┌─────────┐  ┌─────────┐  ┌─────────┐                         │   │
│   │   │   SK1   │  │   SK2   │  │   SK3   │  (quorum = 2/3)         │   │
│   │   └─────────┘  └─────────┘  └─────────┘                         │   │
│   │                                                                 │   │
│   └──────────────────────┬──────────────────────────────────────────┘   │
│                          │                                              │
│   ┌──────────────────────▼──────────────────────────────────────────┐   │
│   │                    Object Storage (S3)                          │   │
│   │              (Stockage durable et économique)                   │   │
│   │                                                                 │   │
│   └─────────────────────────────────────────────────────────────────┘   │
│                                                                         │
│   Fonctionnalités uniques :                                             │
│   • Branching instantané (comme Git pour les données!)                  │
│   • Scale-to-zero (0 coût quand inactif)                                │
│   • Point-in-time restore à la seconde                                  │
│   • Connection pooling intégré                                          │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

Branching Neon

Le branching permet de créer des copies instantanées de votre base :

# Créer une branche pour le développement
neon branch create --name dev-feature-123 --parent main

# La branche est disponible immédiatement avec toutes les données
# Aucune copie physique n'est faite (copy-on-write)

# Connexion à la branche
psql "postgres://user:pass@dev-feature-123.neon.tech/mydb"

Cas d'usage du branching :

  • Preview environments : Une branche par PR
  • Tests : Tester les migrations sur une copie
  • Analytics : Requêtes lourdes sur une branche isolée
  • Debug : Reproduire un bug avec les vraies données

5.3 Supabase

Supabase est une alternative open-source à Firebase, basée sur PostgreSQL.

┌─────────────────────────────────────────────────────────────────────────┐
│                    Architecture Supabase                                │
│                                                                         │
│   ┌─────────────────────────────────────────────────────────────────┐   │
│   │                      Supabase Studio                            │   │
│   │              (Interface d'administration web)                   │   │
│   └─────────────────────────────────────────────────────────────────┘   │
│                                                                         │
│   ┌─────────────────┐  ┌─────────────────┐  ┌─────────────────┐         │
│   │   Auth (GoTrue) │  │  Storage (S3)   │  │   Realtime      │         │
│   │                 │  │                 │  │  (WebSocket)    │         │
│   │  • JWT tokens   │  │  • File upload  │  │  • Subscriptions│         │
│   │  • OAuth/SAML   │  │  • CDN          │  │  • Broadcasts   │         │
│   │  • Row Level    │  │  • Policies     │  │  • Presence     │         │
│   │    Security     │  │                 │  │                 │         │
│   └────────┬────────┘  └────────┬────────┘  └────────┬────────┘         │
│            │                    │                    │                  │
│            └────────────────────┼────────────────────┘                  │
│                                 │                                       │
│   ┌─────────────────────────────▼───────────────────────────────────┐   │
│   │                        PostgREST                                │   │
│   │              (API REST auto-générée depuis le schéma)           │   │
│   └─────────────────────────────┬───────────────────────────────────┘   │
│                                 │                                       │
│   ┌─────────────────────────────▼───────────────────────────────────┐   │
│   │                        PostgreSQL                               │   │
│   │                                                                 │   │
│   │   Extensions incluses :                                         │   │
│   │   • pgvector (IA/ML)                                            │   │
│   │   • PostGIS (géospatial)                                        │   │
│   │   • pg_graphql                                                  │   │
│   │   • pgsodium (encryption)                                       │   │
│   │   • pg_stat_statements                                          │   │
│   │                                                                 │   │
│   └─────────────────────────────────────────────────────────────────┘   │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

Exemple Supabase avec JavaScript

import { createClient } from '@supabase/supabase-js'

const supabase = createClient(
  'https://xxx.supabase.co',
  'your-anon-key'
)

// Requête simple
const { data, error } = await supabase
  .from('users')
  .select('*')
  .eq('status', 'active')

// Insertion
const { data, error } = await supabase
  .from('posts')
  .insert({ title: 'Hello World', user_id: 1 })
  .select()

// Temps réel
supabase
  .channel('posts')
  .on('postgres_changes',
    { event: 'INSERT', schema: 'public', table: 'posts' },
    (payload) => console.log('New post:', payload.new)
  )
  .subscribe()

// Recherche vectorielle (pgvector)
const { data } = await supabase.rpc('match_documents', {
  query_embedding: [0.1, 0.2, ...],
  match_threshold: 0.8,
  match_count: 5
})

5.4 Comparaison des Solutions Serverless

Critère Neon Supabase PlanetScale* Aurora Serverless
Base PostgreSQL PostgreSQL MySQL PostgreSQL
Scale-to-zero Oui Non (plan Pro) Oui Oui (v2)
Branching Oui Non Oui Non
Temps réel Non Oui Non Non
Auth intégré Non Oui Non Non
Open source Oui Oui Non Non
Prix entrée Gratuit Gratuit Gratuit ~$50/mois

*PlanetScale est MySQL mais souvent comparé


Partie 6 : Bonnes Pratiques Cloud-Native

6.1 Connection Pooling

Dans le cloud, les connexions sont précieuses. Utilisez toujours un pooler.

┌─────────────────────────────────────────────────────────────────────────┐
│                    Sans vs Avec Connection Pooling                      │
│                                                                         │
│   SANS POOLING (problème)                                               │
│                                                                         │
│   Lambda/Container 1 ────┐                                              │
│   Lambda/Container 2 ────┼────► PostgreSQL (max_connections = 100)      │
│   Lambda/Container 3 ────┤      Épuisement rapide des connexions!       │
│   ...                    │                                              │
│   Lambda/Container 100 ──┘                                              │
│                                                                         │
│   AVEC POOLING (solution)                                               │
│                                                                         │
│   Lambda/Container 1 ────┐      ┌─────────────┐                         │
│   Lambda/Container 2 ────┼─────►│  PgBouncer  │────► PostgreSQL         │
│   Lambda/Container 3 ────┤      │  (pooler)   │     (20 connexions)     │
│   ...                    │      │ 1000 clients│                         │
│   Lambda/Container 1000 ─┘      └─────────────┘                         │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘
# Déploiement PgBouncer sur Kubernetes
apiVersion: apps/v1  
kind: Deployment  
metadata:  
  name: pgbouncer
spec:
  replicas: 2
  template:
    spec:
      containers:
        - name: pgbouncer
          image: bitnami/pgbouncer:latest
          env:
            - name: POSTGRESQL_HOST
              value: "postgres-primary"
            - name: POSTGRESQL_DATABASE
              value: "mydb"
            - name: PGBOUNCER_POOL_MODE
              value: "transaction"
            - name: PGBOUNCER_MAX_CLIENT_CONN
              value: "1000"
            - name: PGBOUNCER_DEFAULT_POOL_SIZE
              value: "20"

6.2 Secrets et Configuration

# Kubernetes Secret pour les credentials
apiVersion: v1  
kind: Secret  
metadata:  
  name: postgres-credentials
type: Opaque  
stringData:  
  POSTGRES_USER: "myuser"
  POSTGRES_PASSWORD: "super-secret-password"
  POSTGRES_DB: "mydb"
---
# Utilisation dans un Pod
apiVersion: v1  
kind: Pod  
spec:  
  containers:
    - name: app
      env:
        - name: DATABASE_URL
          valueFrom:
            secretKeyRef:
              name: postgres-credentials
              key: POSTGRES_PASSWORD
# AWS Secrets Manager
aws secretsmanager create-secret \
  --name prod/postgres/credentials \
  --secret-string '{"username":"admin","password":"xxx"}'

# Rotation automatique
aws secretsmanager rotate-secret \
  --secret-id prod/postgres/credentials \
  --rotation-lambda-arn arn:aws:lambda:...

6.3 Observabilité

# Stack d'observabilité cloud-native
┌─────────────────────────────────────────────────────────────────────────┐
│                                                                         │
│   Métriques                    Logs                     Traces          │
│   ┌─────────────┐             ┌─────────────┐         ┌─────────────┐   │
│   │ Prometheus  │             │   Loki /    │         │   Jaeger /  │   │
│   │ + postgres  │             │ CloudWatch  │         │   Tempo     │   │
│   │   exporter  │             │             │         │             │   │
│   └──────┬──────┘             └──────┬──────┘         └──────┬──────┘   │
│          │                           │                       │          │
│          └───────────────────────────┼───────────────────────┘          │
│                                      │                                  │
│                              ┌───────▼───────┐                          │
│                              │    Grafana    │                          │
│                              │  (Dashboard)  │                          │
│                              └───────────────┘                          │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘
# ServiceMonitor pour Prometheus (avec postgres_exporter)
apiVersion: monitoring.coreos.com/v1  
kind: ServiceMonitor  
metadata:  
  name: postgres-monitor
spec:
  selector:
    matchLabels:
      app: postgres
  endpoints:
    - port: metrics
      interval: 30s
      path: /metrics

6.4 Disaster Recovery Multi-Cloud

┌────────────────────────────────────────────────────────────────────────┐
│                    Architecture DR Multi-Cloud                         │
│                                                                        │
│   Cloud Principal (AWS)                Cloud DR (GCP)                  │
│                                                                        │
│   ┌─────────────────────┐              ┌─────────────────────┐         │
│   │   Region us-east-1  │              │   Region us-central │         │
│   │                     │              │                     │         │
│   │  ┌─────────────┐    │    WAL       │  ┌─────────────┐    │         │
│   │  │   Primary   │────┼──────────────┼─►│   Standby   │    │         │
│   │  │  (Aurora)   │    │   Streaming  │  │ (Cloud SQL) │    │         │
│   │  └─────────────┘    │              │  └─────────────┘    │         │
│   │        │            │              │                     │         │
│   │        ▼            │              │                     │         │
│   │  ┌─────────────┐    │              │  ┌──────────────┐   │         │
│   │  │  S3 Bucket  │────┼──────────────┼─►│  GCS Bucket  │   │         │
│   │  │  (Backups)  │    │  Cross-cloud │  │  (Backups)   │   │         │
│   │  └─────────────┘    │  replication │  └──────────────┘   │         │
│   │                     │              │                     │         │
│   └─────────────────────┘              └─────────────────────┘         │
│                                                                        │
│   RPO (Recovery Point Objective) : < 1 minute                          │
│   RTO (Recovery Time Objective) : < 15 minutes                         │
│                                                                        │
└────────────────────────────────────────────────────────────────────────┘

Résumé

Ce chapitre a exploré PostgreSQL dans les architectures cloud modernes :

Concept Ce qu'il faut retenir
Services managés RDS, Aurora, Cloud SQL, AlloyDB
Kubernetes Operators (CNPG, Zalando), StatefulSets
Distribué Citus, YugabyteDB pour le scale horizontal
Serverless Neon, Supabase, Aurora Serverless v2
Bonnes pratiques Pooling, secrets, observabilité

Points Clés

  • Les services managés simplifient l'opérationnel mais réduisent le contrôle
  • Kubernetes + Operators offrent un bon équilibre contrôle/automatisation
  • Citus est idéal pour le multi-tenant SaaS
  • YugabyteDB et CockroachDB pour les applications globales
  • Neon révolutionne le développement avec le branching
  • Le connection pooling est obligatoire dans le cloud

Choisir la Bonne Solution

┌─────────────────────────────────────────────────────────────────────────┐
│                    Arbre de Décision                                    │
│                                                                         │
│   Besoin de scale horizontal ?                                          │
│   ├─► Oui ──► Transactions distribuées importantes ?                    │
│   │           ├─► Oui ──► YugabyteDB / CockroachDB                      │
│   │           └─► Non ──► Citus (surtout si multi-tenant)               │
│   │                                                                     │
│   └─► Non ──► Besoin de simplicité maximale ?                           │
│               ├─► Oui ──► Service managé (RDS, Cloud SQL)               │
│               └─► Non ──► Besoin de contrôle ?                          │
│                           ├─► Oui ──► Kubernetes + Operator             │
│                           └─► Non ──► Serverless (Neon, Supabase)       │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

⏭️ Columnar storage (Hydra, pg_analytics)