# Vérifier que le slave n'est plus en recovery
oc exec$SLAVE_POD -- psql -U postgres -c "SELECT pg_is_in_recovery();"# Doit retourner "f"# Tester une écriture
oc exec$SLAVE_POD -- psql -U postgres -c "CREATE TABLE test_failover (id INT);"
oc exec$SLAVE_POD -- psql -U postgres -c "INSERT INTO test_failover VALUES (1);"
oc exec$SLAVE_POD -- psql -U postgres -c "SELECT * FROM test_failover;"
Étape 5 : Redirection du service master
Modifier le service pour pointer vers l'ex-slave (nouveau master) :
Resource : Modification du service postgresql
apiVersion:v1kind:Servicemetadata:name:postgresqllabels:app:postgresqlspec:ports:-name:postgresqlport:5432targetPort:5432selector:app:postgresqlrole:slave# ← Pointer vers l'ex-slavetype:ClusterIP
Appliquer :
oc apply -f postgresql-service-updated.yaml
# Ou directement avec oc patch
oc patch service postgresql -p '{"spec":{"selector":{"role":"slave"}}}'
Étape 6 : Mise à jour des labels du nouveau master
Mettre à jour les labels du pod promu :
# Modifier le deployment slave
oc edit deployment postgresql-slave
# Changer les labels# labels:# app: postgresql# role: master # ← Changer de "slave" à "master"
Ou créer un nouveau service temporaire :
# Créer un service pointant vers l'ex-slave
oc expose deployment postgresql-slave --name=postgresql-temp --port=5432
# Supprimer l'ancien service master
oc delete service postgresql
# Renommer le service temporaire
oc patch service postgresql-temp -p '{"metadata":{"name":"postgresql"}}'
Étape 7 : Configuration du nouveau master pour la réplication
Configurer le nouveau master pour accepter de futurs slaves :
# Créer l'utilisateur de réplication si nécessaire
oc exec$SLAVE_POD -- psql -U postgres <<EOF
DO \$\$
BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname='replicator') THEN
CREATE USER replicator WITH REPLICATION ENCRYPTED PASSWORD 'replicator_password';
END IF;
END
\$\$;
EOF# Créer un nouveau slot de réplication
oc exec$SLAVE_POD -- psql -U postgres -c "SELECT pg_create_physical_replication_slot('replication_slot_new_slave');"
Appliquer la configuration master (réutiliser les ConfigMaps existantes) :
# Le pod utilise déjà slave.conf, il faut le passer en master.conf
oc exec$SLAVE_POD -- bash -c "cp /etc/postgresql/slave.conf /var/lib/postgresql/data/postgresql.auto.conf"# Ou recréer le pod avec la configuration master
oc set volumes deployment/postgresql-slave \
--add --name=master-config \
--type=configmap \
--configmap-name=postgresql-master-config \
--mount-path=/etc/postgresql/master.conf \
--sub-path=master.conf \
--overwrite
# Redémarrer le pod
oc rollout restart deployment/postgresql-slave
Étape 8 : Validation finale
# Applications peuvent écrire
oc exec$SLAVE_POD -- psql -U postgres -c "INSERT INTO test_failover VALUES (2);"# Vérifier les connexions
oc exec$SLAVE_POD -- psql -U postgres -c "SELECT count(*) FROM pg_stat_activity;"# Tester depuis une application
oc run test-pg --image=postgres:15 --rm -it --restart=Never -- \
psql -h postgresql -U postgres -d postgres -c "SELECT now();"
Failover automatique avec Patroni
Patroni est la solution recommandée pour le failover automatique PostgreSQL sur Kubernetes/OpenShift.
oc apply -f etcd-statefulset.yaml
# Attendre que etcd soit prêt
oc wait --for=condition=ready pod -l app=etcd --timeout=300s
# Vérifier l'état du cluster
oc exec etcd-0 -- etcdctl member list
Sans Patroni (manuel) :
Suivre la procédure de failover manuel (section précédente)
Test 2 : Failover automatique sur panne
# Simuler un crash du pod master
MASTER_POD=$(oc get pods -l app=postgresql-patroni,role=master -o jsonpath='{.items[0].metadata.name}')
oc delete pod $MASTER_POD --grace-period=0 --force
# Surveiller
watch -n 1 "oc get pods -l app=postgresql-patroni"
watch -n 1 "oc exec postgresql-patroni-0 -- patronictl -c /etc/patroni/patroni.yml list"
Test 3 : Split-brain prevention
# Isoler un pod du réseau (nécessite Network Policies)# Créer une NetworkPolicy qui bloque le master actuel# Patroni devrait :# 1. Détecter la perte de quorum# 2. Promouvoir un nouveau master parmi les nœuds connectés# 3. Empêcher l'ancien master d'accepter des écritures
Test 4 : Performance pendant failover
# Script de test de chargecat > test-failover-performance.sh <<'EOF'#!/bin/bash# Connexion à la base
CONNECTION="postgresql://postgres:password@postgresql-master:5432/postgres"# Boucle d'écriturewhiletrue; do
result=$(psql "$CONNECTION" -c "INSERT INTO test_failover VALUES (NOW()) RETURNING *;" 2>&1)
if [[ $? -eq 0 ]]; thenecho"[$(date)] SUCCESS: $result"elseecho"[$(date)] FAILED: $result"fisleep 1
done
EOF
# Lancer le test en arrière-plan
oc run test-failover --image=postgres:15 --rm -it --restart=Never -- bash -c "$(cat test-failover-performance.sh)"# Dans un autre terminal, déclencher le failover
oc delete pod $MASTER_POD
Retour à la normale
Après failover manuel : Ajouter un nouveau slave
Une fois le failover effectué, l'ancien master peut être reconfiguré comme slave.
Étape 1 : Nettoyer l'ancien master
# Si l'ancien master est récupérable
OLD_MASTER_POD=$(oc get pods -l name=postgresql -o jsonpath='{.items[0].metadata.name}')
# Supprimer le pod et le PVC
oc delete pod $OLD_MASTER_POD
oc delete pvc postgresql # PVC de l'ancien master
Étape 2 : Créer un nouveau PVC pour le nouveau slave