Skip to content

Latest commit

 

History

History
1360 lines (1132 loc) · 59.8 KB

File metadata and controls

1360 lines (1132 loc) · 59.8 KB

🔝 Retour au Sommaire

20bis.4.2. Operators : Zalando, CloudNativePG, Crunchy

Introduction

Dans le chapitre précédent, nous avons vu que les StatefulSets fournissent les briques de base pour exécuter PostgreSQL sur Kubernetes : identité stable, persistance des données et ordre de déploiement. Cependant, ils ne gèrent pas la logique métier spécifique à PostgreSQL.

C'est là qu'interviennent les Operators. Un Operator est un composant qui automatise la gestion complète d'une application sur Kubernetes, en encapsulant l'expertise d'un administrateur de base de données dans du code.

Dans ce chapitre, nous explorerons trois Operators PostgreSQL majeurs : Zalando Postgres Operator, CloudNativePG et Crunchy Postgres Operator. Vous comprendrez leurs forces, leurs différences et comment choisir celui qui convient à votre projet.


Qu'est-ce qu'un Operator ?

Le Concept Fondamental

Un Operator est un logiciel qui étend Kubernetes pour gérer des applications complexes de manière automatisée. Il encode les connaissances d'un expert humain dans un contrôleur logiciel.

┌─────────────────────────────────────────────────────────────────────┐
│                    LE CONCEPT D'OPERATOR                            │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│   SANS OPERATOR (Gestion manuelle)                                  │
│   ────────────────────────────────                                  │
│                                                                     │
│   Administrateur humain doit :                                      │
│   • Configurer la réplication                                       │
│   • Surveiller la santé du cluster                                  │
│   • Gérer les failovers manuellement                                │
│   • Planifier et exécuter les backups                               │
│   • Gérer les mises à jour                                          │
│   • Réagir aux pannes (souvent la nuit !)                           │
│                                                                     │
│                                                                     │
│   AVEC OPERATOR (Gestion automatisée)                               │
│   ───────────────────────────────────                               │
│                                                                     │
│   L'Operator fait tout automatiquement :                            │
│   • Configure la réplication ✓                                      │
│   • Surveille en continu ✓                                          │
│   • Failover automatique en secondes ✓                              │
│   • Backups planifiés ✓                                             │
│   • Rolling updates ✓                                               │
│   • Self-healing 24/7 ✓                                             │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

Le Pattern Operator

Un Operator fonctionne selon un cycle de réconciliation continu :

                    BOUCLE DE RÉCONCILIATION
                    ────────────────────────

     ┌─────────────────────────────────────────────────────┐
     │                                                     │
     │   1. OBSERVER                                       │
     │      L'Operator surveille l'état actuel             │
     │      du cluster PostgreSQL                          │
     │                                                     │
     └─────────────────────┬───────────────────────────────┘
                           │
                           ▼
     ┌─────────────────────────────────────────────────────┐
     │                                                     │
     │   2. COMPARER                                       │
     │      État actuel vs État désiré                     │
     │      (défini dans le Custom Resource)               │
     │                                                     │
     └─────────────────────┬───────────────────────────────┘
                           │
                           ▼
     ┌─────────────────────────────────────────────────────┐
     │                                                     │
     │   3. AGIR                                           │
     │      Si différence détectée :                       │
     │      → Appliquer les changements nécessaires        │
     │      → Créer/modifier/supprimer des ressources      │
     │                                                     │
     └─────────────────────┬───────────────────────────────┘
                           │
                           └──────────► Retour à l'étape 1
                                        (boucle continue)

Custom Resources (CR) et Custom Resource Definitions (CRD)

Les Operators introduisent de nouveaux types de ressources dans Kubernetes :

# Exemple de Custom Resource pour PostgreSQL
apiVersion: postgresql.example.com/v1  
kind: PostgresCluster        # ← Nouveau type de ressource !  
metadata:  
  name: my-postgres
spec:
  instances: 3
  storage: 100Gi
  version: "16"
  backup:
    schedule: "0 2 * * *"    # Backup à 2h du matin

Au lieu de gérer manuellement des StatefulSets, Services, ConfigMaps, etc., vous déclarez simplement ce que vous voulez et l'Operator s'occupe du comment.

SANS OPERATOR                           AVEC OPERATOR
─────────────                           ─────────────

Vous gérez :                            Vous gérez :
• 1 StatefulSet                         • 1 Custom Resource
• 1 Service Headless                       (PostgresCluster)
• 1 Service ClusterIP
• 1 ConfigMap                           L'Operator gère :
• 1 Secret                              • Tout le reste
• N PersistentVolumeClaims                automatiquement !
• Scripts de réplication
• Scripts de backup
• Monitoring config
• ...

~500 lignes de YAML                     ~30 lignes de YAML

Pourquoi Utiliser un Operator pour PostgreSQL ?

Les Défis de PostgreSQL en Production

Exécuter PostgreSQL en production sur Kubernetes implique de nombreux défis :

