Skip to content

Réplication PostgreSQL pour Odoo 18

Mettre en place une réplication PostgreSQL pour Odoo 18

Section titled “Mettre en place une réplication PostgreSQL pour Odoo 18”

La réplication de base de données est une technique essentielle pour garantir la haute disponibilité et la scalabilité de vos instances Odoo. Elle permet de :

  • Répartir la charge : les requêtes de lecture (rapports, recherches, API) peuvent être dirigées vers une réplique, libérant le serveur principal pour les écritures.
  • Assurer la continuité : en cas de panne du serveur principal, la réplique peut prendre le relais (basculement manuel ou automatique).
  • Sécuriser les données : la réplique peut servir de source pour des sauvegardes sans impacter la production.

Dans ce tutoriel, nous allons mettre en place une réplication physique (streaming replication) avec PostgreSQL, où une réplique en lecture seule maintient une copie synchronisée du serveur principal.


  • Docker et Docker Compose installés sur votre machine.
  • Odoo 18 installé (ou un conteneur Odoo que nous lancerons).
  • Connaissances de base en administration système et en SQL.

Nous allons déployer deux conteneurs PostgreSQL :

  1. pg_primary : le serveur principal qui accepte les écritures.
  2. pg_replica : la réplique en lecture seule qui se synchronise en continu.

Un troisième conteneur hébergera Odoo 18, configuré pour utiliser le serveur principal pour les écritures et la réplique pour les lectures.


Créez un répertoire pour le projet :

Terminal window
mkdir odoo-replication && cd odoo-replication

Créez les fichiers et dossiers suivants :

odoo-replication/
├── docker-compose.yml
├── odoo.conf
├── primary_init/
│ └── init.sql
└── replica_bootstrap/
└── replica-entrypoint.sh

Le fichier docker-compose.yml définit les trois services :

services:
pg_primary:
image: postgres:16
container_name: pg_primary
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
ports:
- "5433:5432"
command:
- -c
- listen_addresses=*
- -c
- wal_level=replica
- -c
- max_wal_senders=10
- -c
- max_replication_slots=10
- -c
- hot_standby_feedback=on
- -c
- log_statement=all
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres -h localhost -p 5432"]
interval: 2s
timeout: 2s
retries: 30
volumes:
- primary_data:/var/lib/postgresql/data
- ./primary_init:/docker-entrypoint-initdb.d
pg_replica:
image: postgres:16
container_name: pg_replica
depends_on:
pg_primary:
condition: service_healthy
environment:
REPL_USER: replicator
REPL_PASSWORD: replpass
ports:
- "5434:5432"
entrypoint: ["/bin/bash", "/usr/local/bin/replica-entrypoint.sh"]
command:
- -c
- listen_addresses=*
- -c
- log_statement=all
volumes:
- replica_data:/var/lib/postgresql/data
- ./replica_bootstrap/replica-entrypoint.sh:/usr/local/bin/replica-entrypoint.sh:ro
odoo:
image: odoo:18
container_name: odoo
depends_on:
pg_primary:
condition: service_healthy
pg_replica:
condition: service_started
ports:
- "8069:8069"
volumes:
- odoo_data:/var/lib/odoo
- ./odoo.conf:/etc/odoo/odoo.conf:ro
command: ["odoo", "-c", "/etc/odoo/odoo.conf"]
volumes:
primary_data:
replica_data:
odoo_data:

3. Script d’initialisation de la réplique

Section titled “3. Script d’initialisation de la réplique”

Créez replica_bootstrap/replica-entrypoint.sh :

