Ripristino di emergenza (RE) avanzato con slot di failover logico

Questa pagina descrive come utilizzare lo slot di failover logico per configurare la replica logica di Cloud SQL per PostgreSQL in modo che funzioni perfettamente con le operazioni di disaster ripristino di emergenza (RE) avanzato, in particolare lo switchover e il failover della replica sulle istanze con Cloud SQL Enterprise Plus.

Le funzionalità di ripristino di emergenza (RE) avanzato di Cloud SQL consentono di disporre di solide funzionalità di disaster recovery. Se combinato con la replica logica di PostgreSQL, è fondamentale che il flusso di replica rimanga integro dopo un cambio di ruolo o un failover della replica.

Utilizzando il ripristino di emergenza (RE) avanzato con la replica logica di PostgreSQL, puoi assicurarti che i tuoi sottoscrittori logici non subiscano alcuna perdita di dati e che possano riconnettersi automaticamente alla nuova istanza principale dopo un evento di ripristino di emergenza, garantendo così la continuità aziendale.

Puoi utilizzare questa funzionalità sulle istanze Cloud SQL con la seguente configurazione:

  • PostgreSQL versione 17 o successive
  • Versione Cloud SQL Enterprise Plus
  • Accesso privato ai servizi

    Ti consigliamo di utilizzare l'endpoint di scrittura del servizio di nomi di dominio (DNS) di accesso privato ai servizi per abilitare le riconnessioni automatiche dei sottoscrittori logici.

Prima di iniziare

Configura il ripristino di emergenza (RE) avanzato con la replica logica

La procedura per configurare il ripristino di emergenza (RE) avanzato con la replica logica di PostgreSQL prevede i seguenti passaggi di alto livello:

  1. Configura le variabili di ambiente e la VM bastion.
  2. Crea e configura l'istanza principale.
  3. Crea e designa RE DR.
  4. Crea e configura un'istanza di sottoscrittore logico.
  5. Crea una sottoscrizione di replica logica.
  6. Eseguire un cambio o un failover della replica.
  7. Convalida la replica.
  8. Liberare spazio nello slot di replica orfano sulla nuova replica.
  9. (Facoltativo) Esegui il rollback.

Configura le variabili di ambiente e la VM bastion

  1. Imposta le seguenti variabili di ambiente.

    # Project
    export PROJECT="PROJECT_ID"
    
    # Instance names
    export PRIMARY_INSTANCE_NAME="PRIMARY_INSTANCE"
    export DR_REPLICA_NAME="DR_REPLICA"
    export SUBSCRIBER_INSTANCE_NAME="SUBSCRIBER_INSTANCE"
    export BASTION_VM_NAME="BASTION_VM"
    
    # Regions and zones
    export PRIMARY_REGION="PRIMARY_REGION"
    export REPLICA_REGION="REPLICA_REGION"
    export SUBSCRIBER_REGION="SUBSCRIBER_REGION"
    export VM_ZONE="VM_ZONE"
    
    # Network
    export NETWORK_NAME="NETWORK"
    
    # Credentials
    export POSTGRES_PASSWORD="PASSWORD"
    
    # Set gcloud project
    gcloud config set project PROJECT_ID
    

    Sostituisci quanto segue:

    • PROJECT_ID: l'ID progetto.
    • PRIMARY_INSTANCE: il nome dell'istanza Cloud SQL primaria.
    • DR_REPLICA: il nome della replica.
    • SUBSCRIBER_INSTANCE: il nome dell'istanza di sottoscrizione.
    • BASTION_VM: il nome della VM bastion.
    • PRIMARY_REGION: la regione in cui si trova l'istanza primaria.
    • REPLICA_REGION: la regione in cui si trova la replica. La replica deve trovarsi in una regione diversa da quella dell'istanza primaria.
    • SUBSCRIBER_REGION: la regione in cui si trova l'abbonato.
    • VM_ZONE: la zona in cui si trova la VM bastion.
    • NETWORK: il nome della tua rete VPC.
    • PASSWORD: la password per l'utente postgres.
  2. Crea una VM bastion di Compute Engine.

    Le istanze Cloud SQL utilizzano l'IP privato. Pertanto, crea una VM bastion host di Compute Engine nella tua rete VPC.

    gcloud compute instances create $BASTION_VM_NAME \
      --zone=$VM_ZONE \
      --machine-type=e2-small \
      --network=projects/$PROJECT_ID/global/networks/$NETWORK_NAME \
      --image-project=debian-cloud \
      --image-family=debian-11 \
      --project=$PROJECT
    
  3. Connettiti alla VM bastion.

    gcloud compute ssh $BASTION_VM_NAME \
      --zone=$VM_ZONE \
      --project=$PROJECT
    
  4. Sulla VM bastion, installa il client PostgreSQL.

    sudo apt-get update
    sudo apt-get install -y postgresql-client
    exit
    