Défi Complexité sans Operator
Réplication streaming Configuration manuelle de primary/replica
Failover Détection de panne + promotion manuelle
Backups Scripts cron + stockage + rétention
Restauration Procédure manuelle, risque d'erreur
Mises à jour Rolling update délicat
Scaling Ajout de replicas avec réplication
Monitoring Configuration Prometheus/exporters
TLS Génération et rotation des certificats

Ce qu'un Operator Apporte

┌─────────────────────────────────────────────────────────────────────┐
│                 FONCTIONNALITÉS D'UN OPERATOR POSTGRESQL            │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│  ┌──────────────────────┐  ┌──────────────────────┐                 │
│  │ HAUTE DISPONIBILITÉ  │  │      BACKUPS         │                 │
│  │                      │  │                      │                 │
│  │ • Réplication auto   │  │ • Backups planifiés  │                 │
│  │ • Failover auto      │  │ • Stockage S3/GCS    │                 │
│  │ • Leader election    │  │ • Rétention auto     │                 │
│  │ • Health checks      │  │ • PITR               │                 │
│  └──────────────────────┘  └──────────────────────┘                 │
│                                                                     │
│  ┌──────────────────────┐  ┌──────────────────────┐                 │
│  │     SÉCURITÉ         │  │    OBSERVABILITÉ     │                 │
│  │                      │  │                      │                 │
│  │ • TLS automatique    │  │ • Métriques Prom.    │                 │
│  │ • Rotation secrets   │  │ • Logs centralisés   │                 │
│  │ • RBAC intégré       │  │ • Alertes            │                 │
│  │ • Network policies   │  │ • Dashboards         │                 │
│  └──────────────────────┘  └──────────────────────┘                 │
│                                                                     │
│  ┌──────────────────────┐  ┌──────────────────────┐                 │
│  │   CYCLE DE VIE       │  │     SCALING          │                 │
│  │                      │  │                      │                 │
│  │ • Provisioning       │  │ • Horizontal (repl.) │                 │
│  │ • Updates            │  │ • Vertical (ressour.)│                 │
│  │ • Minor upgrades     │  │ • Connection pooling │                 │
│  │ • Major upgrades     │  │ • Read replicas      │                 │
│  └──────────────────────┘  └──────────────────────┘                 │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

Zalando Postgres Operator

Présentation

Le Zalando Postgres Operator a été développé par Zalando, le géant européen du e-commerce. En production chez Zalando depuis 2017, il gère des milliers de clusters PostgreSQL.

┌─────────────────────────────────────────────────────────────────────┐
│                    ZALANDO POSTGRES OPERATOR                        │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│  Créateur    : Zalando SE (Allemagne)                               │
│  Depuis      : 2017                                                 │
│  Licence     : MIT                                                  │
│  GitHub      : github.com/zalando/postgres-operator                 │
│  Maturité    : Production-ready, très utilisé                       │
│                                                                     │
│  Points forts :                                                     │
│  • Simplicité de configuration                                      │
│  • Intégration AWS native (S3, IAM)                                 │
│  • Connection pooling intégré (PgBouncer)                           │
│  • Interface Web (UI) optionnelle                                   │
│  • Large communauté                                                 │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

Architecture

                    ARCHITECTURE ZALANDO OPERATOR
                    ─────────────────────────────

┌───────────────────────────────────────────────────────────────────┐
│                         KUBERNETES CLUSTER                        │
│                                                                   │
│   ┌──────────────────────────────────────────────────────────┐    │
│   │              POSTGRES OPERATOR (Deployment)              │    │
│   │                                                          │    │
│   │   Surveille les ressources "postgresql"                  │    │
│   │   Crée et gère les clusters PostgreSQL                   │    │
│   └─────────────────────────┬────────────────────────────────┘    │
│                             │                                     │
│                             │ Gère                                │
│                             ▼                                     │
│   ┌──────────────────────────────────────────────────────────┐    │
│   │              CLUSTER POSTGRESQL "my-db"                  │    │
│   │                                                          │    │
│   │   ┌───────────┐  ┌───────────┐  ┌───────────┐            │    │
│   │   │my-db-0    │  │my-db-1    │  │my-db-2    │            │    │
│   │   │(Primary)  │  │(Replica)  │  │(Replica)  │            │    │
│   │   │           │  │           │  │           │            │    │
│   │   │┌─────────┐│  │┌─────────┐│  │┌─────────┐│            │    │
│   │   ││Postgres ││  ││Postgres ││  ││Postgres ││            │    │
│   │   │└─────────┘│  │└─────────┘│  │└─────────┘│            │    │
│   │   │┌─────────┐│  │┌─────────┐│  │┌─────────┐│            │    │
│   │   ││ Patroni ││  ││ Patroni ││  ││ Patroni ││            │    │
│   │   │└─────────┘│  │└─────────┘│  │└─────────┘│            │    │
│   │   └─────┬─────┘  └─────┬─────┘  └─────┬─────┘            │    │
│   │         │              │              │                  │    │
│   │         └──────────────┼──────────────┘                  │    │
│   │                        ▼                                 │    │
│   │              ┌─────────────────┐                         │    │
│   │              │     Spilo       │  Image Docker contenant │    │
│   │              │ (PostgreSQL +   │  PostgreSQL + Patroni   │    │
│   │              │  Patroni + ...) │  + outils               │    │
│   │              └─────────────────┘                         │    │
│   │                                                          │    │
│   └──────────────────────────────────────────────────────────┘    │
│                                                                   │
└───────────────────────────────────────────────────────────────────┘

