Questo documento è destinato ad amministratori di database, architetti cloud e professionisti delle operazioni interessati al deployment di una topologia MySQL a disponibilità elevata su Google Kubernetes Engine.
Segui questo tutorial per scoprire come eseguire il deployment di un cluster MySQL InnoDB e di un clusterSet MySQL InnoDB, oltre al middleware MySQL Router sul tuo cluster GKE e come eseguire gli upgrade.
Obiettivi
In questo tutorial imparerai a:- Crea ed esegui il deployment di un servizio Kubernetes stateful.
- Esegui il deployment di un cluster MySQL InnoDB per l'alta disponibilità.
- Esegui il deployment del middleware Router per il routing delle operazioni di database.
- Esegui il deployment di un cluster InnoDB MySQL per la tolleranza agli errori.
- Simula un failover del cluster MySQL.
- Esegui un upgrade della versione di MySQL.
Le sezioni seguenti descrivono l'architettura della soluzione che creerai in questo tutorial.
Cluster InnoDB di MySQL
Nel cluster GKE regionale, utilizzando un StatefulSet, esegui il deployment di un'istanza del database MySQL con la denominazione e la configurazione necessarie per creare un cluster MySQL InnoDB. Per fornire tolleranza agli errori e alta disponibilità, esegui il deployment di tre pod dell'istanza del database. In questo modo, la maggior parte dei pod in zone diverse è disponibile in qualsiasi momento per un'elezione primaria riuscita utilizzando un protocollo di consenso e il cluster MySQL InnoDB è tollerante ai singoli errori di zona.
Una volta eseguito il deployment, devi designare un pod come istanza principale per gestire le operazioni di lettura e scrittura. Gli altri due pod sono repliche secondarie di sola lettura. Se l'istanza primaria riscontra un errore dell'infrastruttura, puoi promuovere uno di questi due pod di replica in modo che diventi quello primario.
In uno spazio dei nomi separato, esegui il deployment di tre pod MySQL Router per fornire il routing delle connessioni per una maggiore resilienza. Invece di connettersi direttamente al servizio di database, le tue applicazioni si connettono ai pod MySQL Router. Ogni pod router è a conoscenza dello stato e dello scopo di ogni pod cluster MySQL InnoDB e indirizza le operazioni dell'applicazione al pod integro corrispondente. Lo stato di routing viene memorizzato nella cache nei pod router e aggiornato dai metadati del cluster archiviati su ogni nodo del cluster MySQL InnoDB. In caso di errore dell'istanza, il router regola il routing della connessione a un'istanza attiva.
MySQL InnoDB ClusterSet
Puoi creare un clusterSet MySQL InnoDB da un cluster MySQL InnoDB iniziale. In questo modo puoi aumentare la tolleranza agli errori se il cluster primario non è più disponibile.
Se l'istanza principale del cluster MySQL InnoDB non è più disponibile, puoi promuovere un cluster di replica nel ClusterSet a principale. Quando utilizzi il middleware MySQL Router, la tua applicazione non deve monitorare lo stato dell'istanza del database principale. Il routing viene modificato per inviare le connessioni al nuovo nodo primario dopo l'elezione. Tuttavia, è tua responsabilità assicurarti che le applicazioni che si connettono al middleware MySQL Router seguano le best practice per la resilienza, in modo che i tentativi di connessione vengano ripetuti se si verifica un errore durante il failover del cluster.
Costi
In questo documento, utilizzi i seguenti componenti fatturabili di Google Cloud:
Per generare una stima dei costi in base all'utilizzo previsto,
utilizza il calcolatore prezzi.
Al termine delle attività descritte in questo documento, puoi evitare l'addebito di ulteriori costi eliminando le risorse che hai creato. Per ulteriori informazioni, vedi Pulizia.
Prima di iniziare
Configura il progetto
- Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
-
In the Google Cloud console, on the project selector page, click Create project to begin creating a new Google Cloud project.
-
Make sure that billing is enabled for your Google Cloud project.
-
Enable the GKE API.
-
In the Google Cloud console, on the project selector page, click Create project to begin creating a new Google Cloud project.
-
Make sure that billing is enabled for your Google Cloud project.
-
Enable the GKE API.
-
Grant roles to your user account. Run the following command once for each of the following IAM roles:
role/storage.objectViewer, role/logging.logWriter, role/artifactregistry.Admin, roles/container.clusterAdmin, role/container.serviceAgent, roles/serviceusage.serviceUsageAdmin, roles/iam.serviceAccountAdmin
gcloud projects add-iam-policy-binding PROJECT_ID --member="user:USER_IDENTIFIER" --role=ROLE
- Replace
PROJECT_ID
with your project ID. -
Replace
USER_IDENTIFIER
with the identifier for your user account. For example,user:myemail@example.com
. - Replace
ROLE
with each individual role.
- Replace
Imposta le variabili di ambiente.
export PROJECT_ID=PROJECT_ID export CLUSTER_NAME=gkemulti-west export REGION=COMPUTE_REGION
Sostituisci i seguenti valori:
- PROJECT_ID: il tuo Google Cloud ID progetto.
- COMPUTE_REGION: la tua regione Compute Engine.
Per questo tutorial, la regione è
us-west1
. In genere, ti consigliamo di scegliere una regione vicina a te.
Imposta le variabili di ambiente predefinite.
gcloud config set project PROJECT_ID gcloud config set compute/region COMPUTE_REGION
Clona il repository di codice.
git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
Passa alla directory di lavoro.
cd kubernetes-engine-samples/databases/gke-stateful-mysql/kubernetes
Configurare i ruoli
Configura l'ambiente
In questo tutorial utilizzerai Cloud Shell per gestire le risorse ospitate su
Google Cloud. Cloud Shell è preinstallato con Docker e
le interfacce a riga di comando kubectl
e gcloud.
Per utilizzare Cloud Shell per configurare l'ambiente:
Crea un cluster GKE
In questa sezione creerai un cluster GKE regionale. A differenza di un cluster di zona, il control plane di un cluster regionale viene replicato in diverse zone, quindi un'interruzione in una singola zona non rende il control plane non disponibile.
Per creare un cluster GKE:
Autopilot
In Cloud Shell, crea un cluster GKE Autopilot nella regione
us-west1
.gcloud container clusters create-auto $CLUSTER_NAME \ --region=$REGION
Recupera le credenziali del cluster GKE.
gcloud container clusters get-credentials $CLUSTER_NAME \ --region=$REGION
Esegui il deployment di un servizio in tre zone. Questo tutorial utilizza un deployment Kubernetes. Un deployment è un oggetto API Kubernetes che consente di eseguire più repliche di pod distribuite tra i nodi di un cluster.
kubectl apply -f prepare-for-ha.yaml
Per impostazione predefinita, Autopilot esegue il provisioning delle risorse in due zone. Il deployment definito in
prepare-for-ha.yaml
garantisce che Autopilot esegua il provisioning dei nodi in tre zone del tuo cluster impostandoreplicas:3
,podAntiAffinity
conrequiredDuringSchedulingIgnoredDuringExecution
etopologyKey: "topology.kubernetes.io/zone"
.Controlla lo stato del deployment.
kubectl get deployment prepare-three-zone-ha --watch
Quando vedi tre pod nello stato pronto, annulla questo comando con
CTRL+C
. L'output è simile al seguente:NAME READY UP-TO-DATE AVAILABLE AGE prepare-three-zone-ha 0/3 3 0 9s prepare-three-zone-ha 1/3 3 1 116s prepare-three-zone-ha 2/3 3 2 119s prepare-three-zone-ha 3/3 3 3 2m16s
Esegui questo script per verificare che i pod siano stati implementati in tre zone.
bash ../scripts/inspect_pod_node.sh default
Ogni riga dell'output corrisponde a un pod e la seconda colonna indica la zona. L'output è simile al seguente:
gk3-gkemulti-west1-default-pool-eb354e2d-z6mv us-west1-b prepare-three-zone-ha-7885d77d9c-8f7qb gk3-gkemulti-west1-nap-25b73chq-739a9d40-4csr us-west1-c prepare-three-zone-ha-7885d77d9c-98fpn gk3-gkemulti-west1-default-pool-160c3578-bmm2 us-west1-a prepare-three-zone-ha-7885d77d9c-phmhj
Standard
In Cloud Shell, crea un cluster GKE Standard nella regione
us-west1
.gcloud container clusters create $CLUSTER_NAME \ --region=$REGION \ --machine-type="e2-standard-2" \ --disk-type="pd-standard" \ --num-nodes="5"
Recupera le credenziali del cluster GKE.
gcloud container clusters get-credentials $CLUSTER_NAME \ --region=$REGION
Esegui il deployment di StatefulSet MySQL
In questa sezione, esegui il deployment di un oggetto StatefulSet MySQL. Uno StatefulSet è un controller Kubernetes che mantiene un'identità univoca permanente per ciascuno dei suoi pod.
Ogni StatefulSet è costituito da tre repliche MySQL.
Per eseguire il deployment di MySQL StatefulSet:
Crea uno spazio dei nomi per StatefulSet.
kubectl create namespace mysql1
Crea il secret MySQL.
kubectl apply -n mysql1 -f secret.yaml
La password viene implementata con ogni pod e viene utilizzata dagli script di gestione e dai comandi per l'implementazione di MySQL InnoDB Cluster e ClusterSet in questo tutorial.
Crea StorageClass.
kubectl apply -n mysql1 -f storageclass.yaml
Questa classe di archiviazione utilizza il tipo di Persistent Disk
pd-balanced
che bilancia prestazioni e costi. Il campovolumeBindingMode
è impostato suWaitForFirstConsumer
, il che significa che GKE ritarda il provisioning di un PersistentVolume fino alla creazione del pod. Questa impostazione garantisce che il disco venga sottoposto a provisioning nella stessa zona in cui è pianificato il pod.Esegui il deployment di StatefulSet dei pod dell'istanza MySQL.
kubectl apply -n mysql1 -f c1-mysql.yaml
Questo comando esegue il deployment di StatefulSet composto da tre repliche. In questo tutorial, il cluster MySQL principale viene implementato in tre zone di
us-west1
. L'output è simile al seguente:service/mysql created statefulset.apps/dbc1 created
In questo tutorial, i limiti e le richieste delle risorse sono impostati su valori minimi per ridurre i costi. Quando pianifichi un carico di lavoro di produzione, assicurati di impostare questi valori in modo appropriato per le esigenze della tua organizzazione.
Verifica che StatefulSet sia stato creato correttamente.
kubectl get statefulset -n mysql1 --watch
La preparazione di StatefulSet può richiedere circa 10 minuti.
Quando tutti e tre i pod sono in stato pronto, esci dal comando utilizzando
Ctrl+C
. Se visualizzi erroriPodUnscheduleable
dovuti a CPU o memoria insufficienti, attendi qualche minuto per il ridimensionamento del control plane in modo da gestire il carico di lavoro elevato.L'output è simile al seguente:
NAME READY AGE dbc1 1/3 39s dbc1 2/3 50s dbc1 3/3 73s
Per esaminare il posizionamento dei pod sui nodi del cluster GKE, esegui questo script:
bash ../scripts/inspect_pod_node.sh mysql1 mysql
L'output mostra il nome del pod, il nome del nodo GKE e la zona in cui viene eseguito il provisioning del nodo ed è simile al seguente:
gke-gkemulti-west-5-default-pool-4bcaca65-jch0 us-west1-b dbc1-0 gke-gkemulti-west-5-default-pool-1ac6e8b5-ddjx us-west1-c dbc1-1 gke-gkemulti-west-5-default-pool-1f5baa66-bf8t us-west1-a dbc1-2
Le colonne nell'output rappresentano rispettivamente il nome host, la zona cloud e il nome del pod.
Il criterio
topologySpreadConstraints
nella specifica StatefulSet (c1-mysql.yaml
) indica allo scheduler di posizionare i pod in modo uniforme nel dominio in errore (topology.kubernetes.io/zone
).Il criterio
podAntiAffinity
applica il vincolo che i pod non devono essere posizionati sullo stesso nodo del cluster GKE (kubernetes.io/hostname
). Per i pod dell'istanza MySQL, questo criterio comporta il deployment dei pod in modo uniforme nelle tre zone della regione Google Cloud . Questo posizionamento consente l'alta disponibilità del cluster MySQL InnoDB posizionando ogni istanza di database in un dominio in errore separato.
Prepara il cluster MySQL InnoDB principale
Per configurare un cluster MySQL InnoDB:
Nel terminale Cloud Shell, imposta le configurazioni di replica del gruppo per le istanze MySQL da aggiungere al cluster.
bash ../scripts/c1-clustersetup.sh
Lo script si connetterà in remoto a ciascuna delle tre istanze MySQL per impostare e rendere persistenti le seguenti variabili di ambiente:
group_replication_ip_allowlist
: consente all'istanza all'interno del cluster di connettersi a qualsiasi istanza del gruppo.binlog_transaction_dependency_tracking='WRITESET'
: consente transazioni parallele che non sono in conflitto.
Nelle versioni di MySQL precedenti alla 8.0.22, utilizza
group_replication_ip_whitelist
anzichégroup_replication_ip_allowlist
.Apri un secondo terminale, in modo da non dover creare una shell per ogni pod.
Connettiti a MySQL Shell sul pod
dbc1-0
.kubectl -n mysql1 exec -it dbc1-0 -- \ /bin/bash \ -c 'mysqlsh --uri="root:$MYSQL_ROOT_PASSWORD@dbc1-0.mysql.mysql1.svc.cluster.local"'
Verifica la lista consentita della replica di gruppo MySQL per la connessione ad altre istanze.
\sql SELECT @@group_replication_ip_allowlist;
L'output è simile al seguente:
+----------------------------------+ | @@group_replication_ip_allowlist | +----------------------------------+ | mysql.mysql1.svc.cluster.local | +----------------------------------+
Verifica che
server-id
sia univoco in ciascuna delle istanze.\sql SELECT @@server_id;
L'output è simile al seguente:
+-------------+ | @@server_id | +-------------+ | 21 | +-------------+
Configura ogni istanza per l'utilizzo di MySQL InnoDB Cluster e crea un account amministratore su ogni istanza.
\js dba.configureInstance('root@dbc1-0.mysql.mysql1.svc.cluster.local', {password: os.getenv("MYSQL_ROOT_PASSWORD"),clusterAdmin: 'icadmin', clusterAdminPassword: os.getenv("MYSQL_ADMIN_PASSWORD")}); dba.configureInstance('root@dbc1-1.mysql.mysql1.svc.cluster.local', {password: os.getenv("MYSQL_ROOT_PASSWORD"),clusterAdmin: 'icadmin', clusterAdminPassword: os.getenv("MYSQL_ADMIN_PASSWORD")}); dba.configureInstance('root@dbc1-2.mysql.mysql1.svc.cluster.local', {password: os.getenv("MYSQL_ROOT_PASSWORD"),clusterAdmin: 'icadmin', clusterAdminPassword: os.getenv("MYSQL_ADMIN_PASSWORD")});
Tutte le istanze devono avere lo stesso nome utente e la stessa password affinché il cluster MySQL InnoDB funzioni correttamente. Ogni comando produce un output simile al seguente:
... The instance 'dbc1-2.mysql:3306' is valid to be used in an InnoDB cluster. Cluster admin user 'icadmin'@'%' created. The instance 'dbc1-2.mysql.mysql1.svc.cluster.local:3306' is already ready to be used in an InnoDB cluster. Successfully enabled parallel appliers.
Verifica che l'istanza sia pronta per essere utilizzata in un cluster MySQL InnoDB.
dba.checkInstanceConfiguration()
L'output è simile al seguente:
... The instance 'dbc1-0.mysql.mysql1.svc.cluster.local:3306' is valid to be used in an InnoDB cluster. { "status": "ok" }
Facoltativamente, puoi connetterti a ogni istanza MySQL e ripetere questo comando. Ad esempio, esegui questo comando per controllare lo stato dell'istanza
dbc1-1
:kubectl -n mysql1 exec -it dbc1-0 -- \ /bin/bash \ -c 'mysqlsh --uri="root:$MYSQL_ROOT_PASSWORD@dbc1-1.mysql.mysql1.svc.cluster.local" \ --js --execute "dba.checkInstanceConfiguration()"'
Crea il cluster InnoDB MySQL principale
Successivamente, crea il cluster MySQL InnoDB utilizzando il comando MySQL Admin
createCluster
. Inizia con l'istanza dbc1-0
, che sarà l'istanza primaria per il cluster, poi aggiungi due repliche aggiuntive al cluster.
Per inizializzare il cluster MySQL InnoDB, segui questi passaggi:
Crea il cluster MySQL InnoDB.
var cluster=dba.createCluster('mycluster');
L'esecuzione del comando
createCluster
attiva queste operazioni:- Esegui il deployment dello schema dei metadati.
- Verifica che la configurazione sia corretta per la replica di gruppo.
- Registrala come istanza seed del nuovo cluster.
- Crea gli account interni necessari, ad esempio l'account utente di replica.
- Avvia la replica di gruppo.
Questo comando inizializza un cluster MySQL InnoDB con l'host
dbc1-0
come primario. Il riferimento al cluster è memorizzato nella variabile del cluster.L'output è simile al seguente:
A new InnoDB cluster will be created on instance 'dbc1-0.mysql:3306'. Validating instance configuration at dbc1-0.mysql:3306... This instance reports its own address as dbc1-0.mysql.mysql1.svc.cluster.local:3306 Instance configuration is suitable. NOTE: Group Replication will communicate with other instances using 'dbc1-0.mysql:33061'. Use the localAddress option to override. Creating InnoDB cluster 'mycluster' on 'dbc1-0.mysql.mysql1.svc.cluster.local:3306'... Adding Seed Instance... Cluster successfully created. Use Cluster.addInstance() to add MySQL instances. At least 3 instances are needed for the cluster to be able to withstand up to one server failure.
Aggiungi la seconda istanza al cluster.
cluster.addInstance('icadmin@dbc1-1.mysql', {password: os.getenv("MYSQL_ROOT_PASSWORD"), recoveryMethod: 'clone'});
Aggiungi l'istanza rimanente al cluster.
cluster.addInstance('icadmin@dbc1-2.mysql', {password: os.getenv("MYSQL_ROOT_PASSWORD"), recoveryMethod: 'clone'});
L'output è simile al seguente:
... The instance 'dbc1-2.mysql:3306' was successfully added to the cluster.
Verifica lo stato del cluster.
cluster.status()
Questo comando mostra lo stato del cluster. La topologia è costituita da tre host, uno principale e due secondari. In via facoltativa, puoi chiamare
cluster.status({extended:1})
.L'output è simile al seguente:
{ "clusterName": "mysql1", "defaultReplicaSet": { "name": "default", "primary": "dbc1-0.mysql:3306", "ssl": "REQUIRED", "status": "OK", "statusText": "Cluster is ONLINE and can tolerate up to ONE failure.", "topology": { "dbc1-0.mysql:3306": { "address": "dbc1-0.mysql:3306", "memberRole": "PRIMARY", "mode": "R/W", "readReplicas": {}, "replicationLag": null, "role": "HA", "status": "ONLINE", "version": "8.0.28" }, "dbc1-1.mysql:3306": { "address": "dbc1-1.mysql:3306", "memberRole": "SECONDARY", "mode": "R/O", "readReplicas": {}, "replicationLag": null, "role": "HA", "status": "ONLINE", "version": "8.0.28" }, "dbc1-2.mysql:3306": { "address": "dbc1-2.mysql:3306", "memberRole": "SECONDARY", "mode": "R/O", "readReplicas": {}, "replicationLag": null, "role": "HA", "status": "ONLINE", "version": "8.0.28" } }, "topologyMode": "Single-Primary" }, "groupInformationSourceMember": "dbc1-0.mysql:3306" }
Se vuoi, puoi chiamare il numero
cluster.status({extended:1})
per ottenere ulteriori dettagli sullo stato.
Crea un database di esempio
Per creare un database di esempio:
Crea un database e carica i dati al suo interno.
\sql create database loanapplication; use loanapplication CREATE TABLE loan (loan_id INT unsigned AUTO_INCREMENT PRIMARY KEY, firstname VARCHAR(30) NOT NULL, lastname VARCHAR(30) NOT NULL , status VARCHAR(30) );
Inserisci dati di esempio nel database. Per inserire i dati, devi essere connesso all'istanza principale del cluster.
INSERT INTO loan (firstname, lastname, status) VALUES ( 'Fred','Flintstone','pending'); INSERT INTO loan (firstname, lastname, status) VALUES ( 'Betty','Rubble','approved');
Verifica che la tabella contenga le tre righe inserite nel passaggio precedente.
SELECT * FROM loan;
L'output è simile al seguente:
+---------+-----------+------------+----------+ | loan_id | firstname | lastname | status | +---------+-----------+------------+----------+ | 1 | Fred | Flintstone | pending | | 2 | Betty | Rubble | approved | +---------+-----------+------------+----------+ 2 rows in set (0.0010 sec)
Crea un clusterSet MySQL InnoDB
Puoi creare un ClusterSet MySQL InnoDB per gestire la replica dal cluster primario ai cluster di replica, utilizzando un canale di replica ClusterSet dedicato.
Un clusterSet MySQL InnoDB offre la tolleranza agli errori per i deployment di cluster MySQL InnoDB collegando un cluster MySQL InnoDB primario a una o più repliche di se stesso in posizioni alternative, ad esempio più zone e più regioni.
Se hai chiuso MySQL Shell, crea una nuova shell eseguendo questo comando in un nuovo terminale Cloud Shell:
kubectl -n mysql1 exec -it dbc1-0 -- \
/bin/bash -c 'mysqlsh \
--uri="root:$MYSQL_ROOT_PASSWORD@dbc1-0.mysql.mysql1.svc.cluster.local"'
Per creare un MySQL InnoDB ClusterSet:
Nel terminale di MySQL Shell, ottieni un oggetto cluster.
\js cluster=dba.getCluster()
L'output è simile al seguente:
<Cluster:mycluster>
Inizializza un cluster InnoDB di MySQL con il cluster InnoDB di MySQL esistente memorizzato nell'oggetto cluster come primario.
clusterset=cluster.createClusterSet('clusterset')
L'output è simile al seguente:
A new ClusterSet will be created based on the Cluster 'mycluster'. * Validating Cluster 'mycluster' for ClusterSet compliance. * Creating InnoDB ClusterSet 'clusterset' on 'mycluster'... * Updating metadata... ClusterSet successfully created. Use ClusterSet.createReplicaCluster() to add Replica Clusters to it. <ClusterSet:clusterset>
Controlla lo stato del tuo MySQL InnoDB ClusterSet.
clusterset.status()
L'output è simile al seguente:
{ "clusters": { "mycluster": { "clusterRole": "PRIMARY", "globalStatus": "OK", "primary": "dbc1-0.mysql:3306" } }, "domainName": "clusterset", "globalPrimaryInstance": "dbc1-0.mysql:3306", "primaryCluster": "mycluster", "status": "HEALTHY", "statusText": "All Clusters available." }
Se vuoi, puoi chiamare il numero
clusterset.status({extended:1})
per ottenere ulteriori dettagli sullo stato, incluse informazioni sul cluster.Esci da MySQL Shell.
\q
Esegui il deployment di un router MySQL
Puoi eseguire il deployment di un router MySQL per indirizzare il traffico delle applicazioni client ai cluster corretti. Il routing si basa sulla porta di connessione dell'applicazione che esegue un'operazione di database:
- Le scritture vengono indirizzate all'istanza del cluster principale nel ClusterSet principale.
- Le letture possono essere indirizzate a qualsiasi istanza nel cluster principale.
Quando avvii un router MySQL, viene eseguito il bootstrap rispetto al deployment di MySQL InnoDB ClusterSet. Le istanze del router MySQL connesse al cluster InnoDB MySQL sono a conoscenza di eventuali switchover controllati o failover di emergenza e indirizzano il traffico al nuovo cluster primario.
Per eseguire il deployment di un router MySQL:
Nel terminale Cloud Shell, esegui il deployment di MySQL Router.
kubectl apply -n mysql1 -f c1-router.yaml
L'output è simile al seguente:
configmap/mysql-router-config created service/mysql-router created deployment.apps/mysql-router created
Controlla l'idoneità del deployment di MySQL Router.
kubectl -n mysql1 get deployment mysql-router --watch
Quando tutti e tre i pod sono pronti, l'output è simile al seguente:
NAME READY UP-TO-DATE AVAILABLE AGE mysql-router 3/3 3 0 3m36s
Se nella console viene visualizzato un errore
PodUnschedulable
, attendi un minuto o due mentre GKE esegue il provisioning di altri nodi. Aggiorna e dovresti visualizzare3/3 OK
.Avvia MySQL Shell su qualsiasi membro del cluster esistente.
kubectl -n mysql1 exec -it dbc1-0 -- \ /bin/bash -c 'mysqlsh --uri="root:$MYSQL_ROOT_PASSWORD@dbc1-0.mysql"'
Questo comando si connette al pod
dbc1-0
, quindi avvia una shell connessa all'istanza MySQLdbc1-0
.Verifica la configurazione del router.
clusterset=dba.getClusterSet() clusterset.listRouters()
L'output è simile al seguente:
{ "domainName": "clusterset", "routers": { "mysql-router-7cd8585fbc-74pkm::": { "hostname": "mysql-router-7cd8585fbc-74pkm", "lastCheckIn": "2022-09-22 23:26:26", "roPort": 6447, "roXPort": 6449, "rwPort": 6446, "rwXPort": 6448, "targetCluster": null, "version": "8.0.27" }, "mysql-router-7cd8585fbc-824d4::": { ... }, "mysql-router-7cd8585fbc-v2qxz::": { ... } } }
Esci da MySQL Shell.
\q
Esegui questo script per esaminare il posizionamento dei pod MySQL Router.
bash ../scripts/inspect_pod_node.sh mysql1 | sort
Lo script mostra il posizionamento del nodo e della zona cloud di tutti i pod nello spazio dei nomi
mysql1
, dove l'output è simile al seguente:gke-gkemulti-west-5-default-pool-1ac6e8b5-0h9v us-west1-c mysql-router-6654f985f5-df97q gke-gkemulti-west-5-default-pool-1ac6e8b5-ddjx us-west1-c dbc1-1 gke-gkemulti-west-5-default-pool-1f5baa66-bf8t us-west1-a dbc1-2 gke-gkemulti-west-5-default-pool-1f5baa66-kt03 us-west1-a mysql-router-6654f985f5-qlfj9 gke-gkemulti-west-5-default-pool-4bcaca65-2l6s us-west1-b mysql-router-6654f985f5-5967d gke-gkemulti-west-5-default-pool-4bcaca65-jch0 us-west1-b dbc1-0
Puoi notare che i pod MySQL Router sono distribuiti equamente tra le zone, ovvero non sono posizionati sullo stesso nodo di un pod MySQL o sullo stesso nodo di un altro pod MySQL Router.
Gestire gli upgrade di GKE e MySQL InnoDB Cluster
Gli aggiornamenti sia per MySQL sia per Kubernetes vengono rilasciati regolarmente. Segui le best practice operative per aggiornare regolarmente l'ambiente software. Per impostazione predefinita, GKE gestisce gli upgrade del cluster e del pool di nodi. Kubernetes e GKE forniscono anche funzionalità aggiuntive per facilitare gli upgrade del software MySQL.
Pianifica gli upgrade di GKE
Puoi adottare misure proattive e impostare configurazioni per ridurre i rischi e facilitare un upgrade del cluster più fluido quando esegui servizi stateful, tra cui:
Cluster standard: segui le best practice di GKE per l'upgrade dei cluster. Scegli una strategia di upgrade appropriata per assicurarti che gli upgrade vengano eseguiti durante il periodo di manutenzione:
- Scegli upgrade improvvisi se l'ottimizzazione dei costi è importante e se i tuoi workload possono tollerare un arresto controllato in meno di 60 minuti.
- Scegli gli upgrade blu/verde se i tuoi workload tollerano meno le interruzioni e un aumento temporaneo dei costi dovuto a un maggiore utilizzo delle risorse è accettabile.
Per saperne di più, consulta Eseguire l'upgrade di un cluster che esegue un carico di lavoro stateful. I cluster Autopilot vengono aggiornati automaticamente in base al canale di rilascio selezionato.
Utilizza i periodi di manutenzione per assicurarti che gli upgrade vengano eseguiti quando vuoi. Prima della periodo di manutenzione, assicurati che i backup del database siano riusciti.
Prima di consentire il traffico ai nodi MySQL aggiornati, utilizza i probe di idoneità e i probe di attività per assicurarti che siano pronti per il traffico.
Crea probe che valutino se la replica è sincronizzata prima di accettare il traffico. Questa operazione può essere eseguita tramite script personalizzati, a seconda della complessità e delle dimensioni del database.
Imposta una norma di budget di interruzione dei pod (PDB)
Quando un cluster MySQL InnoDB è in esecuzione su GKE, deve essere in esecuzione un numero sufficiente di istanze in qualsiasi momento per soddisfare il requisito di quorum.
In questo tutorial, dato un cluster MySQL di tre istanze, due istanze devono
essere disponibili per formare un quorum. Un criterio PodDisruptionBudget
ti consente di
limitare il numero di pod che possono essere terminati in un dato momento. Questa funzionalità è
utile sia per le operazioni in stato stazionario dei servizi stateful sia per
gli upgrade del cluster.
Per garantire che un numero limitato di pod venga interrotto contemporaneamente, imposta il PDB per il carico di lavoro su maxUnavailable: 1
. In questo modo, in qualsiasi momento
dell'operazione di servizio, non è in esecuzione più di un pod.
Il seguente manifest dei criteri PodDisruptionBudget
imposta il numero massimo di pod non disponibili su uno per l'applicazione MySQL.
Per applicare il criterio PDB al cluster:
Applica il criterio PDB utilizzando
kubectl
.kubectl apply -n mysql1 -f mysql-pdb-maxunavailable.yaml
Visualizza lo stato del PDB.
kubectl get poddisruptionbudgets -n mysql1 mysql-pdb -o yaml
Nella sezione
status
dell'output, visualizza i conteggi dei podcurrentHealthy
edesiredHealthy
. L'output è simile al seguente:status: ... currentHealthy: 3 desiredHealthy: 2 disruptionsAllowed: 1 expectedPods: 3 ...
Pianifica gli upgrade binari di MySQL
Kubernetes e GKE forniscono funzionalità per facilitare gli upgrade del binario MySQL. Tuttavia, devi eseguire alcune operazioni per prepararti agli upgrade.
Prima di iniziare la procedura di upgrade, tieni presente le seguenti considerazioni:
- Gli upgrade devono essere eseguiti prima in un ambiente di test. Per i sistemi di produzione, devi eseguire ulteriori test in un ambiente di pre-produzione.
- Per alcune release binarie, non puoi eseguire il downgrade della versione dopo l'upgrade. Prenditi il tempo necessario per comprendere le implicazioni di un upgrade.
- Le origini di replica possono essere replicate in una versione più recente. Tuttavia, la copia da una versione più recente a una precedente in genere non è supporta.
- Assicurati di avere un backup completo del database prima di eseguire il deployment della versione aggiornata.
- Tieni presente la natura effimera dei pod di Kubernetes. Qualsiasi stato di configurazione memorizzato dal pod che non si trova sul volume permanente andrà perso quando il pod viene ridistribuito.
- Per gli upgrade binari di MySQL, utilizza la stessa strategia di aggiornamento di PDB, pool di nodi e probe descritta in precedenza.
In un ambiente di produzione, devi seguire queste best practice:
- Crea un'immagine container con la nuova versione di MySQL.
- Mantieni le istruzioni di compilazione dell'immagine in un repository di controllo del codice sorgente.
- Utilizza una pipeline di creazione e test automatizzati delle immagini come Cloud Build e memorizza il binario dell'immagine in un registro delle immagini come Artifact Registry.
Per semplificare questo tutorial, non creerai e non renderai persistente un'immagine container. Utilizzerai invece le immagini MySQL pubbliche.
Esegui il deployment del binario MySQL aggiornato
Per eseguire l'upgrade del binario MySQL, devi emettere un comando dichiarativo che modifica la versione dell'immagine della risorsa StatefulSet. GKE esegue i passaggi necessari per arrestare il pod corrente, eseguire il deployment di un nuovo pod con il binario aggiornato e collegare il disco permanente al nuovo pod.
Verifica che il PDB sia stato creato.
kubectl get poddisruptionbudgets -n mysql1
Recupera l'elenco dei set stateful.
kubectl get statefulsets -n mysql1
Ottieni l'elenco dei pod in esecuzione utilizzando l'etichetta
app
.kubectl get pods --selector=app=mysql -n mysql1
Aggiorna l'immagine MySQL nel set stateful.
kubectl -n mysql1 \ set image statefulset/dbc1 \ mysql=mysql/mysql-server:8.0.30
L'output è simile al seguente:
statefulset.apps/mysql image updated
Controlla lo stato dei pod in fase di terminazione e dei nuovi pod.
kubectl get pods --selector=app=mysql -n mysql1
Convalida l'upgrade binario di MySQL
Durante l'upgrade, puoi verificare lo stato dell'implementazione, i nuovi pod e il servizio esistente.
Conferma l'upgrade eseguendo il comando
rollout status
.kubectl rollout status statefulset/dbc1 -n mysql1
L'output è simile al seguente:
partitioned roll out complete: 3 new pods have been updated...
Conferma la versione dell'immagine esaminando il set stateful.
kubectl get statefulsets -o wide -n mysql1
L'output è simile al seguente:
NAME READY AGE CONTAINERS IMAGES dbc1 3/3 37m mysql mysql/mysql-server:8.0.30
Controlla lo stato del cluster.
kubectl -n mysql1 \ exec -it dbc1-0 -- \ /bin/bash \ -c 'mysqlsh \ --uri="root:$MYSQL_ROOT_PASSWORD@dbc1-1.mysql.mysql1.svc.cluster.local" \ --js \ --execute "print(dba.getClusterSet().status({extended:1})); print(\"\\n\")"'
Per ogni istanza del cluster, cerca i valori di stato e versione nell'output. L'output è simile al seguente:
... "status": "ONLINE", "version": "8.0.30" ...
Esegui il rollback dell'ultima implementazione dell'app
Quando ripristini il deployment di una versione binaria aggiornata, il processo di implementazione viene invertito e viene eseguito il deployment di un nuovo insieme di pod con la versione precedente dell'immagine.
Per ripristinare il deployment alla versione funzionante precedente, utilizza il comando rollout undo
:
kubectl rollout undo statefulset/dbc1 -n mysql1
L'output è simile al seguente:
statefulset.apps/dbc1 rolled back
Scalare orizzontalmente il cluster di database
Per scalare orizzontalmente il cluster MySQL InnoDB, aggiungi nodi aggiuntivi al pool di nodi del cluster GKE (obbligatorio solo se utilizzi Standard), esegui il deployment di istanze MySQL aggiuntive, quindi aggiungi ogni istanza al cluster MySQL InnoDB esistente.
Aggiungi nodi al cluster Standard
Questa operazione non è necessaria se utilizzi un cluster Autopilot.
Per aggiungere nodi al cluster Standard, segui le istruzioni riportate di seguito per Cloud Shell o la console Google Cloud . Per la procedura dettagliata, vedi Ridimensiona un node pool.
gcloud
In Cloud Shell, ridimensiona il pool di nodi predefinito a otto istanze in ogni gruppo di istanze gestite.
gcloud container clusters resize ${CLUSTER_NAME} \
--node-pool default-pool \
--num-nodes=8
Console
Per aggiungere nodi al cluster Standard:
- Apri la pagina
gkemulti-west1
Cluster nella console Google Cloud . - Seleziona Nodi e fai clic su Pool predefinito.
- Scorri verso il basso fino a Gruppi di istanze.
- Per ogni gruppo di istanze, ridimensiona il valore
Number of nodes
da 5 a 8 nodi.
Aggiungi pod MySQL al cluster primario
Per eseguire il deployment di pod MySQL aggiuntivi per scalare orizzontalmente il cluster:
In Cloud Shell, aggiorna il numero di repliche nel deployment MySQL da tre a cinque.
kubectl scale -n mysql1 --replicas=5 -f c1-mysql.yaml
Verifica l'avanzamento del deployment.
kubectl -n mysql1 get pods --selector=app=mysql -o wide
Per determinare se i pod sono pronti, utilizza il flag
--watch
per monitorare il deployment. Se utilizzi cluster Autopilot e visualizzi erroriPod Unschedulable
, questo potrebbe indicare che GKE sta eseguendo il provisioning dei nodi per ospitare i pod aggiuntivi.Configura le impostazioni di replica dei gruppi per le nuove istanze MySQL da aggiungere al cluster.
bash ../scripts/c1-clustersetup.sh 3 4
Lo script invia i comandi alle istanze in esecuzione sui pod con ordinali da 3 a 4.
Apri MySQL Shell.
kubectl -n mysql1 \ exec -it dbc1-0 -- \ /bin/bash \ -c 'mysqlsh \ --uri="root:$MYSQL_ROOT_PASSWORD@dbc1-0.mysql"'
Configura le due nuove istanze MySQL.
dba.configureInstance('root:$MYSQL_ROOT_PASSWORD@dbc1-3.mysql', {password: os.getenv("MYSQL_ROOT_PASSWORD"),clusterAdmin: 'icadmin', clusterAdminPassword: os.getenv("MYSQL_ADMIN_PASSWORD")}); dba.configureInstance('root:$MYSQL_ROOT_PASSWORD@dbc1-4.mysql', {password: os.getenv("MYSQL_ROOT_PASSWORD"),clusterAdmin: 'icadmin', clusterAdminPassword: os.getenv("MYSQL_ADMIN_PASSWORD")});
I comandi verificano se l'istanza è configurata correttamente per l'utilizzo di MySQL InnoDB Cluster ed eseguono le modifiche di configurazione necessarie.
Aggiungi una delle nuove istanze al cluster primario.
cluster = dba.getCluster() cluster.addInstance('icadmin@dbc1-3.mysql', {password: os.getenv("MYSQL_ROOT_PASSWORD"), recoveryMethod: 'clone'});
Aggiungi una seconda nuova istanza al cluster primario.
cluster.addInstance('icadmin@dbc1-4.mysql', {password: os.getenv("MYSQL_ROOT_PASSWORD"), recoveryMethod: 'clone'});
Ottieni lo stato di ClusterSet, che include anche lo stato del cluster.
clusterset = dba.getClusterSet() clusterset.status({extended: 1})
L'output è simile al seguente:
"domainName": "clusterset", "globalPrimaryInstance": "dbc1-0.mysql:3306", "metadataServer": "dbc1-0.mysql:3306", "primaryCluster": "mycluster", "status": "HEALTHY", "statusText": "All Clusters available."
Esci da MySQL Shell.
\q
Esegui la pulizia
Per evitare che al tuo account Google Cloud vengano addebitati costi relativi alle risorse utilizzate in questo tutorial, elimina il progetto che contiene le risorse oppure mantieni il progetto ed elimina le singole risorse.
Elimina il progetto
Il modo più semplice per evitare la fatturazione è eliminare il progetto creato per il tutorial.
Delete a Google Cloud project:
gcloud projects delete PROJECT_ID
Passaggi successivi
- Scopri di più su come l'integrazione di Google Cloud Observability MySQL raccoglie le metriche delle prestazioni relative a InnoDB.
- Scopri di più su Backup per GKE, un servizio per il backup e il ripristino dei carichi di lavoro in GKE.
- Esplora i volumi permanenti in modo più dettagliato.