I comandi PostgreSQL nei passaggi successivi devono essere eseguiti dalla VM bastion.

Crea e configura l'istanza principale

  1. Crea l'istanza Cloud SQL principale.

    gcloud sql instances create $PRIMARY_INSTANCE_NAME \
      --database-version=POSTGRES_17 \
      --edition=ENTERPRISE_PLUS \
      --region=$PRIMARY_REGION \
      --tier=db-perf-optimized-N-2 \
      --no-assign-ip \
      --network=projects/$PROJECT/global/networks/$NETWORK_NAME \
      --project=$PROJECT
    
  2. Abilita la decodifica logica.

    gcloud sql instances patch $PRIMARY_INSTANCE_NAME \
      --database-flags=cloudsql.logical_decoding=on \
      --project=$PROJECT
    
  3. Imposta la password per l'utente postgres sul server primario.

    gcloud sql users set-password postgres \
      --instance=$PRIMARY_INSTANCE_NAME \
      --password="$POSTGRES_PASSWORD" \
      --project=$PROJECT
    
  4. Connettiti all'istanza principale dalla VM bastion.

    1. Recupera l'indirizzo IP privato dell'istanza principale.

      gcloud sql instances describe $PRIMARY_INSTANCE_NAME \
        --format="value(ipAddresses[0].ipAddress)" \
        --project=$PROJECT
      

      Copia e conserva l'indirizzo IP privato dell'istanza principale.

    2. Accedi tramite SSH alla VM bastion.

      gcloud compute ssh $BASTION_VM_NAME --zone=$VM_ZONE --project=$PROJECT
      
    3. Dalla VM bastion, connettiti all'istanza principale.

      psql -h PRIMARY_PRIVATE_IP -U postgres
      

      Sostituisci PRIMARY_PRIVATE_IP con l'IP privato dell'istanza primaria che hai recuperato nel passaggio 4.a di questa procedura.

    4. Quando viene richiesta la password, inserisci la variabile $POSTGRES_PASSWORD.

      La VM bastion è ora connessa all'istanza primaria tramite PostgreSQL.

  5. Concedi le autorizzazioni e crea la pubblicazione.

    1. Concedi il privilegio REPLICATION all'utente postgres.

      ALTER USER postgres WITH REPLICATION;
      
    2. Concedi i privilegi necessari sullo schema e sulle tabelle pubblici.

      GRANT SELECT ON ALL TABLES IN SCHEMA public TO postgres;
      
    3. Crea la pubblicazione per tutte le tabelle.

      CREATE PUBLICATION my_publication FOR ALL TABLES;
      
    4. Digita exit per uscire da PostgreSQL, quindi exit di nuovo per chiudere la sessione SSH della VM bastion.