Composants Clés

Composant Rôle
Postgres Operator Contrôleur qui gère le cycle de vie des clusters
Spilo Image Docker contenant PostgreSQL + Patroni + outils
Patroni Gestion du failover et de la haute disponibilité
PgBouncer Connection pooling (optionnel)

Custom Resource : postgresql

# Exemple de cluster Zalando
apiVersion: "acid.zalan.do/v1"  
kind: postgresql  
metadata:  
  name: my-postgres-cluster
  namespace: default
spec:
  teamId: "myteam"                    # Préfixe pour les ressources

  # Configuration du cluster
  numberOfInstances: 3                 # 1 primary + 2 replicas

  # Version PostgreSQL
  postgresql:
    version: "16"
    parameters:
      max_connections: "100"
      shared_buffers: "256MB"

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

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

  # Utilisateurs et bases
  users:
    myapp_user:
      - superuser
      - createdb
    readonly_user: []

  databases:
    myapp_db: myapp_user              # base: owner

  # Connection pooling
  enableConnectionPooler: true
  connectionPooler:
    numberOfInstances: 2
    mode: "transaction"

  # Backups vers S3
  backup:
    enableWALBackup: true

Fonctionnalités Principales

1. Haute Disponibilité avec Patroni

Zalando utilise Patroni pour la haute disponibilité :

FAILOVER AUTOMATIQUE AVEC PATRONI
─────────────────────────────────

État normal :
┌─────────────┐     ┌─────────────┐     ┌─────────────┐
│  my-db-0    │     │  my-db-1    │     │  my-db-2    │
│  (Primary)  │────►│  (Replica)  │     │  (Replica)  │
│             │────►│             │     │             │
└─────────────┘     └─────────────┘     └─────────────┘
      │                   ▲                   ▲
      └───────────────────┴───────────────────┘
              Réplication streaming


Le Primary tombe :
┌─────────────┐     ┌─────────────┐     ┌─────────────┐
│  my-db-0    │     │  my-db-1    │     │  my-db-2    │
│    ╳ DOWN   │     │  (Replica)  │     │  (Replica)  │
└─────────────┘     └─────────────┘     └─────────────┘

                           │
                           │ Patroni détecte (~10s)
                           │ Élection du nouveau leader
                           ▼

┌─────────────┐     ┌─────────────┐     ┌─────────────┐
│  my-db-0    │     │  my-db-1    │     │  my-db-2    │
│  (à recréer)│◄────│ (NOUVEAU    │────►│  (Replica)  │
│             │     │  PRIMARY)   │     │             │
└─────────────┘     └─────────────┘     └─────────────┘

Temps de failover : ~10-30 secondes

2. Connection Pooling Intégré

# Activer PgBouncer
spec:
  enableConnectionPooler: true
  connectionPooler:
    numberOfInstances: 2
    mode: "transaction"      # ou "session"
    maxDBConnections: 100

L'Operator crée automatiquement :

  • Des Pods PgBouncer
  • Un Service pour accéder au pooler
  • La configuration appropriée

3. Gestion des Utilisateurs et Bases

spec:
  users:
    admin_user:
      - superuser
      - createdb
    app_user:
      - login
    readonly_user:
      - login

  databases:
    production_db: admin_user
    analytics_db: admin_user

Les mots de passe sont automatiquement générés et stockés dans des Secrets Kubernetes.

4. Backups vers S3

# Configuration dans l'Operator (ConfigMap)
configuration:
  aws_region: eu-west-1
  wal_s3_bucket: my-postgres-backups

# Ou dans le cluster
spec:
  backup:
    enableWALBackup: true

Installation de Zalando Operator

# Cloner le dépôt
git clone https://github.com/zalando/postgres-operator.git  
cd postgres-operator  

# Installer avec kubectl
kubectl create -f manifests/configmap.yaml  
kubectl create -f manifests/operator-service-account-rbac.yaml  
kubectl create -f manifests/postgres-operator.yaml  

# Ou avec Helm
helm repo add postgres-operator-charts \
  https://opensource.zalando.com/postgres-operator/charts/postgres-operator
helm install postgres-operator postgres-operator-charts/postgres-operator

CloudNativePG

Présentation

CloudNativePG (anciennement CloudNative-PG) est un Operator développé initialement par EDB (EnterpriseDB) puis donné à la CNCF (Cloud Native Computing Foundation). Il est conçu nativement pour Kubernetes, sans dépendances externes.

