Este documento está dirigido a los administradores de bases de datos, los arquitectos de la nube y los profesionales de operaciones interesados en implementar una topología de MySQL con alta disponibilidad en Google Kubernetes Engine.
Sigue este instructivo para aprender a implementar un MySQL InnoDB Cluster y un MySQL InnoDB ClusterSet, además del middleware MySQL Router en tu clúster de GKE y cómo realizar actualizaciones.
Objetivos
En este instructivo aprenderás realizar las siguientes tareas:- Crea e implementa un servicio de Kubernetes con estado.
- Implementa un MySQL InnoDB Cluster para alta disponibilidad.
- Implementar middleware de router para el enrutamiento de operaciones de base de datos.
- Implementar un MySQL InnoDB ClusterSet para la tolerancia a desastres
- Simular una conmutación por error de clúster de MySQL.
- Realizar una actualización de la versión de MySQL.
En las siguientes secciones, se describe la arquitectura de la solución que compilarás en este instructivo.
MySQL InnoDB Cluster
En el clúster de GKE regional, mediante un StatefulSet, debes implementar una instancia de base de datos de MySQL con el nombre y la configuración necesarios para crear un MySQL InnoDB Cluster. Para proporcionar tolerancia a errores y alta disponibilidad, implementa tres Pods de instancias de base de datos. Esto garantiza que la mayoría de los Pods en diferentes zonas estén disponibles en cualquier momento para una elección principal exitosa mediante un protocolo de consenso, y hace que tu MySQL InnoDB Cluster tolere las fallas zonales individuales.
Una vez implementado, designa un Pod como la instancia principal para entregar operaciones de lectura y escritura. Los otros dos Pods son réplicas secundarias de solo lectura. Si la instancia principal experimenta una falla en la infraestructura, puedes promover uno de estos dos Pods de réplica para que se convierta en la instancia principal.
En un espacio de nombres independiente, implementa tres Pods de MySQL Router para proporcionar enrutamiento de conexión con el fin de mejorar la resiliencia. En lugar de conectarse directamente al servicio de base de datos, las aplicaciones se conectan a los Pods de MySQL Router. Cada Pod del router conoce el estado y el propósito de cada Pod de MySQL InnoDB Cluster, y enruta las operaciones de la aplicación al Pod en buen estado correspondiente. El estado de enrutamiento se almacena en caché en los Pods del router y se actualiza desde los metadatos del clúster almacenados en cada nodo de MySQL InnoDB Cluster. En caso de que se produzca una falla en la instancia, el router ajusta el enrutamiento de la conexión a una instancia activa.
MySQL InnoDB ClusterSet
Puedes crear un MySQL InnoDB ClusterSet a partir de un MySQL InnoDB Cluster inicial. Esto te permite aumentar la tolerancia a desastres si el clúster principal ya no está disponible.
Si la instancia principal de MySQL InnoDB Cluster ya no está disponible, puedes ascender un clúster de réplica en el ClusterSet a principal. Cuando se usa middleware de MySQL Router, la aplicación no necesita realizar un seguimiento del estado de la instancia de la base de datos principal. El enrutamiento se ajusta para enviar conexiones al nuevo elemento principal después de que se produce la elección. Sin embargo, es tu responsabilidad asegurarte de que las aplicaciones que se conectan a tu middleware de MySQL Router sigan las prácticas recomendadas para resiliencia, de modo que se vuelvan a intentar las conexiones si se produce un error durante la conmutación por error del clúster.
Costos
En este documento, usarás los siguientes componentes facturables de Google Cloud:
Para generar una estimación de costos en función del uso previsto, usa la calculadora de precios.
Cuando finalices las tareas que se describen en este documento, puedes borrar los recursos que creaste para evitar que continúe la facturación. Para obtener más información, consulta Cómo realizar una limpieza.
Antes de comenzar
Configurar tu 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.
-
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.
Configura funciones
-
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_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
Configure su entorno
En este instructivo, usarás Cloud Shell para administrar recursos alojados en Google Cloud. Cloud Shell viene preinstalado con Docker y la CLI de gcloud y kubectl
.
Sigue estos pasos para configurar tu entorno con Cloud Shell:
Configurar variables de entorno
export PROJECT_ID=PROJECT_ID export CLUSTER_NAME=gkemulti-west export REGION=COMPUTE_REGION
Reemplaza los siguientes valores:
- PROJECT_ID: el ID del proyecto de Google Cloud
- COMPUTE_REGION: tu región de Compute Engine.
Para este instructivo, la región es
us-west1
. Por lo general, se recomienda una región cercana a ti.
Configura las variables de entorno predeterminadas.
gcloud config set project PROJECT_ID gcloud config set compute/region COMPUTE_REGION
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
Crea un clúster de GKE
En esta sección, crearás un clúster de GKE regional. A diferencia de un clúster zonal, el plano de control de un clúster regional se replica en varias zonas, por lo que una interrupción en una sola zona no hace que el plano de control esté 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 \ --region=$REGION
Obtén las credenciales del clúster de GKE.
gcloud container clusters get-credentials $CLUSTER_NAME \ --region=$REGION
Implementa un servicio en tres zonas.
kubectl apply -f prepare-for-ha.yaml
De forma predeterminada, Autopilot aprovisiona recursos en dos zonas. La implementación definida en
prepare-for-ha.yaml
garantiza que Autopilot aprovisione nodos en tres zonas de tu clúster mediante la configuración dereplicas:3
,podAntiAffinity
conrequiredDuringSchedulingIgnoredDuringExecution
ytopologyKey: "topology.kubernetes.io/zone"
.Verifica el estado del Deployment.
kubectl get deployment prepare-three-zone-ha --watch
Cuando veas tres Pods en el estado listo, cancela este comando con
CTRL+C
. El resultado es similar a este: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 hayan implementado 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 de la nube. El resultado es similar a este:
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 de Standard de GKE en la región
us-west1
.gcloud container clusters create $CLUSTER_NAME \ --region=$REGION \ --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 \ --region=$REGION
Implemente MySQL StatefulSets
En esta sección, debes implementar un MySQL StatefulSet. Cada StatefulSet consta de tres réplicas de MySQL.
Para implementar el MySQL StatefulSet, 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 las secuencias de comandos de administración y los comandos para la implementación de MySQL InnoDB Cluster y ClusterSet en este instructivo.
Crea la 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 costo. El campovolumeBindingMode
se establece enWaitForFirstConsumer
, lo que significa que GKE retrasa el aprovisionamiento de un PersistentVolume hasta que se crea el Pod. Esta configuración garantiza que el disco se aprovisione en la misma zona en la que está programado el Pod.Implementar 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 instructivo, el clúster principal de MySQL se implementa en tres zonas de
us-west1
. El resultado es similar a este:service/mysql created statefulset.apps/dbc1 created
En este instructivo, los límites y las solicitudes de recursos se establecen en valores mínimos para ahorrar costos. Cuando planifiques una carga de trabajo de producción, asegúrate de establecer estos valores de forma adecuada para las necesidades de tu organización.
Verifica que el StatefulSet se haya creado correctamente.
kubectl get statefulset -n mysql1 --watch
El SatefulSet puede tardar unos 10 minutos en estar listo.
Cuando los tres Pods estén listos, sal del comando mediante
Ctrl+C
. Si ves erroresPodUnscheduleable
debido a que no hay suficiente CPU o memoria, espera unos minutos para que el plano de control cambie de tamaño y se adapte a la gran carga de trabajo.El resultado es similar a este:
NAME READY AGE dbc1 1/3 39s dbc1 2/3 50s dbc1 3/3 73s
Para inspeccionar la ubicació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, y 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 del resultado representan el nombre de host, la zona de la nube y el nombre del Pod, respectivamente.
La política
topologySpreadConstraints
en la especificación de StatefulSet (c1-mysql.yaml
) dirige al programador para que coloque los pods de manera uniforme en el dominio con fallas (topology.kubernetes.io/zone
).La política
podAntiAffinity
aplica la restricción de que los Pods no se deben colocar en el mismo nodo del clúster de GKE (kubernetes.io/hostname
). En el caso de los Pods de instancias de MySQL, esta política hace que los Pods se implementen de manera uniforme en las tres zonas de la región de Google Cloud. Esta ubicación permite una alta disponibilidad del MySQL InnoDB Cluster porque coloca cada instancia de la base de datos en un dominio con fallas separado.
Prepara el MySQL InnoDB Cluster principal
Para configurar un MySQL InnoDB Cluster, sigue estos pasos:
En la terminal de Cloud Shell, establece las configuraciones de replicación del grupo para las instancias de MySQL que se agregarán a tu clúster.
bash ../scripts/c1-clustersetup.sh
La secuencia de comandos se conectará de forma remota a cada una de las tres instancias de MySQL para establecer y conservar las siguientes variables de entorno:
group_replication_ip_allowlist
: permite que la instancia dentro del clúster se conecte a cualquier instancia del grupo.binlog_transaction_dependency_tracking='WRITESET'
: permite las transacciones en paralelo que no entrarán 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, de modo que no necesites crear una shell para cada Pod.
Conéctate a la shell del MySQL 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 entidades permitidas de replicación de grupos de MySQL para conectarte a otras instancias.
\sql SELECT @@group_replication_ip_allowlist;
El resultado es similar a este:
+----------------------------------+ | @@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 es similar a este:
+-------------+ | @@server_id | +-------------+ | 21 | +-------------+
Configura cada instancia para el uso de MySQL InnoDB Cluster y crea una cuenta de administrador en cada una.
\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 contraseña para que MySQL InnoDB Cluster funcione correctamente. Cada comando produce 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 MySQL InnoDB Cluster.
dba.checkInstanceConfiguration()
El resultado es similar a este:
... The instance 'dbc1-0.mysql.mysql1.svc.cluster.local:3306' is valid to be used in an InnoDB cluster. { "status": "ok" }
De manera opcional, puedes conectarte a cada instancia de MySQL y repetir este comando. Por ejemplo, ejecuta este comando para verificar el estado en 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()"'
Crea el MySQL InnoDB Cluster principal
Luego, crea el MySQL InnoDB Cluster mediante el comando createCluster
del administrador de MySQL. Comienza con la instancia dbc1-0
, que será la instancia principal del clúster y, luego, agrega dos réplicas adicionales al clúster.
Para inicializar el MySQL InnoDB Cluster, sigue estos pasos:
Crea el MySQL InnoDB Cluster.
var cluster=dba.createCluster('mycluster');
Cuando ejecutas el comando
createCluster
, se activan estas operaciones:- Implementa el esquema de metadatos.
- Verifica que la configuración sea correcta para la replicación de grupos.
- Regístralo como la instancia de origen del clúster nuevo.
- Crea las cuentas internas necesarias, como la cuenta de usuario de replicación.
- Inicia la replicación del grupo.
Este comando inicializa un MySQL InnoDB Cluster con el host
dbc1-0
como la instancia 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.
Agrega la instancia secundaria al clúster.
cluster.addInstance('icadmin@dbc1-1.mysql', {password: os.getenv("MYSQL_ROOT_PASSWORD"), recoveryMethod: 'clone'});
Agrega la instancia secundaria al clúster.
cluster.addInstance('icadmin@dbc1-2.mysql', {password: os.getenv("MYSQL_ROOT_PASSWORD"), recoveryMethod: 'clone'});
El resultado es similar a este:
... 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. De manera opcional, puedes llamar a
cluster.status({extended:1})
.El resultado es similar a este:
{ "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" }
De manera opcional, puedes llamar a
cluster.status({extended:1})
para obtener detalles adicionales del estado.
Crea una base de datos de muestra
Para crear una base de datos de muestra, sigue estos pasos:
Crea una base de datos y cargar 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) );
Ingresa datos de muestra en la base de datos. Para insertar datos, debes estar conectado 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 es similar a este:
+---------+-----------+------------+----------+ | loan_id | firstname | lastname | status | +---------+-----------+------------+----------+ | 1 | Fred | Flintstone | pending | | 2 | Betty | Rubble | approved | +---------+-----------+------------+----------+ 2 rows in set (0.0010 sec)
Crea un MySQL InnoDB ClusterSet
Puedes crear un MySQL InnoDB ClusterSet para administrar la replicación de tu clúster principal a los clústeres de réplica mediante un canal de replicación de ClusterSet dedicado.
Un MySQL InnoDB ClusterSet proporciona tolerancia a desastres para implementaciones de MySQL InnoDB Cluster, mediante la vinculación de un MySQL InnoDB Cluster principal con una o más réplicas de sí mismas en ubicaciones alternativas, como varias zonas y regiones.
Si cerraste MySQL Shell, crea un shell nuevo mediante la ejecución de este comando en una terminal nueva 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 MySQL InnoDB ClusterSet, sigue estos pasos:
En tu terminal de MySQL Shell, obtén un objeto de clúster.
\js cluster=dba.getCluster()
El resultado es similar a este:
<Cluster:mycluster>
Inicializa un MySQL InnoDB ClusterSet con el MySQL InnoDB Cluster existente almacenado en el objeto de clúster como la instancia principal.
clusterset=cluster.createClusterSet('clusterset')
El resultado es similar a este:
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>
Comprueba el estado de tu MySQL InnoDB ClusterSet.
clusterset.status()
El resultado es similar a este:
{ "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." }
De manera opcional, puedes llamar a
clusterset.status({extended:1})
para obtener detalles adicionales del estado, incluida la información sobre el clúster.Sal de MySQL Shell.
\q
Implementa un MySQL Router
Puedes implementar un MySQL Router para dirigir el tráfico de las aplicaciones 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 enrutan a la instancia del clúster principal en el ClusterSet principal.
- Las lecturas se pueden enrutar a cualquier instancia en el clúster principal.
Cuando inicias un MySQL Router, se inicia con la implementación del MySQL InnoDB ClusterSet. Las instancias de MySQL Router conectadas con el MySQL InnoDB ClusterSet conocen todos los cambios controlados o las conmutaciones por error de emergencia y dirigen el tráfico al clúster principal nuevo.
Para implementar un MySQL Router, sigue estos pasos:
En la terminal de Cloud Shell, implementa el MySQL Router.
kubectl apply -n mysql1 -f c1-router.yaml
El resultado es similar a este:
configmap/mysql-router-config created service/mysql-router created deployment.apps/mysql-router created
Comprueba la preparación de la implementación del MySQL Router.
kubectl -n mysql1 get deployment mysql-router --watch
Cuando los tres Pods están listos, el resultado es 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 existente.
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, luego, inicia una shell conectada a la instancia de MySQLdbc1-0
.Verifica la configuración del router.
clusterset=dba.getClusterSet() clusterset.listRouters()
El resultado es similar a este:
{ "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 ubicación de los Pods del MySQL Router.
bash ../scripts/inspect_pod_node.sh mysql1 | sort
La secuencia de comandos muestra el nodo y la ubicación de la zona de Cloud de todos los Pods en el espacio de nombres
mysql1
, en el que el resultado es similar al 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, que no estén ubicadas en el mismo nodo que un Pod de MySQL o en el mismo nodo que otro Pod de MySQL Router.
Administra las actualizaciones de GKE y MySQL InnoDB Cluster
Las actualizaciones para MySQL y Kubernetes se lanzan con regularidad. Sigue las prácticas recomendadas operativas para actualizar el entorno de software con regularidad. De forma predeterminada, GKE administra las actualizaciones del clúster y del grupo de nodos por ti. Kubernetes y GKE también proporcionan funciones adicionales para facilitar las actualizaciones de software de MySQL.
Planifica las actualizaciones de GKE
Puedes tomar medidas proactivas y establecer parámetros de configuración para mitigar el riesgo y facilitar una actualización del clúster sin problemas cuando ejecutas servicios con estado, incluidos los siguientes:
Clústeres de Standard: Sigue las prácticas recomendadas de GKE para actualizar clústeres. Elige una estrategia de actualización adecuada para garantizar que las actualizaciones se realicen durante el período de mantenimiento:
- Elige actualizaciones de aumento si la optimización de costos es importante y si tus cargas de trabajo pueden tolerar un cierre ordenado en menos de 60 minutos.
- Elige actualizaciones azul-verde si las cargas de trabajo son menos tolerantes a las interrupciones. Además, un aumento temporal del costo debido al mayor uso de recursos es aceptable.
Para obtener más información, consulta Actualiza un clúster que ejecuta una carga de trabajo con estado. Los clústeres de Autopilot se actualizan de forma automática, según el canal de versiones que seleccionaste.
Usa los períodos de mantenimiento para garantizar que las actualizaciones se realicen cuando lo desees. Antes del período de mantenimiento, asegúrate de que las copias de seguridad de la base de datos se ejecuten correctamente.
Antes de permitir el tráfico a los nodos de MySQL actualizados, usa sondeos de preparación y funcionamiento a fin de asegurarte de que estén listos para el tráfico.
Crea sondeos que evalúen si la replicación está sincronizada antes de aceptar tráfico Esto se puede hacer mediante secuencias de comandos personalizadas, según la complejidad y la escala de la base de datos.
Configura una política de presupuesto de interrupción de Pods (PDB)
Cuando un MySQL InnoDB Cluster se ejecuta en GKE, debe haber una cantidad suficiente de instancias en ejecución en cualquier momento para cumplir con el requisito de quórum.
En este instructivo, dado un clúster de MySQL de tres instancias, dos instancias deben estar disponibles para formar un quórum. Una política PodDisruptionBudget
te permite limitar la cantidad de Pods que se pueden finalizar en un momento determinado. Esto es útil para las operaciones de estado estable de tus servicios con estado y para las actualizaciones de clústeres.
Para asegurarte de que una cantidad limitada de Pods se interrumpa de forma simultánea, debes configurar el PDB de la carga de trabajo como maxUnavailable: 1
. Esto garantiza que en cualquier momento de la operación del servicio no se ejecute más de un Pod.
En el manifiesto de la política PodDisruptionBudget
siguiente, se establece la cantidad máxima de Pods no disponibles para uno para tu aplicación de MySQL.
Para aplicar la política de PDB a tu clúster, sigue estos pasos:
Aplica la política de PDB mediante
kubectl
.kubectl apply -n mysql1 -f mysql-pdb-maxunavailable.yaml
Consulta el estado del PDB.
kubectl get poddisruptionbudgets -n mysql1 mysql-pdb -o yaml
En la sección
status
del resultado, consulta los recuentos de PodscurrentHealthy
ydesiredHealthy
. El resultado es similar a este:status: ... currentHealthy: 3 desiredHealthy: 2 disruptionsAllowed: 1 expectedPods: 3 ...
Planifica las actualizaciones de objeto binario de MySQL
Kubernetes y GKE proporcionan funciones para facilitar las actualizaciones de objeto binario de MySQL. Sin embargo, debes realizar algunas operaciones para prepararte para las mejoras.
Ten en cuenta las siguientes consideraciones antes de comenzar el proceso de actualización:
- 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.
- Para algunas versiones de objeto binario, no puedes cambiar a una versión inferior de la versión una vez que se realiza una actualización. Tómate el tiempo para comprender las implicaciones de una actualización.
- Las fuentes de replicación pueden replicar a una versión más reciente. Sin embargo, por lo general, 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 que no se encuentra en el volumen persistente se perderá cuando se vuelva a implementar el Pod.
- Para las actualizaciones de objeto binario de MySQL, usa el mismo PDB, la estrategia de actualización de grupos de nodos y los sondeos como se describió antes.
En un entorno de producción, debes seguir estas recomendaciones:
- Crear una imagen de contenedor con la versión nueva de MySQL
- Almacena las instrucciones de compilación de imágenes en un repositorio de control de origen.
- Usa una canalización de compilación y prueba de imágenes automatizada, como Cloud Build, y almacena el objeto binario de la imagen en un registro de imágenes, como Artifact Registry.
Para que este instructivo sea simple, no compilarás ni conservarás una imagen de contenedor; en su lugar, usarás las imágenes públicas de MySQL.
Implementa el objeto binario actualizado de MySQL
Para realizar la actualización de objeto binario de MySQL, emite un comando declarativo que modifique la versión de la imagen del recurso StatefulSet. GKE realiza los pasos necesarios para detener el Pod actual, implementar un Pod nuevo con el objeto binario actualizado y conectar el disco persistente al Pod nuevo.
Verifica que se haya creado el PDB.
kubectl get poddisruptionbudgets -n mysql1
Obtén la lista de conjuntos con 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 es similar a este:
statefulset.apps/mysql image updated
Verifica el estado de los Pods que se cerrarán y de los nuevos.
kubectl get pods --selector=app=mysql -n mysql1
Valida la actualización de objeto binario de MySQL
Durante la actualización, puedes verificar el estado del lanzamiento, los nuevos Pods y el servicio existente.
Confirma la actualización, ejecuta el comando
rollout status
.kubectl rollout status statefulset/dbc1 -n mysql1
El resultado es similar a este:
partitioned roll out complete: 3 new pods have been updated...
Para confirmar la versión de la imagen, inspecciona el conjunto con estado.
kubectl get statefulsets -o wide -n mysql1
El resultado es similar a este:
NAME READY AGE CONTAINERS IMAGES dbc1 3/3 37m mysql mysql/mysql-server:8.0.30
Verifica 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\")"'
Para cada instancia de clústeres, busca los valores de estado y versión en el resultado. El resultado es similar a este:
... "status": "ONLINE", "version": "8.0.30" ...
Revierte el último lanzamiento de la implementación de la app
Cuando reviertes la implementación de una versión binaria actualizada, el proceso de lanzamiento se revierte y se implementa un conjunto nuevo de Pods con la versión de la 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 es similar a este:
statefulset.apps/dbc1 rolled back
Escala tu clúster de base de datos de forma horizontal
Para escalar MySQL InnoDB Cluster de forma horizontal, agrega nodos adicionales al grupo de nodos del clúster de GKE (solo se requiere si usas Standard), implementa instancias de MySQL adicionales y, luego, agrega cada instancia al MySQL existente Clúster de InnoDB.
Agrega nodos a tu clúster de Standard
Esta operación no es necesaria si usas un clúster de Autopilot.
A fin de agregar nodos a tu clúster estándar, sigue las instrucciones que se encuentran a continuación para Cloud Shell o la consola de Google Cloud. Para obtener pasos detallados, consulta Modifica el tamaño de un grupo 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
Console
Para agregar nodos a tu clúster de Standard, haz lo siguiente:
- Abre la página de
gkemulti-west1
Cluster en la consola de Google Cloud. - Selecciona Nodos y haz clic en grupo predeterminado.
- Desplázate hacia abajo hasta Grupos de instancias.
- Para cada grupo de instancias, cambia el tamaño del valor
Number of nodes
de 5 a 8 nodos.
Agrega los Pods de MySQL al clúster principal
Para implementar Pods de MySQL adicionales a fin de escalar tu clúster de forma horizontal, sigue estos pasos:
En Cloud Shell, actualiza la cantidad de réplicas en la implementación de MySQL de tres a cinco réplicas.
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
A fin de determinar si los Pods están listos, usa la marca
--watch
para ver la implementación. Si usas clústeres de Autopilot y ves erroresPod Unschedulable
, esto podría indicar que GKE aprovisiona nodos para alojar los Pods adicionales.Establece la configuración de la replicación de grupos para las instancias de MySQL nuevas que se agregarán 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 instancias nuevas 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 se configuró de forma correcta para el uso del MySQL InnoDB Cluster y si realizaron los cambios de configuración necesarios.
Agrega una de las instancias nuevas al clúster principal.
cluster = dba.getCluster() cluster.addInstance('icadmin@dbc1-3.mysql', {password: os.getenv("MYSQL_ROOT_PASSWORD"), recoveryMethod: 'clone'});
Agrega una segunda instancia nueva al clúster principal.
cluster.addInstance('icadmin@dbc1-4.mysql', {password: os.getenv("MYSQL_ROOT_PASSWORD"), recoveryMethod: 'clone'});
Obtén el estado de ClusterSet, que también incluye el estado del clúster.
clusterset = dba.getClusterSet() clusterset.status({extended: 1})
El resultado es similar a este:
"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
Limpia
Para evitar que se apliquen cargos a tu cuenta de Google Cloud por los recursos usados en este instructivo, borra el proyecto que contiene los recursos o conserva el proyecto y borra los recursos individuales.
Borra el proyecto
La manera más fácil de evitar la facturación es borrar el proyecto que creaste para el instructivo.
Delete a Google Cloud project:
gcloud projects delete PROJECT_ID
¿Qué sigue?
- Obtén más información sobre cómo la integración de Google Cloud Observability MySQL recopila métricas de rendimiento relacionadas con InnoDB.
- Obtén más información sobre la Copia de seguridad para GKE, un servicio para crear copias de seguridad y restablecer cargas de trabajo en GKE.
- Explora los volúmenes persistentes con más detalle.