Implementazione di riferimento del database MySQL su GDC con air gap

Questa guida fornisce un tutorial completo passo passo per il deployment di un cluster InnoDB MySQL 8.4 a elevata disponibilità in tre zone di disponibilità in un ambiente con air gap di Google Distributed Cloud (GDC). Questa architettura utilizza la replica dei gruppi per il consenso basato su Paxos, MySQL Router per il routing intelligente delle connessioni e MySQL Shell per l'orchestrazione dei cluster.

Utilizzando rigorosamente le macchine virtuali (VM), questa implementazione aggira le limitazioni di GDC con air gap relative ai cluster stretch Kubernetes tra zone, garantendo una resilienza multizona completa senza rischiare la perdita di dati.

Questo è il diagramma dell'architettura:

Architettura a tre VM che esegue uno stack di servizi colocalizzati.

Prima di iniziare

Esegui il deployment delle VM

Segui la procedura descritta in Creare e avviare un'istanza VM per creare tre VM nelle tre zone disponibili.

Configura l'ambiente locale per stabilire una connessione SSH alle VM con una coppia di chiavi: Connettersi a una VM

Questa operazione è necessaria per utilizzare la copia sicura (SCP) per trasferire i pacchetti: Trasferire file

Per la verifica, abbiamo utilizzato il sistema operativo Ubuntu 22.04 e il tipo di macchina n3-standard-2-gdc. Per un ambiente di produzione, utilizza un tipo di macchina con più risorse.

Ottieni gli indirizzi IP delle VM utilizzando:

VM_NAME=$1

if [[ -z "$VM_NAME" ]]; then
  echo "Error: VM_NAME must be provided."
  echo "Usage: $0 <VM_NAME>"
  exit 1
fi

# 1. Get External IP from 'instances list'
EXT_IP=$(gdcloud compute instances list | awk -v vm="${VM_NAME}" '$1 == vm {print $5}')

if [[ -z "$EXT_IP" ]]; then
  echo "Error: Could not find VM '${VM_NAME}' in the instance list."
  exit 1
fi

INTERNAL_IP=$(gdcloud compute instances describe "${VM_NAME}" | awk '/^status:/ {in_status=1} in_status && /- [0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/ {print $2; exit}' | cut -d'/' -f1)

if [[ -z "$INTERNAL_IP" ]]; then
  INTERNAL_IP="<Not assigned or not found>"
fi

echo "${VM_NAME}"
echo "External IP: ${EXT_IP}"
echo "Internal IP: ${INTERNAL_IP}"

Configura le variabili di ambiente

Imposta queste variabili nella sessione della shell della workstation locale:

export PROJECT_ID="your-project-id"
export VM1_NAME="mysql-node-1"
export VM2_NAME="mysql-node-2"
export VM3_NAME="mysql-node-3"
export VM1_IP="10.0.1.245" # Zone 1
export VM2_IP="10.0.1.241" # Zone 2
export VM3_IP="10.0.1.242" # Zone 3
export CLUSTER_NAME="mysql-ha-cluster"

Configurazione di rete

Se devi raggiungere il database al di fuori del progetto o dell'organizzazione, ricordati di configurare di conseguenza il PNP (Project Network Policy).

Segui le sezioni di Panoramica di PNP a seconda del caso d'uso.

Preparazione del software con air gap

Scarica i pacchetti utilizzando Docker

Esegui il comando seguente da una workstation connessa per recuperare i componenti di MySQL 8.4 e Shell:

mkdir -p ./mysql-packages
docker run --rm -v "$(pwd)/mysql-packages:/packages" ubuntu:22.04 bash -c "
  apt-get update && apt-get install -y curl gnupg apt-rdepends wget lsb-release
  curl -LsS https://dev.mysql.com/get/mysql-apt-config_0.8.39-1_all.deb -o config.deb
  # Configure for MySQL 8.4 LTS
  DEBIAN_FRONTEND=noninteractive dpkg -i config.deb 
  apt-get update
  cd /packages
  PACKAGES='mysql-server mysql-shell mysql-router'
  apt-get download \$(apt-cache depends --recurse --no-recommends --no-suggests --no-conflicts --no-breaks --no-replaces --no-enhances --no-pre-depends \${PACKAGES} | grep '^\w')
"

Trasferisci e installa

Carica i file .deb in /tmp/packages/ su tutte e tre le VM e installali:

# From workstation: scp ./mysql-packages/*.deb ${VM_IP}:/tmp/packages/
# On each VM:
sudo dpkg -i /tmp/packages/*.deb

Assicurati che dpkg non restituisca errori. In caso contrario, controlla i log per vedere quali pacchetti deb potrebbero mancare e includili nel download.

Quando ti viene chiesto di impostare la password root, lasciala vuota. Imposteremo la password in un secondo momento.

Configurazione del nodo MySQL

Configura MySQL per l'utilizzo del cluster

Modifica /etc/mysql/mysql.conf.d/mysqld.cnf su tutti i nodi per abilitare GTID e la registrazione binaria:

[mysqld]
bind-address = 0.0.0.0
server-id = 1 # Use 2 and 3 for other VMs
gtid-mode = ON
enforce-gtid-consistency = ON
binlog-format = ROW
log-bin = mysql-bin
report_host = 10.0.1.245 # Use the VM's specific IP

Riavvia il servizio:

sudo systemctl restart mysql

Quindi, connettiti al database:

sudo mysql

e imposta la password root:

CREATE USER 'root'@'%' IDENTIFIED WITH 'caching_sha2_password' BY 'your_new_secure_password';
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' WITH GRANT OPTION;
FLUSH PRIVILEGES;

Inizializzazione e verifica del cluster InnoDB

Crea il cluster utilizzando MySQL Shell

SOLO SULLA VM 1, utilizza MySQL Shell per inizializzare il cluster:

mysqlsh --uri root@localhost
# Inside MySQL Shell:
\js
dba.configureInstance('root@VM1_IP')
var cluster = dba.createCluster('mysql-ha-cluster')
cluster.addInstance('root@VM2_IP')
cluster.addInstance('root@VM3_IP')
cluster.status()

Esegui il bootstrap di MySQL Router

Su tutte e tre le VM, esegui il bootstrap del router per rilevare il nuovo cluster:

sudo mysqlrouter --bootstrap root@VM1_IP --user=mysqlrouter
sudo systemctl restart mysqlrouter
sudo systemctl enable mysqlrouter

Verifica il bilanciamento e le connessioni

Esegui questi comandi da qualsiasi nodo per assicurarti che il router distribuisca correttamente il traffico.

  1. Verifica il routing di scrittura (primario attivo): esegui una query sulla porta 6446 (RW classica). Dovrebbe restituire rigorosamente il nome host del primario corrente.

    mysql -u root -pyour_new_secure_password -h 127.0.0.1 -P 6446 -e "SELECT @@hostname;"
    
  2. Verifica il bilanciamento di lettura (round robin): esegui più volte una query sulla porta 6447 (RO classica) . Dovrebbe scorrere i nomi host di tutti i nodi disponibili nel cluster.

    for i in {1..4}; do mysql -u root -pyour_new_secure_password -h 127.0.0.1 -P 6447 -e "SELECT @@hostname;"; done
    
  3. Controlla la topologia di connessione: utilizza MySQL Shell per verificare che tutti i membri siano ONLINE e correttamente bilanciati.

    mysqlsh --uri root@localhost --cluster
    
    # inside the shell
    > cluster.status()
    

Configurazione del bilanciatore del carico globale

Fornisci un singolo indirizzo IP virtuale (VIP) stabile per le tue applicazioni utilizzando il bilanciatore del carico L4 globale di GDC. Segui Configurare i bilanciatori del carico globali interni per configurare il bilanciatore del carico L4 globale interno e configurare le VM come target: Configurare le VM come target del bilanciatore del carico.

Verifica del failover automatico

Questo test conferma che il cluster elegge un nuovo leader e che il router reindirizza il traffico senza intervento manuale.

Simula un errore primario

Identifica il primario corrente (ad es. Nodo 1) e arresta il servizio MySQL:

sudo systemctl stop mysql

Verifica l'elezione e lo spostamento del routing

Attendi 10-20 secondi affinché il protocollo di consenso elegga un nuovo leader.

  1. Controlla lo stato del cluster: dalla VM 2 o 3, verifica che sia stato eletto un nuovo primario.

    mysqlsh --uri root@localhost --cluster
    
    # inside the shell
    > cluster.status()
    

    Verifica che uno dei nodi rimanenti sia contrassegnato come PRIMARY e che il nodo non riuscito sia contrassegnato come UNREACHABLE o MISSING.

  2. Verifica il routing di scrittura: esegui di nuovo il test della porta RW (6446). Ora dovrebbe restituire il nome host del nuovo primario.

    mysql -u root -p -h 127.0.0.1 -P 6446 -e "SELECT @@hostname;"
    
  3. Testa la connettività VIP globale: da un server applicazioni, esegui una query sul VIP globale.

    mysql -u root -p -h ${LB_IP} -P 3306 -e "SELECT @@hostname;"
    

Recupera e verifica il rientro

Avvia il servizio MySQL sul nodo non riuscito e verifica che si unisca come replica secondaria.

sudo systemctl start mysql
mysqlsh --uri root@localhost --cluster -e "cluster.status()"

Verifica che tutti e tre i nodi restituiscano lo stato ONLINE.