┌─────────────────────────────────────────────────────────────────────┐
│                         CLOUDNATIVEPG                               │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│  Créateur    : EDB, maintenant projet CNCF                          │
│  Depuis      : 2020                                                 │
│  Licence     : Apache 2.0                                           │
│  GitHub      : github.com/cloudnative-pg/cloudnative-pg             │
│  Maturité    : Production-ready, en forte croissance                │
│                                                                     │
│  Points forts :                                                     │
│  • Architecture Kubernetes-native pure                              │
│  • Pas de dépendances externes (pas de Patroni/etcd)                │
│  • Excellente documentation                                         │
│  • Support officiel disponible (EDB)                                │
│  • Projet CNCF (gouvernance neutre)                                 │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

Architecture

CloudNativePG se distingue par son approche Kubernetes-native : il utilise les mécanismes natifs de Kubernetes (leases, endpoints) plutôt que des outils externes.

                    ARCHITECTURE CLOUDNATIVEPG
                    ──────────────────────────

┌──────────────────────────────────────────────────────────────────┐
│                         KUBERNETES CLUSTER                       │
│                                                                  │
│   ┌─────────────────────────────────────────────────────────┐    │
│   │            CLOUDNATIVEPG OPERATOR (Deployment)          │    │
│   │                                                         │    │
│   │   • Surveille les ressources "Cluster"                  │    │
│   │   • Gère le failover via Kubernetes Leases              │    │
│   │   • Pas de dépendance externe (Patroni, etcd)           │    │
│   └─────────────────────────┬───────────────────────────────┘    │
│                             │                                    │
│                             │ Gère                               │
│                             ▼                                    │
│   ┌─────────────────────────────────────────────────────────┐    │
│   │                   CLUSTER "my-cluster"                  │    │
│   │                                                         │    │
│   │   ┌───────────────┐                                     │    │
│   │   │my-cluster-1   │  ← Primary                          │    │
│   │   │               │                                     │    │
│   │   │ ┌───────────┐ │                                     │    │
│   │   │ │ PostgreSQL│ │                                     │    │
│   │   │ │   16      │ │                                     │    │
│   │   │ └───────────┘ │                                     │    │
│   │   │ ┌───────────┐ │                                     │    │
│   │   │ │ Instance  │ │  Gestionnaire intégré               │    │
│   │   │ │ Manager   │ │  (pas de Patroni)                   │    │
│   │   │ └───────────┘ │                                     │    │
│   │   └───────┬───────┘                                     │    │
│   │           │ Réplication                                 │    │
│   │           ▼                                             │    │
│   │   ┌───────────────┐  ┌───────────────┐                  │    │
│   │   │my-cluster-2   │  │my-cluster-3   │                  │    │
│   │   │ (Replica)     │  │ (Replica)     │                  │    │
│   │   └───────────────┘  └───────────────┘                  │    │
│   │                                                         │    │
│   └─────────────────────────────────────────────────────────┘    │
│                                                                  │
└──────────────────────────────────────────────────────────────────┘

Custom Resource : Cluster

# Exemple de cluster CloudNativePG
apiVersion: postgresql.cnpg.io/v1  
kind: Cluster  
metadata:  
  name: my-cluster
  namespace: default
spec:
  # Nombre d'instances (1 primary + N-1 replicas)
  instances: 3

  # Version PostgreSQL
  imageName: ghcr.io/cloudnative-pg/postgresql:16.2

  # Configuration PostgreSQL
  postgresql:
    parameters:
      max_connections: "100"
      shared_buffers: "256MB"
      effective_cache_size: "1GB"
    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: "1"

  # Bootstrap (initialisation)
  bootstrap:
    initdb:
      database: myapp
      owner: myapp_user
      secret:
        name: myapp-credentials

  # Backups
  backup:
    barmanObjectStore:
      destinationPath: s3://my-bucket/backups
      s3Credentials:
        accessKeyId:
          name: s3-creds
          key: ACCESS_KEY_ID
        secretAccessKey:
          name: s3-creds
          key: SECRET_ACCESS_KEY
    retentionPolicy: "7d"

  # Monitoring
  monitoring:
    enablePodMonitor: true

Fonctionnalités Principales

1. Failover Kubernetes-Native

CloudNativePG utilise les Leases Kubernetes pour l'élection du leader :

FAILOVER AVEC LEASES KUBERNETES
───────────────────────────────

                    ┌─────────────────────┐
                    │  Kubernetes Lease   │
                    │  "my-cluster-leader"│
                    │                     │
                    │  holder: cluster-1  │
                    └──────────┬──────────┘
                               │
         ┌─────────────────────┼─────────────────────┐
         │                     │                     │
         ▼                     ▼                     ▼
  ┌─────────────┐      ┌───────────────┐      ┌───────────────┐
  │  cluster-1  │      │  cluster-2    │      │  cluster-3    │
  │  (Primary)  │      │  (Replica)    │      │  (Replica)    │
  │             │      │               │      │               │
  │ "J'ai la    │      │ "Je surveille │      │ "Je surveille │
  │  Lease !"   │      │  la Lease"    │      │  la Lease"    │
  └─────────────┘      └───────────────┘      └───────────────┘