#!/usr/bin/env bash
set -euo pipefail
PRIMARY_HOST="pg_primary"
PRIMARY_PORT="5432"
REPL_USER="${REPL_USER:-replicator}"
REPL_PASSWORD="${REPL_PASSWORD:-replpass}"
SLOT="replica1"
wait_for_primary() {
echo "[replica] Waiting for primary ${PRIMARY_HOST}:${PRIMARY_PORT}..."
until pg_isready -h "$PRIMARY_HOST" -p "$PRIMARY_PORT" -U postgres >/dev/null 2>&1; do
sleep 1
done
echo "[replica] Primary is ready."
}
if [ -z "$(ls -A "$PGDATA" 2>/dev/null)" ]; then
wait_for_primary
echo "[replica] Taking base backup from $PRIMARY_HOST..."
export PGPASSWORD="$REPL_PASSWORD"
pg_basebackup -h "$PRIMARY_HOST" -p "$PRIMARY_PORT" -U "$REPL_USER" \
-D "$PGDATA" -Fp -Xs -P -R -S "$SLOT"
{
echo "primary_conninfo = 'host=$PRIMARY_HOST port=$PRIMARY_PORT user=$REPL_USER password=$REPL_PASSWORD application_name=pg_replica1'"
echo "primary_slot_name = '$SLOT'"
} >> "$PGDATA/postgresql.auto.conf"
echo "hot_standby = on" >> "$PGDATA/postgresql.conf"
fi
exec docker-entrypoint.sh postgres "$@"

Rendez-le exécutable :

Terminal window
chmod +x replica_bootstrap/replica-entrypoint.sh

Créez primary_init/init.sql pour créer l’utilisateur de réplication et un utilisateur pour Odoo :

-- Créer l'utilisateur de réplication
CREATE ROLE replicator WITH LOGIN REPLICATION PASSWORD 'replpass';
-- Créer l'utilisateur pour Odoo
CREATE ROLE dd WITH LOGIN PASSWORD 'dd' CREATEDB CREATEROLE;

Créez odoo.conf :

[options]
addons_path = /mnt/extra-addons
admin_passwd = admin
db_host = pg_primary
db_port = 5432
db_user = dd
db_password = dd
db_name = v18_test_cluster
# Configuration de la réplique pour les lectures
db_replica_host = pg_replica
db_replica_port = 5432
# Autres options
workers = 2
proxy_mode = True

Note : Odoo 18 reconnaît les paramètres db_replica_host et db_replica_port pour rediriger automatiquement les requêtes de lecture vers la réplique. Assurez-vous que l’utilisateur dd existe sur la réplique (il sera créé automatiquement par la réplication).


Démarrez les conteneurs :

Terminal window
docker compose up -d

Surveillez les logs pour vérifier que tout se passe bien :

Terminal window
docker compose logs -f

Connectez-vous à la réplique et interrogez la table res_users :

Terminal window
PGPASSWORD=dd psql -h 127.0.0.1 -p 5434 -U dd -d v18_test_cluster -c "SELECT id, login FROM res_users;"

Vous devriez voir la liste des utilisateurs Odoo, ce qui prouve que la réplication fonctionne.


Pour simuler une panne du primaire, arrêtez le conteneur :

Terminal window
docker stop pg_primary

Odoo continuera de fonctionner, mais les écritures échoueront. Pour basculer vers la réplique, vous pouvez promouvoir celle-ci en primaire (opération manuelle avancée). Dans un environnement de production, on utilise un outil comme Patroni ou repmgr pour automatiser le basculement.


  • Monitoring : surveillez l’état de la réplication avec pg_stat_replication sur le primaire et pg_stat_wal_receiver sur la réplique.
  • Sécurité : isolez les réseaux des conteneurs et utilisez des mots de passe forts.
  • Performance : ajustez les paramètres max_wal_senders, wal_keep_size, etc., selon votre charge.
  • Haute disponibilité : combinez la réplication avec un outil de clustering (Patroni, repmgr) et un load balancer (HAProxy) pour un basculement automatique.

Vous avez maintenant une architecture Odoo 18 avec réplication PostgreSQL maître/esclave, prête à supporter des charges de lecture élevées et à améliorer la résilience de votre système. Cette configuration est un socle solide pour monter en charge et garantir la continuité de service.