Crea e designa la replica di ripristino di emergenza (replica RE)

  1. Crea una replica di RE.

    gcloud sql instances create $DR_REPLICA_NAME \
      --master-instance-name=$PRIMARY_INSTANCE_NAME \
      --edition=ENTERPRISE_PLUS \
      --tier=db-perf-optimized-N-2 \
      --region=$REPLICA_REGION \
      --no-assign-ip \
      --network=projects/$PROJECT/global/networks/$NETWORK_NAME \
      --project=$PROJECT
    
  2. Designa questa replica come replica RE.

    gcloud sql instances patch $PRIMARY_INSTANCE_NAME \
      --failover-dr-replica-name=$DR_REPLICA_NAME \
      --project=$PROJECT
    
  3. Configura la replica RE per la sincronizzazione degli slot logici.

    gcloud sql instances patch $DR_REPLICA_NAME \
      --database-flags="^:^cloudsql.logical_decoding=on:hot_standby_feedback=on:sync_replication_slots=on:cloudsql.logical_slot_sync_dbname=postgres" \
      --project=$PROJECT
    
  4. Configura la replica sincrona tra l'istanza principale e la replica di RE.

    Per evitare la potenziale perdita di dati sul sottoscrittore logico in caso di interruzione improvvisa dell'istanza principale e successivo failover della replica di ripristino di emergenza, ti consigliamo di configurare la replica sincrona tra l'istanza principale e la replica di ripristino di emergenza.

    L'impostazione di cloudsql.synchronized_standby_replicas sull'istanza principale impone al mittente del log Write-Ahead (WAL) di replica logica dell'istanza principale di attendere che la replica di RE abbia ricevuto e scaricato il WAL per una determinata transazione prima di inviarla al subscriber logico. In questo modo, lo stato della replica diRER è sempre uguale o successivo allo stato del sottoscrittore logico.

    gcloud sql instances patch $PRIMARY_INSTANCE_NAME \
      --database-flags="^:^cloudsql.logical_decoding=on:cloudsql.synchronized_standby_replicas=$DR_REPLICA_NAME" \
      --project=$PROJECT
    

Crea e configura un'istanza di sottoscrittore logico

  1. Crea un'istanza di sottoscrittore.

    gcloud sql instances create $SUBSCRIBER_INSTANCE_NAME \
      --database-version=POSTGRES_17 \
      --tier=db-perf-optimized-N-2 \
      --region=$SUBSCRIBER_REGION \
      --no-assign-ip \
      --network=projects/$PROJECT/global/networks/$NETWORK_NAME \
      --project=$PROJECT
    
  2. Abilita la decodifica logica sul sottoscrittore.

    gcloud sql instances patch $SUBSCRIBER_INSTANCE_NAME \
      --database-flags=cloudsql.logical_decoding=on \
      --project=$PROJECT
    