Si cluster-1 tombe :
1. La Lease expire
2. cluster-2 ou cluster-3 l'acquiert
3. Le nouveau holder devient Primary

Pas besoin de Patroni, etcd ou autre composant externe !

2. Backup avec Barman

CloudNativePG utilise Barman pour les backups :

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

Créer un backup à la demande :

apiVersion: postgresql.cnpg.io/v1  
kind: Backup  
metadata:  
  name: my-backup
spec:
  cluster:
    name: my-cluster

3. Point-In-Time Recovery (PITR)

Restaurer à un moment précis :

apiVersion: postgresql.cnpg.io/v1  
kind: Cluster  
metadata:  
  name: restored-cluster
spec:
  instances: 3

  bootstrap:
    recovery:
      source: my-cluster
      recoveryTarget:
        targetTime: "2024-01-15 10:30:00"

  externalClusters:
    - name: my-cluster
      barmanObjectStore:
        destinationPath: s3://my-bucket/backups
        s3Credentials:
          accessKeyId:
            name: s3-creds
            key: ACCESS_KEY_ID
          secretAccessKey:
            name: s3-creds
            key: SECRET_ACCESS_KEY

4. Replica Clusters (Disaster Recovery)

Créer un cluster replica dans une autre région :

apiVersion: postgresql.cnpg.io/v1  
kind: Cluster  
metadata:  
  name: dr-cluster
  namespace: default
spec:
  instances: 3

  # Ce cluster réplique depuis un autre cluster
  replica:
    enabled: true
    source: main-cluster

  externalClusters:
    - name: main-cluster
      connectionParameters:
        host: main-cluster-rw.primary-region.svc
        user: streaming_replica
      password:
        name: replica-credentials
        key: password

5. Monitoring Intégré

CloudNativePG expose des métriques Prometheus automatiquement :

spec:
  monitoring:
    enablePodMonitor: true    # Crée un PodMonitor pour Prometheus
    customQueriesConfigMap:
      - name: custom-queries
        key: queries

Installation de CloudNativePG

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

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

Crunchy Postgres Operator (PGO)

Présentation

Le Crunchy Postgres Operator (aussi appelé PGO) est développé par Crunchy Data, un des principaux contributeurs à PostgreSQL. C'est l'un des Operators les plus complets et les plus matures.

┌─────────────────────────────────────────────────────────────────────┐
│                    CRUNCHY POSTGRES OPERATOR (PGO)                  │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│  Créateur    : Crunchy Data                                         │
│  Depuis      : 2017                                                 │
│  Licence     : Apache 2.0                                           │
│  GitHub      : github.com/CrunchyData/postgres-operator             │
│  Maturité    : Production-ready, très mature                        │
│                                                                     │
│  Points forts :                                                     │
│  • Fonctionnalités très complètes                                   │
│  • pgBackRest pour backups (robuste)                                │
│  • Support commercial disponible                                    │
│  • Excellent pour les environnements enterprise                     │
│  • Intégration avec l'écosystème Crunchy                            │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

Architecture

                    ARCHITECTURE CRUNCHY PGO
                    ────────────────────────

┌──────────────────────────────────────────────────────────────────┐
│                         KUBERNETES CLUSTER                       │
│                                                                  │
│   ┌─────────────────────────────────────────────────────────┐    │
│   │                    PGO OPERATOR                         │    │
│   │                                                         │    │
│   │   Surveille les ressources "PostgresCluster"            │    │
│   └─────────────────────────┬───────────────────────────────┘    │
│                             │                                    │
│                             │ Gère                               │
│                             ▼                                    │
│   ┌─────────────────────────────────────────────────────────┐    │
│   │                POSTGRESCLUSTER "hippo"                  │    │
│   │                                                         │    │
│   │  ┌─────────────────────────────────────────────────┐    │    │
│   │  │              INSTANCE SET "instance1"           │    │    │
│   │  │                                                 │    │    │
│   │  │  ┌────────────┐ ┌────────────┐ ┌────────────┐   │    │    │
│   │  │  │ hippo-     │ │ hippo-     │ │ hippo-     │   │    │    │
│   │  │  │ instance1  │ │ instance1  │ │ instance1  │   │    │    │
│   │  │  │ -xxxx      │ │ -yyyy      │ │ -zzzz      │   │    │    │
│   │  │  │            │ │            │ │            │   │    │    │
│   │  │  │┌──────────┐│ │┌──────────┐│ │┌──────────┐│   │    │    │
│   │  │  ││PostgreSQL││ ││PostgreSQL││ ││PostgreSQL││   │    │    │
│   │  │  │└──────────┘│ │└──────────┘│ │└──────────┘│   │    │    │
│   │  │  │┌──────────┐│ │┌──────────┐│ │┌──────────┐│   │    │    │
│   │  │  ││ Patroni  ││ ││ Patroni  ││ ││ Patroni  ││   │    │    │
│   │  │  │└──────────┘│ │└──────────┘│ │└──────────┘│   │    │    │
│   │  │  └────────────┘ └────────────┘ └────────────┘   │    │    │
│   │  └─────────────────────────────────────────────────┘    │    │
│   │                                                         │    │
│   │  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐      │    │
│   │  │ PgBouncer   │  │ pgBackRest  │  │ pg_exporter │      │    │
│   │  │ (Pooler)    │  │ (Backup)    │  │ (Metrics)   │      │    │
│   │  └─────────────┘  └─────────────┘  └─────────────┘      │    │
│   │                                                         │    │
│   └─────────────────────────────────────────────────────────┘    │
│                                                                  │
└──────────────────────────────────────────────────────────────────┘

