Este documento está dirigido a administradores de bases de datos, arquitectos de soluciones en la nube y profesionales de operaciones que quieran desplegar una topología de MySQL de alta disponibilidad en Google Kubernetes Engine.
Sigue este tutorial para aprender a desplegar un clúster InnoDB de MySQL y un conjunto de clústeres InnoDB de MySQL, así como el middleware MySQL Router en tu clúster de GKE, y a realizar actualizaciones.
Objetivos
En este tutorial aprenderás a:- Crea y despliega un servicio de Kubernetes con estado.
- Despliega un clúster InnoDB de MySQL para conseguir alta disponibilidad.
- Implementa el middleware Router para enrutar las operaciones de la base de datos.
- Despliega un InnoDB ClusterSet de MySQL para tolerar fallos.
- Simula una conmutación por error de un clúster de MySQL.
- Actualiza la versión de MySQL.
En las siguientes secciones se describe la arquitectura de la solución que crearás en este tutorial.
Clúster InnoDB de MySQL
En tu clúster regional de GKE, mediante un StatefulSet, implementas una instancia de base de datos MySQL con la nomenclatura y la configuración necesarias para crear un clúster InnoDB de MySQL. Para ofrecer tolerancia a fallos y alta disponibilidad, debes desplegar tres pods de instancias de base de datos. De esta forma, se asegura de que la mayoría de los pods de diferentes zonas estén disponibles en cualquier momento para que se pueda elegir un primario correctamente mediante un protocolo de consenso, y hace que tu clúster InnoDB de MySQL sea tolerante a los fallos de una sola zona.
Una vez implementado, designa un pod como instancia principal para que gestione las operaciones de lectura y escritura. Los otros dos pods son réplicas secundarias de solo lectura. Si la instancia principal sufre un fallo en la infraestructura, puedes ascender uno de estos dos pods de réplica para que se convierta en el principal.
En un espacio de nombres independiente, despliega tres pods de MySQL Router para proporcionar enrutamiento de conexiones y mejorar la resiliencia. En lugar de conectarse directamente al servicio de base de datos, tus aplicaciones se conectan a pods de MySQL Router. Cada pod de Router conoce el estado y el propósito de cada pod de clúster InnoDB de MySQL y dirige las operaciones de la aplicación al pod correspondiente que esté en buen estado. El estado de enrutamiento se almacena en caché en los pods de Router y se actualiza a partir de los metadatos del clúster almacenados en cada nodo del clúster MySQL InnoDB. En caso de que falle una instancia de, el router ajusta el enrutamiento de la conexión a una instancia activa.
MySQL InnoDB ClusterSet
Puedes crear un conjunto de clústeres InnoDB de MySQL a partir de un clúster InnoDB de MySQL inicial. De esta forma, puedes aumentar la tolerancia a fallos si el clúster principal deja de estar disponible.
Si la instancia principal del clúster InnoDB de MySQL ya no está disponible, puedes ascender a principal un clúster de réplica del ClusterSet. Cuando se usa el middleware MySQL Router, tu aplicación no tiene que monitorizar el estado de la instancia de base de datos principal. El enrutamiento se ajusta para enviar las conexiones al nuevo primario una vez que se haya producido la elección. Sin embargo, es tu responsabilidad asegurarte de que las aplicaciones que se conecten a tu middleware MySQL Router sigan las prácticas recomendadas para la resiliencia, de forma que se reintenten las conexiones si se produce un error durante la conmutación por error del clúster.
Costes
En este documento, se utilizan los siguientes componentes facturables de Google Cloud:
Para generar una estimación de costes basada en el uso previsto,
utiliza la calculadora de precios.
Cuando termines las tareas que se describen en este documento, puedes evitar que se te siga facturando eliminando los recursos que has creado. Para obtener más información, consulta la sección Limpiar.
Antes de empezar
Configurar el proyecto
- 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.
Roles required to create a project
To create a project, you need the Project Creator (
roles/resourcemanager.projectCreator
), which contains theresourcemanager.projects.create
permission. Learn how to grant roles. -
Verify that billing is enabled for your Google Cloud project.
-
Enable the GKE API.
Roles required to enable APIs
To enable APIs, you need the Service Usage Admin IAM role (
roles/serviceusage.serviceUsageAdmin
), which contains theserviceusage.services.enable
permission. Learn how to grant roles. -
In the Google Cloud console, on the project selector page, click Create project to begin creating a new Google Cloud project.
Roles required to create a project
To create a project, you need the Project Creator (
roles/resourcemanager.projectCreator
), which contains theresourcemanager.projects.create
permission. Learn how to grant roles. -
Verify that billing is enabled for your Google Cloud project.
-
Enable the GKE API.
Roles required to enable APIs
To enable APIs, you need the Service Usage Admin IAM role (
roles/serviceusage.serviceUsageAdmin
), which contains theserviceusage.services.enable
permission. Learn how to grant roles. -
Make sure that you have the following role or roles on the project: role/storage.objectViewer, role/logging.logWriter, role/artifactregistry.Admin, roles/container.clusterAdmin, role/container.serviceAgent, roles/serviceusage.serviceUsageAdmin, roles/iam.serviceAccountAdmin
Check for the roles
-
In the Google Cloud console, go to the IAM page.
Go to IAM - Select the project.
-
In the Principal column, find all rows that identify you or a group that you're included in. To learn which groups you're included in, contact your administrator.
- For all rows that specify or include you, check the Role column to see whether the list of roles includes the required roles.
Grant the roles
-
In the Google Cloud console, go to the IAM page.
Ir a IAM - Selecciona el proyecto.
- Haz clic en Conceder acceso.
-
En el campo Nuevos principales, introduce tu identificador de usuario. Normalmente, se trata de la dirección de correo de una cuenta de Google.
- En la lista Selecciona un rol, elige un rol.
- Para conceder más roles, haz clic en Añadir otro rol y añade cada rol adicional.
- Haz clic en Guardar.
Configurar un entorno
En este tutorial, usarás Cloud Shell para gestionar los recursos alojados enGoogle Cloud. Cloud Shell tiene preinstalados Docker y las CLIs
kubectl
y gcloud.Para usar Cloud Shell y configurar tu entorno, sigue estos pasos:
Define las variables de entorno.
export PROJECT_ID=PROJECT_ID export CLUSTER_NAME=gkemulti-west export CONTROL_PLANE_LOCATION=CONTROL_PLANE_LOCATION
Sustituye los siguientes valores:
- PROJECT_ID: tu Google Cloud ID de proyecto.
- CONTROL_PLANE_LOCATION: la región de Compute Engine del plano de control de tu clúster. En este tutorial, la región es
us-west1
. Normalmente, te interesa una región que esté cerca de ti.
Define las variables de entorno predeterminadas.
gcloud config set project PROJECT_ID gcloud config set compute/region CONTROL_PLANE_LOCATION
Clona el repositorio de código.
git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
Cambia al directorio de trabajo.
cd kubernetes-engine-samples/databases/gke-stateful-mysql/kubernetes
Crear un clúster de GKE
En esta sección, crearás un clúster de GKE regional. A diferencia de los clústeres zonales, el plano de control de los clústeres regionales se replica en varias zonas, por lo que una interrupción en una sola zona no provoca que el plano de control deje de estar disponible.
Para crear un clúster de GKE, sigue estos pasos:
Autopilot
En Cloud Shell, crea un clúster de Autopilot de GKE en la región
us-west1
.gcloud container clusters create-auto $CLUSTER_NAME \ --location=$CONTROL_PLANE_LOCATION
Obtén las credenciales del clúster de GKE.
gcloud container clusters get-credentials $CLUSTER_NAME \ --location=$CONTROL_PLANE_LOCATION
Despliega un servicio en tres zonas. En este tutorial se usa un Deployment de Kubernetes. Un Deployment es un objeto de la API de Kubernetes que te permite ejecutar varias réplicas de pods distribuidas entre los nodos de un clúster.
kubectl apply -f prepare-for-ha.yaml
De forma predeterminada, Autopilot aprovisiona recursos en dos zonas. El Deployment definido en
prepare-for-ha.yaml
asegura que Autopilot aprovisione nodos en tres zonas de tu clúster. Para ello, se definenreplicas:3
ypodAntiAffinity
conrequiredDuringSchedulingIgnoredDuringExecution
ytopologyKey: "topology.kubernetes.io/zone"
.Comprueba el estado del despliegue.
kubectl get deployment prepare-three-zone-ha --watch
Cuando veas tres pods en estado listo, cancela este comando con
CTRL+C
. El resultado debería ser similar al siguiente: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
Ejecuta esta secuencia de comandos para validar que tus pods se han desplegado en tres zonas.
bash ../scripts/inspect_pod_node.sh default
Cada línea del resultado corresponde a un pod y la segunda columna indica la zona. El resultado debería ser similar al siguiente:
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
Estándar
En Cloud Shell, crea un clúster estándar de GKE en la región
us-west1
.gcloud container clusters create $CLUSTER_NAME \ --location=$CONTROL_PLANE_LOCATION \ --machine-type="e2-standard-2" \ --disk-type="pd-standard" \ --num-nodes="5"
Obtén las credenciales del clúster de GKE.
gcloud container clusters get-credentials $CLUSTER_NAME \ --location=$CONTROL_PLANE_LOCATION
Desplegar StatefulSets de MySQL
En esta sección, desplegarás un StatefulSet de MySQL. Un StatefulSet es un controlador de Kubernetes que mantiene una identidad única y persistente para cada uno de sus pods.
Cada StatefulSet consta de tres réplicas de MySQL.
Para implementar el StatefulSet de MySQL, sigue estos pasos:
Crea un espacio de nombres para el StatefulSet.
kubectl create namespace mysql1
Crea el secreto de MySQL.
kubectl apply -n mysql1 -f secret.yaml
La contraseña se implementa con cada pod y la usan los comandos y las secuencias de comandos de gestión para la implementación de clústeres y ClusterSet de MySQL InnoDB en este tutorial.
Crea el objeto StorageClass.
kubectl apply -n mysql1 -f storageclass.yaml
Esta clase de almacenamiento usa el tipo de disco persistente
pd-balanced
, que equilibra el rendimiento y el coste. El campovolumeBindingMode
se define comoWaitForFirstConsumer
, lo que significa que GKE retrasa el aprovisionamiento de un PersistentVolume hasta que se crea el pod. Este ajuste asegura que el disco se aprovisione en la misma zona en la que se ha programado el pod.Despliega el StatefulSet de los pods de la instancia de MySQL.
kubectl apply -n mysql1 -f c1-mysql.yaml
Este comando implementa el StatefulSet que consta de tres réplicas. En este tutorial, el clúster de MySQL principal se despliega en tres zonas de
us-west1
. El resultado debería ser similar al siguiente:service/mysql created statefulset.apps/dbc1 created
En este tutorial, los límites y las solicitudes de recursos se han definido con valores mínimos para ahorrar costes. Cuando planifiques una carga de trabajo de producción, asegúrate de definir estos valores de forma adecuada para las necesidades de tu organización.
Verifica que el StatefulSet se ha creado correctamente.
kubectl get statefulset -n mysql1 --watch
El StatefulSet puede tardar unos 10 minutos en estar listo.
Cuando los tres pods estén en estado Ready, sal del comando con
Ctrl+C
. Si aparecen erroresPodUnscheduleable
debido a que no hay suficiente CPU o memoria, espera unos minutos a que el plano de control cambie de tamaño para adaptarse a la carga de trabajo grande.El resultado debería ser similar al siguiente:
NAME READY AGE dbc1 1/3 39s dbc1 2/3 50s dbc1 3/3 73s
Para inspeccionar la colocación de tus pods en los nodos del clúster de GKE, ejecuta esta secuencia de comandos:
bash ../scripts/inspect_pod_node.sh mysql1 mysql
El resultado muestra el nombre del pod, el nombre del nodo de GKE y la zona en la que se aprovisiona el nodo. Es similar al siguiente:
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
Las columnas de la salida representan el nombre de host, la zona de nube y el nombre del pod, respectivamente.
La política
topologySpreadConstraints
de la especificación de StatefulSet (c1-mysql.yaml
) indica al programador que coloque los pods de forma uniforme en el dominio de errores (topology.kubernetes.io/zone
).La política
podAntiAffinity
aplica la restricción de que los pods no se coloquen en el mismo nodo de clúster de GKE (kubernetes.io/hostname
). En el caso de los pods de la instancia de MySQL, esta política hace que los pods se implementen de forma uniforme en las tres zonas de la región Google Cloud . Esta colocación permite la alta disponibilidad del clúster InnoDB de MySQL colocando cada instancia de base de datos en un dominio de errores independiente.
Preparar el clúster InnoDB de MySQL principal
Para configurar un clúster InnoDB de MySQL, sigue estos pasos:
En la terminal Cloud Shell, define las configuraciones de replicación de grupos de las instancias de MySQL que se añadirán al clúster.
bash ../scripts/c1-clustersetup.sh
El script se conectará de forma remota a cada una de las tres instancias de MySQL para definir y conservar las siguientes variables de entorno:
group_replication_ip_allowlist
: permite que la instancia del clúster se conecte a cualquier instancia del grupo.binlog_transaction_dependency_tracking='WRITESET'
: permite transacciones paralelas que no entran en conflicto.
En las versiones de MySQL anteriores a la 8.0.22, usa
group_replication_ip_whitelist
en lugar degroup_replication_ip_allowlist
.Abre una segunda terminal para no tener que crear un shell para cada pod.
Conéctate a MySQL Shell en el 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 de permitidos de la replicación de grupo de MySQL para conectarte a otras instancias.
\sql SELECT @@group_replication_ip_allowlist;
El resultado debería ser similar al siguiente:
+----------------------------------+ | @@group_replication_ip_allowlist | +----------------------------------+ | mysql.mysql1.svc.cluster.local | +----------------------------------+
Verifica que el
server-id
sea único en cada una de las instancias.\sql SELECT @@server_id;
El resultado debería ser similar al siguiente:
+-------------+ | @@server_id | +-------------+ | 21 | +-------------+
Configura cada instancia para usar el clúster InnoDB de MySQL y crea una cuenta de administrador en cada instancia.
\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")});
Todas las instancias deben tener el mismo nombre de usuario y la misma contraseña para que el clúster InnoDB de MySQL funcione correctamente. Cada comando genera un resultado similar al siguiente:
... 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 que la instancia esté lista para usarse en un clúster InnoDB de MySQL.
dba.checkInstanceConfiguration()
El resultado debería ser similar al siguiente:
... The instance 'dbc1-0.mysql.mysql1.svc.cluster.local:3306' is valid to be used in an InnoDB cluster. { "status": "ok" }
También puedes conectarte a cada instancia de MySQL y repetir este comando. Por ejemplo, ejecuta este comando para comprobar el estado de la instancia
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()"'
Crear el clúster InnoDB de MySQL principal
A continuación, crea el clúster InnoDB de MySQL con el comando MySQL Admin
createCluster
. Empieza con la instanciadbc1-0
, que será la instancia principal del clúster, y, a continuación, añade dos réplicas más al clúster.Para inicializar el clúster InnoDB de MySQL, sigue estos pasos:
Crea el clúster InnoDB de MySQL.
var cluster=dba.createCluster('mycluster');
Al ejecutar el comando
createCluster
, se activan estas operaciones:- Implementa el esquema de metadatos.
- Verifica que la configuración sea correcta para la replicación de grupo.
- Regístrala como instancia inicial del nuevo clúster.
- Crea las cuentas internas necesarias, como la cuenta de usuario de replicación.
- Inicia la replicación de grupo.
Este comando inicializa un clúster InnoDB de MySQL con el host
dbc1-0
como principal. La referencia del clúster se almacena en la variable del clúster.El resultado es similar al siguiente:
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.
Añade la segunda instancia al clúster.
cluster.addInstance('icadmin@dbc1-1.mysql', {password: os.getenv("MYSQL_ROOT_PASSWORD"), recoveryMethod: 'clone'});
Añade la instancia restante al clúster.
cluster.addInstance('icadmin@dbc1-2.mysql', {password: os.getenv("MYSQL_ROOT_PASSWORD"), recoveryMethod: 'clone'});
El resultado debería ser similar al siguiente:
... The instance 'dbc1-2.mysql:3306' was successfully added to the cluster.
Verifica el estado del clúster.
cluster.status()
Este comando muestra el estado del clúster. La topología consta de tres hosts: una instancia principal y dos secundarias. También puedes llamar a
cluster.status({extended:1})
.El resultado debería ser similar al siguiente:
{ "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" }
Si quieres, puedes llamar al
cluster.status({extended:1})
para obtener más información sobre el estado.
Crear una base de datos de muestra
Para crear una base de datos de ejemplo, sigue estos pasos:
Crea una base de datos y carga datos en ella.
\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) );
Inserta datos de muestra en la base de datos. Para insertar datos, debes conectarte a la instancia principal del clúster.
INSERT INTO loan (firstname, lastname, status) VALUES ( 'Fred','Flintstone','pending'); INSERT INTO loan (firstname, lastname, status) VALUES ( 'Betty','Rubble','approved');
Verifica que la tabla contenga las tres filas insertadas en el paso anterior.
SELECT * FROM loan;
El resultado debería ser similar al siguiente:
+---------+-----------+------------+----------+ | loan_id | firstname | lastname | status | +---------+-----------+------------+----------+ | 1 | Fred | Flintstone | pending | | 2 | Betty | Rubble | approved | +---------+-----------+------------+----------+ 2 rows in set (0.0010 sec)
Crear un ClusterSet de InnoDB de MySQL
Puedes crear un ClusterSet de MySQL InnoDB para gestionar la replicación desde tu clúster principal a los clústeres de réplica mediante un canal de replicación de ClusterSet específico.
Un conjunto de clústeres InnoDB de MySQL proporciona tolerancia a desastres para las implementaciones de clústeres InnoDB de MySQL. Para ello, vincula un clúster InnoDB de MySQL principal con una o varias réplicas de sí mismo en ubicaciones alternativas, como varias zonas y varias regiones.
Si has cerrado MySQL Shell, crea uno nuevo ejecutando este comando en un nuevo terminal de 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"'
Para crear un conjunto de clústeres InnoDB de MySQL, siga estos pasos:
En el terminal de MySQL Shell, obtén un objeto de clúster.
\js cluster=dba.getCluster()
El resultado debería ser similar al siguiente:
<Cluster:mycluster>
Inicializa un ClusterSet de MySQL InnoDB con el clúster de MySQL InnoDB almacenado en el objeto de clúster como principal.
clusterset=cluster.createClusterSet('clusterset')
El resultado debería ser similar al siguiente:
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>
Consulta el estado de tu conjunto de clústeres InnoDB de MySQL.
clusterset.status()
El resultado debería ser similar al siguiente:
{ "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." }
Si quieres, puedes llamar a
clusterset.status({extended:1})
para obtener más detalles sobre el estado, incluida información sobre el clúster.Sal de MySQL Shell.
\q
Desplegar un enrutador MySQL
Puedes desplegar un router MySQL para dirigir el tráfico de la aplicación cliente a los clústeres adecuados. El enrutamiento se basa en el puerto de conexión de la aplicación que emite una operación de base de datos:
- Las escrituras se dirigen a la instancia de clúster principal del ClusterSet principal.
- Las lecturas se pueden dirigir a cualquier instancia del clúster principal.
Cuando inicias un MySQL Router, se inicia en la implementación de MySQL InnoDB ClusterSet. Las instancias de MySQL Router conectadas con el conjunto de clústeres InnoDB de MySQL detectan cualquier cambio controlado o conmutación por error de emergencia y dirigen el tráfico al nuevo clúster principal.
Para implementar un MySQL Router, sigue estos pasos:
En el terminal de Cloud Shell, implementa MySQL Router.
kubectl apply -n mysql1 -f c1-router.yaml
El resultado debería ser similar al siguiente:
configmap/mysql-router-config created service/mysql-router created deployment.apps/mysql-router created
Comprueba si el despliegue de MySQL Router está listo.
kubectl -n mysql1 get deployment mysql-router --watch
Cuando los tres pods estén listos, el resultado será similar al siguiente:
NAME READY UP-TO-DATE AVAILABLE AGE mysql-router 3/3 3 0 3m36s
Si ves un error
PodUnschedulable
en la consola, espera uno o dos minutos mientras GKE aprovisiona más nodos. Actualiza la página y deberías ver3/3 OK
.Inicia MySQL Shell en cualquier miembro del clúster.
kubectl -n mysql1 exec -it dbc1-0 -- \ /bin/bash -c 'mysqlsh --uri="root:$MYSQL_ROOT_PASSWORD@dbc1-0.mysql"'
Este comando se conecta al pod
dbc1-0
y, a continuación, inicia un shell conectado a la instancia de MySQLdbc1-0
.Verifica la configuración del router.
clusterset=dba.getClusterSet() clusterset.listRouters()
El resultado debería ser similar al siguiente:
{ "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::": { ... } } }
Sal de MySQL Shell.
\q
Ejecuta esta secuencia de comandos para inspeccionar la colocación de los pods de MySQL Router.
bash ../scripts/inspect_pod_node.sh mysql1 | sort
La secuencia de comandos muestra la colocación de nodos y zonas de Cloud de todos los pods del espacio de nombres
mysql1
, donde la salida es similar a la siguiente: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
Puedes observar que los pods de MySQL Router se distribuyen de forma equitativa entre las zonas, es decir, no se colocan en el mismo nodo que un pod de MySQL ni en el mismo nodo que otro pod de MySQL Router.
Gestionar las actualizaciones de GKE y MySQL InnoDB Cluster
Las actualizaciones de MySQL y Kubernetes se publican de forma periódica. Sigue las prácticas recomendadas operativas para actualizar tu entorno de software con regularidad. De forma predeterminada, GKE gestiona las actualizaciones de clústeres y grupos de nodos. Kubernetes y GKE también ofrecen funciones adicionales para facilitar las actualizaciones del software MySQL.
Planificar las actualizaciones de GKE
Puedes tomar medidas proactivas y definir configuraciones para reducir los riesgos y facilitar una actualización del clúster más fluida cuando ejecutes servicios con estado, como los siguientes:
Clústeres estándar: sigue las prácticas recomendadas de GKE para actualizar clústeres. Elige una estrategia de actualización adecuada para asegurarte de que las actualizaciones se realicen durante el periodo de la ventana de mantenimiento:
- Elige actualizaciones de picos si la optimización de costes es importante y si tus cargas de trabajo pueden tolerar un cierre gradual en menos de 60 minutos.
- Elige las actualizaciones azul-verde si tus cargas de trabajo toleran menos las interrupciones y puedes asumir un aumento temporal de los costes debido a un mayor uso de los recursos.
Para obtener más información, consulta Actualizar un clúster en el que se ejecuta una carga de trabajo con reconocimiento del estado. Los clústeres de Autopilot se actualizan automáticamente en función del canal de lanzamiento que hayas seleccionado.
Usa las ventanas de mantenimiento para asegurarte de que las actualizaciones se realicen cuando quieras. Antes de la ventana de mantenimiento, asegúrate de que las copias de seguridad de tu base de datos se hayan creado correctamente.
Antes de permitir el tráfico a los nodos de MySQL actualizados, usa las sondas de disponibilidad y las sondas de actividad para asegurarte de que están listos para recibir tráfico.
Crea sondas que evalúen si la replicación está sincronizada antes de aceptar el tráfico. Esto se puede hacer mediante secuencias de comandos personalizadas, en función de la complejidad y la escala de tu base de datos.
Definir una política de cobertura para interrupciones de pods (PDB)
Cuando un clúster de MySQL InnoDB se ejecuta en GKE, debe haber un número suficiente de instancias en ejecución en cualquier momento para cumplir el requisito de quórum.
En este tutorial, dado un clúster de MySQL de tres instancias, dos instancias deben estar disponibles para formar un quórum. Una política de
PodDisruptionBudget
te permite limitar el número de pods que se pueden finalizar en un momento dado. Esto es útil tanto para las operaciones de estado estable de tus servicios con estado como para las actualizaciones de clústeres.Para asegurarte de que solo se interrumpa un número limitado de pods simultáneamente, define el PDB de tu carga de trabajo en
maxUnavailable: 1
. De esta forma, se asegura de que, en cualquier momento de la operación del servicio, no haya más de un pod sin ejecutar.El siguiente manifiesto de la política
PodDisruptionBudget
define el número máximo de pods no disponibles en uno para tu aplicación MySQL.Para aplicar la política de PDB a tu clúster, sigue estos pasos:
Aplica la política de PDB con
kubectl
.kubectl apply -n mysql1 -f mysql-pdb-maxunavailable.yaml
Consulta el estado de la PDB.
kubectl get poddisruptionbudgets -n mysql1 mysql-pdb -o yaml
En la sección
status
del resultado, consulta los recuentos decurrentHealthy
ydesiredHealthy
Pods. El resultado debería ser similar al siguiente:status: ... currentHealthy: 3 desiredHealthy: 2 disruptionsAllowed: 1 expectedPods: 3 ...
Planificar las actualizaciones binarias de MySQL
Kubernetes y GKE ofrecen funciones para facilitar las actualizaciones del binario de MySQL. Sin embargo, debe realizar algunas operaciones para preparar las actualizaciones.
Antes de empezar el proceso de actualización, ten en cuenta lo siguiente:
- Las actualizaciones deben realizarse primero en un entorno de prueba. En el caso de los sistemas de producción, debes realizar más pruebas en un entorno de preproducción.
- En algunas versiones binarias, no puedes cambiar a una versión anterior una vez que se haya realizado una actualización. Dedica tiempo a comprender las implicaciones de una actualización.
- Las fuentes de replicación pueden replicarse en una versión más reciente. Sin embargo, normalmente no se admite la copia de una versión más reciente a una anterior.
- Asegúrate de tener una copia de seguridad completa de la base de datos antes de implementar la versión actualizada.
- Ten en cuenta la naturaleza efímera de los pods de Kubernetes. Cualquier estado de configuración que almacene el pod y que no esté en el volumen persistente se perderá cuando se vuelva a implementar el pod.
- Para las actualizaciones binarias de MySQL, usa la misma PDB, estrategia de actualización del grupo de nodos y sondas que se han descrito anteriormente.
En un entorno de producción, debe seguir estas prácticas recomendadas:
- Crea una imagen de contenedor con la nueva versión de MySQL.
- Conserva las instrucciones de compilación de la imagen en un repositorio de control de versiones.
- Usa una canalización automatizada de compilación y pruebas de imágenes, como Cloud Build, y almacena el archivo binario de la imagen en un registro de imágenes, como Artifact Registry.
Para que este tutorial sea sencillo, no crearás ni conservarás una imagen de contenedor, sino que usarás las imágenes públicas de MySQL.
Desplegar el archivo binario de MySQL actualizado
Para llevar a cabo la actualización binaria de MySQL, debes ejecutar un comando declarativo que modifique la versión de la imagen del recurso StatefulSet. GKE lleva a cabo los pasos necesarios para detener el pod actual, implementar un nuevo pod con el binario actualizado y adjuntar el disco persistente al nuevo pod.
Verifica que se haya creado la PDB.
kubectl get poddisruptionbudgets -n mysql1
Obtén la lista de conjuntos con reconocimiento del estado.
kubectl get statefulsets -n mysql1
Obtén la lista de pods en ejecución con la etiqueta
app
.kubectl get pods --selector=app=mysql -n mysql1
Actualiza la imagen de MySQL en el conjunto con estado.
kubectl -n mysql1 \ set image statefulset/dbc1 \ mysql=mysql/mysql-server:8.0.30
El resultado debería ser similar al siguiente:
statefulset.apps/mysql image updated
Comprueba el estado de los pods que se están terminando y de los nuevos.
kubectl get pods --selector=app=mysql -n mysql1
Validar la actualización binaria de MySQL
Durante la actualización, puedes verificar el estado del lanzamiento, los nuevos pods y el servicio actual.
Confirma la actualización ejecutando el comando
rollout status
.kubectl rollout status statefulset/dbc1 -n mysql1
El resultado debería ser similar al siguiente:
partitioned roll out complete: 3 new pods have been updated...
Confirma la versión de la imagen inspeccionando el conjunto con estado.
kubectl get statefulsets -o wide -n mysql1
El resultado debería ser similar al siguiente:
NAME READY AGE CONTAINERS IMAGES dbc1 3/3 37m mysql mysql/mysql-server:8.0.30
Comprueba el estado del clúster.
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\")"'
En cada instancia del clúster, busque los valores de estado y versión en el resultado. El resultado debería ser similar al siguiente:
... "status": "ONLINE", "version": "8.0.30" ...
Restaurar la última versión de la aplicación
Cuando reviertes la implementación de una versión binaria actualizada, el proceso de lanzamiento se invierte y se implementa un nuevo conjunto de pods con la versión de imagen anterior.
Para revertir la implementación a la versión anterior que funcionaba, usa el comando
rollout undo
kubectl rollout undo statefulset/dbc1 -n mysql1
El resultado debería ser similar al siguiente:
statefulset.apps/dbc1 rolled back
Escalar horizontalmente un clúster de base de datos
Para escalar horizontalmente tu clúster InnoDB de MySQL, añade nodos al pool de nodos del clúster de GKE (solo es necesario si usas el modo Estándar), implementa instancias de MySQL adicionales y, a continuación, añade cada instancia al clúster InnoDB de MySQL.
Añadir nodos a un clúster Standard
Esta operación no es necesaria si utilizas un clúster de Autopilot.
Para añadir nodos a tu clúster estándar, sigue las instrucciones que se indican a continuación para Cloud Shell o la consola de Google Cloud . Para ver los pasos detallados, consulta Cambiar el tamaño de un pool de nodos.
gcloud
En Cloud Shell, cambia el tamaño del grupo de nodos predeterminado a ocho instancias en cada grupo de instancias administrado.
gcloud container clusters resize ${CLUSTER_NAME} \ --node-pool default-pool \ --num-nodes=8
Consola
Para añadir nodos a tu clúster estándar, sigue estos pasos:
- Abre la
gkemulti-west1
página Clústeres Google Cloud en la consola. - Selecciona Nodos y haz clic en grupo predeterminado.
- Desplázate hacia abajo hasta Grupos de instancias.
- En cada grupo de instancias, cambia el valor de
Number of nodes
de 5 a 8 nodos.
Añadir pods de MySQL al clúster principal
Para implementar pods de MySQL adicionales y escalar tu clúster horizontalmente, sigue estos pasos:
En Cloud Shell, actualiza el número de réplicas de la implementación de MySQL de tres a cinco.
kubectl scale -n mysql1 --replicas=5 -f c1-mysql.yaml
Verifica el progreso de la implementación.
kubectl -n mysql1 get pods --selector=app=mysql -o wide
Para determinar si los pods están listos, usa la marca
--watch
para monitorizar la implementación. Si utilizas clústeres de Autopilot y ves erroresPod Unschedulable
, puede que GKE esté aprovisionando nodos para dar cabida a los pods adicionales.Configura los ajustes de replicación de grupo de las nuevas instancias de MySQL que quieras añadir al clúster.
bash ../scripts/c1-clustersetup.sh 3 4
La secuencia de comandos envía los comandos a las instancias que se ejecutan en los pods con ordinales del 3 al 4.
Abre MySQL Shell.
kubectl -n mysql1 \ exec -it dbc1-0 -- \ /bin/bash \ -c 'mysqlsh \ --uri="root:$MYSQL_ROOT_PASSWORD@dbc1-0.mysql"'
Configura las dos nuevas instancias de 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")});
Los comandos comprueban si la instancia está configurada correctamente para usar el clúster InnoDB de MySQL y realizan los cambios de configuración necesarios.
Añade una de las nuevas instancias al clúster principal.
cluster = dba.getCluster() cluster.addInstance('icadmin@dbc1-3.mysql', {password: os.getenv("MYSQL_ROOT_PASSWORD"), recoveryMethod: 'clone'});
Añade una segunda instancia nueva al clúster principal.
cluster.addInstance('icadmin@dbc1-4.mysql', {password: os.getenv("MYSQL_ROOT_PASSWORD"), recoveryMethod: 'clone'});
Obtiene el estado de ClusterSet, que también incluye el estado de Cluster.
clusterset = dba.getClusterSet() clusterset.status({extended: 1})
El resultado debería ser similar al siguiente:
"domainName": "clusterset", "globalPrimaryInstance": "dbc1-0.mysql:3306", "metadataServer": "dbc1-0.mysql:3306", "primaryCluster": "mycluster", "status": "HEALTHY", "statusText": "All Clusters available."
Sal de MySQL Shell.
\q
Limpieza
Para evitar que los recursos utilizados en este tutorial se cobren en tu cuenta de Google Cloud, elimina el proyecto que contiene los recursos o conserva el proyecto y elimina los recursos.
Eliminar el proyecto
La forma más fácil de evitar que te cobren es eliminar el proyecto que has creado para el tutorial.
- In the Google Cloud console, go to the Manage resources page.
- In the project list, select the project that you want to delete, and then click Delete.
- In the dialog, type the project ID, and then click Shut down to delete the project.
Siguientes pasos
- Consulta más información sobre cómo la integración de MySQL de Google Cloud Observability recoge métricas de rendimiento relacionadas con InnoDB.
- Consulta más información sobre Copia de seguridad de GKE, un servicio con el que puedes crear copias de seguridad y restaurar cargas de trabajo en GKE.
- Consulta más información sobre los volúmenes persistentes.
-