Crea una sottoscrizione di replica logica

  1. Recupera l'endpoint di scrittura dell'accesso privato ai servizi dell'istanza principale.

    gcloud sql instances describe $PRIMARY_INSTANCE_NAME \
      --format="value(replicationCluster.psaWriteEndpoint)" \
      --project=$PROJECT
    

    Copia e conserva l'endpoint di scrittura.

  2. Connettiti all'istanza di sottoscrizione.

    1. Aggiorna la password per l'utente postgres dell'istanza abbonato.

      gcloud sql users set-password postgres \
        --instance=$SUBSCRIBER_INSTANCE_NAME \
        --password="$POSTGRES_PASSWORD" \
        --project=$PROJECT
      
    2. Recupera l'indirizzo IP privato dell'istanza di sottoscrizione.

      gcloud sql instances describe $SUBSCRIBER_INSTANCE_NAME \
        --format="value(ipAddresses[0].ipAddress)" \
        --project=$PROJECT
      

      Copia e conserva l'indirizzo IP privato.

    3. Accedi tramite SSH alla VM bastion.

      gcloud compute ssh $BASTION_VM_NAME \
        --zone=$VM_ZONE \
        --project=$PROJECT
      
    4. Dalla VM bastion, connettiti all'istanza abbonata tramite PostgreSQL.

      psql -h SUBSCRIBER_PRIVATE_IP -U postgres
      

      Sostituisci SUBSCRIBER_PRIVATE_IP con l'IP privato dell'istanza abbonata che hai copiato nel passaggio 2.b di questa procedura.

    5. Quando viene richiesta la password, inserisci la variabile $POSTGRES_PASSWORD.

  3. Crea un abbonamento.

    CREATE SUBSCRIPTION my_subscription
    CONNECTION 'host=DR_CLUSTER_PSA_DNS_WRITE_ENDPOINT port=5432 dbname=postgres user=postgres password=PASSWORD'
    PUBLICATION my_publication
    WITH (failover = true);
    

    Sostituisci quanto segue:

    • DR_CLUSTER_PSA_DNS_WRITE_ENDPOINT: l'endpoint di scrittura dell'accesso ai servizi privati che hai copiato nel passaggio 1 di questa procedura.
    • PASSWORD: il valore della variabile ${POSTGRES_PASSWORD}.
  4. Esci da PostgreSQL e dalla sessione SSH della VM bastion.

  5. Facoltativo. Verifica la persistenza dello slot nella replica RE.

    Questa transizione alla modalità persistente (temporary = false) in genere avviene rapidamente, spesso in pochi secondi se l'attività del dispositivo principale è bassa. In caso di carico di scrittura elevato sul database primario, questo processo potrebbe richiedere più tempo, in genere circa un minuto. Lo slot deve essere persistente dopo aver completato questi comandi manuali.

    1. Ottieni l'indirizzo IP privato della replica di RE.

      gcloud sql instances describe $DR_REPLICA_NAME \
        --format="value(ipAddresses[0].ipAddress)" \
        --project=$PROJECT
      

      Copia e conserva l'indirizzo IP privato della replica di RE.

    2. Accedi tramite SSH alla VM bastion.

      gcloud compute ssh $BASTION_VM_NAME \
        --zone=$VM_ZONE \
        --project=$PROJECT
      
    3. Dalla VM bastion, connettiti alla replica di RE.

      psql -h DR_REPLICA_PRIVATE_IP -U postgres
      

      Sostituisci DR_REPLICA_PRIVATE_IP con l'indirizzo IP privato della replica di RE che hai recuperato nel passaggio 5.a di questa procedura.

    4. Quando viene richiesta la password, inserisci la variabile $POSTGRES_PASSWORD.

    5. Controlla lo stato dello slot.

      SELECT slot_name, slot_type, temporary, failover, synced
      FROM pg_replication_slots
      WHERE slot_type = 'logical' AND failover = true;
      

      Attendi che la colonna temporary diventi f. In genere, questa operazione richiede meno di un minuto.

    6. Esci da PostgreSQL e dalla sessione SSH della VM bastion.

Esegui uno switchover o un failover della replica