Custom Resource : PostgresCluster

# Exemple de cluster Crunchy PGO
apiVersion: postgres-operator.crunchydata.com/v1beta1  
kind: PostgresCluster  
metadata:  
  name: hippo
spec:
  # Version PostgreSQL
  postgresVersion: 16

  # Instances PostgreSQL
  instances:
    - name: instance1
      replicas: 3
      dataVolumeClaimSpec:
        accessModes:
          - ReadWriteOnce
        resources:
          requests:
            storage: 50Gi
        storageClassName: fast-ssd
      resources:
        requests:
          cpu: "500m"
          memory: "1Gi"
        limits:
          cpu: "1"
          memory: "2Gi"

  # Configuration PostgreSQL
  patroni:
    dynamicConfiguration:
      postgresql:
        parameters:
          max_connections: "100"
          shared_buffers: "256MB"

  # Utilisateurs
  users:
    - name: hippo
      databases:
        - hippo
      options: "SUPERUSER"
    - name: app_user
      databases:
        - hippo

  # Backups avec pgBackRest
  backups:
    pgbackrest:
      image: registry.developers.crunchydata.com/crunchydata/crunchy-pgbackrest:ubi8-2.47-2
      repos:
        - name: repo1
          schedules:
            full: "0 1 * * 0"        # Full backup dimanche 1h
            differential: "0 1 * * 1-6"  # Diff backup autres jours
          volume:
            volumeClaimSpec:
              accessModes:
                - ReadWriteOnce
              resources:
                requests:
                  storage: 100Gi
        - name: repo2
          s3:
            bucket: "my-postgres-backups"
            endpoint: "s3.amazonaws.com"
            region: "us-east-1"

  # Connection pooling
  proxy:
    pgBouncer:
      replicas: 2
      config:
        global:
          pool_mode: transaction

  # Monitoring
  monitoring:
    pgmonitor:
      exporter:
        image: registry.developers.crunchydata.com/crunchydata/crunchy-postgres-exporter:ubi8-5.5.0-0

Fonctionnalités Principales

1. Backups Robustes avec pgBackRest

Crunchy utilise pgBackRest, l'outil de backup le plus robuste pour PostgreSQL :

TYPES DE BACKUPS pgBackRest
───────────────────────────

┌─────────────────────────────────────────────────────────────────┐
│                                                                 │
│  FULL BACKUP (Dimanche)                                         │
│  ═══════════════════════                                        │
│  Copie complète de la base                                      │
│  ~50 Go                                                         │
│                                                                 │
│  DIFFERENTIAL BACKUP (Lundi-Samedi)                             │
│  ═════════════════════════════════                              │
│  Seulement les changements depuis le dernier FULL               │
│  ~5-10 Go                                                       │
│                                                                 │
│  INCREMENTAL BACKUP (Optionnel, plus fréquent)                  │
│  ═════════════════════════════════════════════                  │
│  Seulement les changements depuis le dernier backup (any)       │
│  ~1-2 Go                                                        │
│                                                                 │
│  + WAL Archiving en continu                                     │
│    Permet PITR à n'importe quelle seconde                       │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

Configuration multi-repo (local + S3) :

backups:
  pgbackrest:
    repos:
      - name: repo1
        volume:                    # Repo local (rapide)
          volumeClaimSpec:
            storage: 100Gi
      - name: repo2
        s3:                        # Repo S3 (DR)
          bucket: "pg-backups"
          endpoint: "s3.amazonaws.com"
          region: "us-east-1"

2. Clone et Restauration

Cloner un cluster existant :

apiVersion: postgres-operator.crunchydata.com/v1beta1  
kind: PostgresCluster  
metadata:  
  name: hippo-clone
spec:
  postgresVersion: 16

  dataSource:
    postgresCluster:
      clusterName: hippo
      repoName: repo1

  instances:
    - name: instance1
      replicas: 3
      dataVolumeClaimSpec:
        storage: 50Gi

Restauration PITR :