Scegli l'operazione che vuoi eseguire in base al tuo scenario:

  • Switchover (inversione pianificata dei ruoli): scegli questa opzione per la manutenzione pianificata, i test di ripristino di emergenza o per invertire i ruoli quando l'istanza principale è online e integra. Questa operazione garantisce la perdita zero di dati per la replica fisica.

    gcloud sql instances switchover $DR_REPLICA_NAME \
      --project=$PROJECT
    
  • Failover della replica (ripristino di emergenza): scegli questa opzione quando l'istanza primaria non è disponibile o non risponde. Questa operazione promuove la replica di RE a primaria. Per ridurre al minimo il rischio di perdita di dati per il sottoscrittore logico, assicurati che cloudsql.synchronized_standby_replicas sia stato impostato nell'istanza principale come consigliato in Crea e designa la replica di ripristino di emergenza (replica RE).

    gcloud sql instances promote-replica $DR_REPLICA_NAME \
      --failover \
      --project=$PROJECT
    

    La promozione di $DR_REPLICA_NAME avviene rapidamente. Tuttavia, l'istanza principale originale ($PRIMARY_INSTANCE_NAME) viene riconfigurata come replica della nuova istanza principale solo quando torna online. Puoi monitorare questa operazione cercando il completamento dell'operazione RECONFIGURE_OLD_PRIMARY su $PRIMARY_INSTANCE_NAME nel log delle operazioni. Esegui questo comando:

    gcloud sql operations list --instance=$PRIMARY_INSTANCE_NAME --project=$PROJECT --limit=10`
    

    La configurazione del ripristino di emergenza viene ripristinata completamente solo al termine di questa fase.

Dopo una delle due operazioni, il sottoscrittore si riconnette automaticamente al nuovo $DR_REPLICA_NAME principale tramite l'endpoint di scrittura dell'accesso privato ai servizi.

Gestione dei flag

I workflow di Cloud SQL gestiscono automaticamente i flag di database necessari su entrambe le istanze all'interno del cluster di ripristino di emergenza durante e dopo le operazioni di switchover e failover della replica, tra cui:

  • I flag di sincronizzazione degli slot logici (cloudsql.logical_decoding, hot_standby_feedback, sync_replication_slots, cloudsql.logical_slot_sync_dbname) sono corretti nell'istanza che diventa la nuova replica.
  • Il flag cloudsql.synchronized_standby_replicas sull'istanza che diventa la nuova istanza principale viene aggiornato automaticamente in modo che punti al nome della nuova replica di RE.

Non è necessario riapplicare o modificare manualmente questi flag dopo un'operazione di switchover o di failover della replica. Cloud SQL gestisce la configurazione corretta per i ruoli primario e di replica.

Convalida la replica

  1. Controlla lo stato dell'iscritto.

    1. Dalla VM bastion, esegui il seguente comando.

      psql -h SUBSCRIBER_PRIVATE_IP -U postgres
      

      Sostituisci SUBSCRIBER_PRIVATE_IP con l'indirizzo IP privato dell'istanza abbonata.

    2. Sull'istanza di sottoscrizione, esegui il comando seguente.

      SELECT subname, pid IS NOT NULL AS is_active
      FROM pg_stat_subscription;
      

      Lo stato deve essere streaming.

  2. Controlla lo stato dello slot di replica del nuovo primario. Il nuovo primario è la precedente replica RE ($DR_REPLICA_NAME).

    1. Ottieni l'indirizzo IP privato del nuovo primario.

      gcloud sql instances describe $DR_REPLICA_NAME \
        --project=$PROJECT --format="value(ipAddresses[0].ipAddress)"
      

      Copia e conserva l'indirizzo IP privato del nuovo primario.

    2. Accedi tramite SSH alla VM bastion.

      psql -h NEW_PRIMARY_PRIVATE_IP -U postgres
      

      Sostituisci NEW_PRIMARY_PRIVATE_IP con l'indirizzo IP privato del nuovo primario che hai copiato nel passaggio precedente.

    3. Sulla nuova istanza primaria, esegui questi comandi.

      SELECT
          slot_name,
          slot_type,
          active,
          synced,
          active_pid,
          pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), confirmed_flush_lsn)) AS replication_lag
      FROM pg_replication_slots
      WHERE slot_type = 'logical';
      

      Lo slot (ad esempio, my_subscription) deve essere active = t.

      SELECT
          application_name,
          state
      FROM pg_stat_replication;
      

      pg_stat_replication dovrebbe mostrare l'abbonato connesso.

Pulisci lo slot di replica orfano nella nuova replica

Al termine dell'operazione di cambio e failover, l'istanza principale originale ($PRIMARY_INSTANCE_NAME) è ora una replica. Questa nuova istanza di replica conserva ancora lo slot di replica logica originale denominato my_subscription sul disco. Questo slot my_subscription è ora orfano perché il sottoscrittore deve connettersi al nuovo primario ($DR_REPLICA_NAME) tramite l'endpoint di scrittura dell'accesso privato ai servizi.

Cloud SQL non rimuove automaticamente questo slot orfano dalla nuova replica. Questo perché Cloud SQL non può determinare se il sottoscrittore è stato configurato per utilizzare l'indirizzo IP dell'istanza anziché l'endpoint di scrittura di accesso ai servizi privati. L'abbonato potrebbe ancora tentare di connettersi a questo vecchio slot sulla nuova replica finché l'abbonamento non viene modificato manualmente. L'eliminazione automatica dello slot potrebbe interrompere queste configurazioni.

La presenza di questo slot orfano nella nuova replica ($PRIMARY_INSTANCE_NAME) fa sì che il processo di worker slotsync su questa istanza generi errori nei log. Potresti visualizzare un messaggio di errore simile al seguente in postgres.log della nuova replica. Questo errore si ripete continuamente mentre il worker slotsync continua a riprovare.

ERROR: exiting from slot synchronization because same name slot "my_subscription" already exists on the standby

Per evitare questi errori e consentire al worker slotsync di stabilire correttamente una nuova versione sincronizzata dello slot my_subscription su questa replica, devi eliminare manualmente lo slot orfano. In questo modo, l'istanza viene preparata correttamente se intendi eseguire il rollback in futuro.

  1. Recupera l'indirizzo IP privato della nuova replica ($PRIMARY_INSTANCE_NAME).

    gcloud sql instances describe $PRIMARY_INSTANCE_NAME \
      --project=$PROJECT --format="value(ipAddresses[0].ipAddress)"
    

    Copia e conserva l'indirizzo IP privato della nuova replica.

  2. Accedi tramite SSH alla VM bastion.

    gcloud compute ssh $BASTION_VM_NAME \
      --zone=$VM_ZONE \
      --project=$PROJECT
    
  3. Dalla VM bastion, connettiti alla nuova replica.

    psql -h NEW_REPLICA_IP -U postgres
    

    Sostituisci NEW_REPLICA_IP con l'indirizzo IP della nuova replica che hai copiato nel passaggio 1 di questa procedura.

  4. Quando viene richiesta la password, inserisci la variabile $POSTGRES_PASSWORD.

  5. Nella nuova replica ($PRIMARY_INSTANCE_NAME), elimina lo slot orfano.

    SELECT slot_name, slot_type, temporary, failover, synced, active
    FROM pg_replication_slots
    WHERE slot_name = 'my_subscription';
    

    Verifica che lo slot esista con synced = false e active = false, quindi eliminalo.

    SELECT pg_drop_replication_slot('my_subscription');
    

    Lo slot orfano viene rimosso.

Risincronizzazione automatica degli slot

Una volta eliminato lo slot orfano, il worker slotsync sulla nuova replica ($PRIMARY_INSTANCE_NAME) si connette automaticamente al nuovo nodo primario ($DR_REPLICA_NAME) nel ciclo successivo. Crea un nuovo slot my_subscription locale sincronizzato con lo slot attivo della nuova emittente principale.

Puoi visualizzare i messaggi in postgres.log della nuova replica che indicano l'esito positivo, simili ai seguenti:

LOG: newly created slot "my_subscription" is sync-ready now

Il nuovo slot sincronizzato ha failover=true e alla fine diventa persistente (temporary=false), garantendo che se torni indietro in un secondo momento, questa istanza sia pronta.

(Facoltativo) Esegui il rollback

  1. Ora torna indietro, impostando di nuovo $PRIMARY_INSTANCE_NAME come istanza primaria.

    gcloud sql instances switchover $PRIMARY_INSTANCE_NAME \
      --project=$PROJECT
    
  2. Esegui la verifica dopo il rollback.

    1. Controlla lo stato dell'istanza di abbonato.

      SELECT subname, pid IS NOT NULL AS is_active
      FROM pg_stat_subscription;
      

      L'abbonamento dovrebbe essere ancora attivo, ovvero is_active = t.

    2. Controlla lo stato dello slot della nuova risorsa principale ($PRIMARY_INSTANCE_NAME).

      SELECT slot_name, active FROM pg_replication_slots WHERE slot_type = 'logical';
      SELECT * FROM pg_stat_replication;
      

      Lo slot deve essere attivo e l'abbonato deve essere connesso.

Risoluzione dei problemi

Problema Risoluzione dei problemi

Errore nella nuova replica (ovvero la vecchia istanza principale) dopo il cambio:

"exiting from slot synchronization because same name slot already exists on the standby"

Segui i passaggi descritti in Pulire lo slot di replica orfano nella nuova replica.