dataSource:
  postgresCluster:
    clusterName: hippo
    repoName: repo1
    options:
      - --type=time
      - --target="2024-01-15 10:30:00"

3. Connection Pooling avec PgBouncer

spec:
  proxy:
    pgBouncer:
      replicas: 2
      config:
        global:
          pool_mode: transaction
          max_client_conn: "1000"
          default_pool_size: "20"
      resources:
        requests:
          cpu: "100m"
          memory: "128Mi"

4. Affinity et Topologie

Contrôle fin du placement des Pods :

instances:
  - name: instance1
    replicas: 3
    affinity:
      podAntiAffinity:
        preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 100
            podAffinityTerm:
              topologyKey: "topology.kubernetes.io/zone"
              labelSelector:
                matchLabels:
                  postgres-operator.crunchydata.com/cluster: hippo

5. TLS Automatique

PGO génère et gère automatiquement les certificats TLS :

spec:
  customTLSSecret:
    name: hippo-tls        # Optionnel : utiliser vos propres certificats

  # Sinon, certificats auto-générés

Installation de Crunchy PGO

# Avec kubectl (méthode recommandée)
kubectl apply -k \
  github.com/CrunchyData/postgres-operator-examples/kustomize/install/default

# Ou avec Helm
helm repo add crunchydata https://crunchydata.github.io/postgres-operator  
helm install pgo crunchydata/pgo  

Comparaison des Trois Operators

Tableau Comparatif Détaillé

Aspect Zalando CloudNativePG Crunchy PGO
Licence MIT Apache 2.0 Apache 2.0
Maturité Très mature (2017) Mature (2020) Très mature (2017)
HA Solution Patroni Kubernetes-native Patroni
Backup Tool WAL-E/WAL-G Barman pgBackRest
Connection Pooler PgBouncer intégré Externe (PgBouncer) PgBouncer intégré
Dépendances externes Patroni, S3 Aucune Patroni
Complexité config Simple Moyenne Avancée
Support commercial Non (Zalando interne) Oui (EDB) Oui (Crunchy)
Projet CNCF Non Oui (Sandbox) Non
Documentation Bonne Excellente Excellente
Communauté Grande En croissance Grande

Forces et Faiblesses

┌─────────────────────────────────────────────────────────────────────┐
│                          ZALANDO OPERATOR                           │
├─────────────────────────────────────────────────────────────────────┤
│  ✅ Forces                        │  ⚠️ Faiblesses                  │
│  ─────────────────────────────    │  ─────────────────────────────  │
│  • Configuration simple           │  • Moins flexible               │
│  • UI web disponible              │  • Pas de support commercial    │
│  • PgBouncer natif                │  • Moins de features backup     │
│  • Battle-tested chez Zalando     │  • Dépend de Patroni/etcd       │
└─────────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────────┐
│                          CLOUDNATIVEPG                              │
├─────────────────────────────────────────────────────────────────────┤
│  ✅ Forces                        │  ⚠️ Faiblesses                  │
│  ─────────────────────────────    │  ─────────────────────────────  │
│  • Kubernetes-native pur          │  • Plus récent                  │
│  • Pas de dépendances externes    │  • Moins de plugins/intégrations│
│  • Documentation excellente       │  • Courbe d'apprentissage       │
│  • Projet CNCF                    │  • PgBouncer externe            │
│  • Architecture élégante          │                                 │
└─────────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────────┐
│                          CRUNCHY PGO                                │
├─────────────────────────────────────────────────────────────────────┤
│  ✅ Forces                        │  ⚠️ Faiblesses                  │
│  ─────────────────────────────    │  ─────────────────────────────  │
│  • Fonctionnalités complètes      │  • Complexité de config         │
│  • pgBackRest (best backup)       │  • Images plus lourdes          │
│  • Support commercial             │  • Courbe d'apprentissage       │
│  • Multi-repo backup              │  • Verbosité YAML               │
│  • Entreprise-ready               │                                 │
└─────────────────────────────────────────────────────────────────────┘

Arbre de Décision

                    QUEL OPERATOR CHOISIR ?
                    ───────────────────────

Avez-vous besoin d'un support commercial ?
│
├── OUI ─────────────────────────────────────────────┐
│                                                    │
│   Préférence pour l'écosystème ?                   │
│   │                                                │
│   ├── EDB / PostgreSQL officiel ──► CloudNativePG  │
│   │                                                │
│   └── Crunchy Data ──────────────► Crunchy PGO     │
│                                                    │
└── NON                                              │
    │                                                │
    Complexité de vos besoins ?                      │
    │                                                │
    ├── Simple (petit/moyen projet)                  │
    │   │                                            │
    │   └── Zalando Operator                         │
    │       (facile à démarrer)                      │
    │                                                │
    ├── Moyen (features avancées, K8s-native)        │
    │   │                                            │
    │   └── CloudNativePG                            │
    │       (pas de dépendances)                     │
    │                                                │
    └── Avancé (enterprise, DR, multi-région)        │
        │                                            │
        └── Crunchy PGO                              │
            (le plus complet)                        │

Exemple Pratique : Même Cluster, Trois Operators

Pour mieux comprendre les différences, voici comment créer un cluster PostgreSQL similaire avec chaque Operator.

Spécifications Communes

  • 3 instances (1 primary + 2 replicas)
  • 50 Gi de stockage
  • PostgreSQL 16
  • Backups vers S3

Avec Zalando

apiVersion: "acid.zalan.do/v1"  
kind: postgresql  
metadata:  
  name: my-cluster
spec:
  teamId: "myteam"
  numberOfInstances: 3
  postgresql:
    version: "16"
  volume:
    size: 50Gi
  enableConnectionPooler: true

Lignes de YAML : ~15

Avec CloudNativePG

apiVersion: postgresql.cnpg.io/v1  
kind: Cluster  
metadata:  
  name: my-cluster
spec:
  instances: 3
  imageName: ghcr.io/cloudnative-pg/postgresql:16.2
  storage:
    size: 50Gi
  backup:
    barmanObjectStore:
      destinationPath: s3://my-bucket/backups
      s3Credentials:
        accessKeyId:
          name: s3-creds
          key: ACCESS_KEY_ID
        secretAccessKey:
          name: s3-creds
          key: SECRET_ACCESS_KEY

Lignes de YAML : ~20

Avec Crunchy PGO

apiVersion: postgres-operator.crunchydata.com/v1beta1  
kind: PostgresCluster  
metadata:  
  name: my-cluster
spec:
  postgresVersion: 16
  instances:
    - name: instance1
      replicas: 3
      dataVolumeClaimSpec:
        accessModes: ["ReadWriteOnce"]
        resources:
          requests:
            storage: 50Gi
  backups:
    pgbackrest:
      repos:
        - name: repo1
          s3:
            bucket: "my-bucket"
            endpoint: "s3.amazonaws.com"
            region: "us-east-1"
  proxy:
    pgBouncer:
      replicas: 2

Lignes de YAML : ~30


Bonnes Pratiques Communes

1. Toujours Configurer les Backups

# Quel que soit l'Operator, configurez les backups DÈS LE DÉBUT
backup:
  retentionPolicy: "7d"    # Ou selon vos besoins
  schedule: "0 2 * * *"     # Quotidien à 2h

2. Utiliser des Resources Appropriées

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

3. Configurer la Haute Disponibilité

  • Minimum 3 instances pour la HA
  • Utiliser des anti-affinity rules pour distribuer sur plusieurs nodes/zones

4. Activer le Monitoring

# Exposer les métriques pour Prometheus
monitoring:
  enabled: true

5. Sécuriser les Accès

  • Utiliser TLS pour les connexions
  • Stocker les mots de passe dans des Secrets
  • Configurer les network policies

6. Tester les Restaurations

Testez régulièrement :

  • La restauration de backup
  • Le failover automatique
  • Le PITR

Migration Entre Operators

Si vous souhaitez changer d'Operator, voici la stratégie générale :

MIGRATION ENTRE OPERATORS
─────────────────────────

1. BACKUP
   Effectuer un backup complet avec pg_dump ou backup natif

2. DÉPLOYER
   Installer le nouvel Operator
   Créer un nouveau cluster vide

3. RESTAURER
   Restaurer les données dans le nouveau cluster
   (pg_restore ou restauration native)

4. TESTER
   Vérifier l'intégrité des données
   Tester les applications

5. BASCULER
   Mettre à jour les connexions applicatives

6. NETTOYER
   Supprimer l'ancien cluster
   Désinstaller l'ancien Operator

Conclusion

Les trois Operators présentés dans ce chapitre sont tous production-ready et largement utilisés. Le choix dépend de vos besoins spécifiques :

Choisissez Si vous...
Zalando Voulez démarrer rapidement avec une solution simple et éprouvée
CloudNativePG Préférez une architecture Kubernetes-native sans dépendances
Crunchy PGO Avez besoin de fonctionnalités enterprise avancées

Dans tous les cas, l'utilisation d'un Operator est fortement recommandée pour exécuter PostgreSQL en production sur Kubernetes. Les StatefulSets seuls ne suffisent pas pour gérer la complexité d'un SGBD en production.

Les Operators transforment des heures d'administration manuelle en quelques lignes de YAML déclaratif, tout en assurant une haute disponibilité et des backups automatisés.


Ressources Complémentaires

Documentation Officielle

Tutoriels et Guides

  • Zalando : Getting Started Guide
  • CloudNativePG : Quickstart
  • Crunchy : Tutorial avec exemples

Communautés

  • GitHub Issues de chaque projet
  • Slack Kubernetes (#postgresql)
  • Mailing lists PostgreSQL

Outils Complémentaires

  • kubectl plugins pour PostgreSQL
  • Lens (IDE Kubernetes)
  • k9s (terminal UI)

⏭️ Backup automation (Velero, native solutions)