Este documento é destinado a administradores de bancos de dados, arquitetos de nuvem e profissionais de operações interessados em implantar uma topologia de MySQL altamente disponível no Google Kubernetes Engine.
Siga este tutorial para saber como implantar um cluster do InnoDB do MySQL e um clusterSet do InnoDB do MySQL, além do MySQL Router middleware no seu cluster do GKE e como realizar upgrades.
Objetivos
Neste tutorial, você aprenderá a:- Crie e implante um serviço do Kubernetes com estado.
- Implante um cluster do MySQL InnoDB para alta disponibilidade.
- Implante o middleware do roteador para o roteamento de operações do banco de dados.
- Implante um ClusterSet MySQL MySQL para tolerância a desastres.
- Simular um failover de cluster do MySQL.
- Execute um upgrade de versão do MySQL.
As seções a seguir descrevem a arquitetura da solução que você vai criar neste tutorial.
Cluster do MySQL InnoDBB
No cluster regional do GKE, usando um StatefulSet, você implanta uma instância de banco de dados MySQL com a nomenclatura e a configuração necessárias para criar um cluster InnoDB do MySQL. Para fornecer tolerância a falhas e alta disponibilidade, implante três pods de instâncias de banco de dados. Isso garante que a maioria dos pods em diferentes zonas esteja disponível a qualquer momento para uma eleição primária bem-sucedida usando um protocolo de consenso, além de tornar o cluster do MySQL InnoDB tolerante a falhas de zona única.
Após a implantação, você designa um pod como a instância principal para atender às operações de leitura e gravação. Os outros dois pods são réplicas somente leitura secundárias. Se a instância principal apresentar uma falha de infraestrutura, será possível promover um desses dois pods de réplica para se tornar o principal.
Em um namespace separado, você implanta três pods do MySQL Router para fornecer roteamento de conexão e melhora a resiliência. Em vez de se conectar diretamente ao serviço de banco de dados, os aplicativos se conectam aos pods do MySQL Router. Cada pod do roteador está ciente do status e da finalidade de cada pod de cluster do MySQL InnoDB e encaminha as operações de aplicativos para o respectivo pod íntegro. O estado de roteamento é armazenado em cache nos pods do roteador e atualizado a partir dos metadados de cluster armazenados em cada node do cluster do MySQL InnoDB. Em caso de falha de uma instância, o roteador ajusta o roteamento de conexão a uma instância ativa.
ClusterSet MySQL do MySQL
É possível criar um conjunto de cluster do MySQL InnoDB de um cluster inicial do MySQL InnoDB. Isso permite aumentar a tolerância a desastres se o cluster principal não estiver mais disponível.
Se a instância principal do cluster do MySQL InnoDB não estiver mais disponível, será possível promover um cluster de réplica no ClusterSet para primário. Ao usar o middleware MySQL Router, o aplicativo não precisa rastrear a integridade da instância do banco de dados principal. O roteamento é ajustado para enviar conexões à nova principal após a eleição. No entanto, é sua responsabilidade garantir que os aplicativos que se conectam ao middleware do roteador MySQL sigam as práticas recomendadas para resiliência, de modo que novas conexões serão realizadas se um erro ocorrer durante o failover do cluster.
Custos
Neste documento, você usará os seguintes componentes faturáveis do Google Cloud:
Para gerar uma estimativa de custo baseada na projeção de uso deste tutorial, use a calculadora de preços.
Ao concluir as tarefas descritas neste documento, é possível evitar o faturamento contínuo excluindo os recursos criados. Saiba mais em Limpeza.
Antes de começar
Configurar o projeto
- 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.
Configurar papéis
-
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 seu ambiente
Neste tutorial, você usará o Cloud Shell para gerenciar recursos hospedados no
Google Cloud. O Cloud Shell vem pré-instalado com o Docker, bem como kubectl
e a CLI gcloud.
Siga estes passos para configurar o ambiente usando o Cloud Shell:
Defina variáveis de ambiente.
export PROJECT_ID=PROJECT_ID export CLUSTER_NAME=gkemulti-west export REGION=COMPUTE_REGION
Substitua os seguintes valores:
- PROJECT_ID: é o ID do projeto do Google Cloud.
- COMPUTE_REGION: a região do Compute Engine.
Neste tutorial, a região é
us-west1
. Normalmente, escolha uma região próxima a você.
Defina as variáveis de ambiente padrão.
gcloud config set project PROJECT_ID gcloud config set compute/region COMPUTE_REGION
Clone o repositório do código.
git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
Mude para o diretório de trabalho.
cd kubernetes-engine-samples/databases/gke-stateful-mysql/kubernetes
Criar um cluster do GKE
Nesta seção, você cria um cluster regional do GKE. Ao contrário de um cluster zonal, o plano de controle de um cluster regional é replicado em várias zonas. Portanto, uma falha temporária em uma única zona não torna o plano de controle indisponível.
Para criar um cluster do GKE, siga estas etapas:
Piloto automático
No Cloud Shell, crie um cluster do Autopilot do GKE na região
us-west1
.gcloud container clusters create-auto $CLUSTER_NAME \ --region=$REGION
Consiga as credenciais do cluster do GKE:.
gcloud container clusters get-credentials $CLUSTER_NAME \ --region=$REGION
Implantar um Serviço em três zonas.
kubectl apply -f prepare-for-ha.yaml
Por padrão, o Autopilot provisiona recursos em duas zonas. A implantação definida em
prepare-for-ha.yaml
garante que o Autopilot provisione nós em três zonas do seu cluster, definindoreplicas:3
,podAntiAffinity
comrequiredDuringSchedulingIgnoredDuringExecution
etopologyKey: "topology.kubernetes.io/zone"
Verifique o status da implantação.
kubectl get deployment prepare-three-zone-ha --watch
Quando você vir três pods no estado pronto, cancele este comando com
CTRL+C
. O resultado será assim: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
Execute esse script para validar se os pods foram implantados em três zonas.
bash ../scripts/inspect_pod_node.sh default
Cada linha da saída corresponde a um pod, e a segunda coluna indica a zona da nuvem. O resultado será assim:
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
Padrão
No Cloud Shell, crie um cluster do GKE Standard na região
us-west1
.gcloud container clusters create $CLUSTER_NAME \ --region=$REGION \ --machine-type="e2-standard-2" \ --disk-type="pd-standard" \ --num-nodes="5"
Consiga as credenciais do cluster do GKE:.
gcloud container clusters get-credentials $CLUSTER_NAME \ --region=$REGION
Implantar os StatefulSets do MySQL
Nesta seção, você implantará um StatefulSet do MySQL. Cada StatefulSet consiste em três réplicas do MySQL.
Para implantar o StatefulSet do MySQL, siga estas etapas:
Crie um namespace para o StatefulSet.
kubectl create namespace mysql1
Crie o secret do MySQL.
kubectl apply -n mysql1 -f secret.yaml
Neste tutorial, a senha é implantada a cada pod e usada por scripts e comandos de gerenciamento para o cluster do MySQL InnoDB e a implantação do ClusterSet.
Crie o StorageClass.
kubectl apply -n mysql1 -f storageclass.yaml
Essa classe de armazenamento usa o tipo de disco permanente
pd-balanced
que equilibra desempenho e custo. O campovolumeBindingMode
está definido comoWaitForFirstConsumer
, o que significa que o GKE atrasa o provisionamento de um PersistentVolume até que o pod seja criado. Essa configuração garante que o disco seja provisionado na mesma zona em que o pod está programado.Implante o StatefulSet dos pods de instância do MySQL.
kubectl apply -n mysql1 -f c1-mysql.yaml
Esse comando implanta o StatefulSet composto por três réplicas. Neste tutorial, o cluster principal do MySQL é implantado em três zonas em
us-west1
. O resultado será assim:service/mysql created statefulset.apps/dbc1 created
Neste tutorial, os limites de recursos e as solicitações são definidos como valores mínimos para economizar custos. Ao planejar uma carga de trabalho de produção, defina esses valores adequadamente para as necessidades da sua organização.
Verifique se o StatefulSet foi criado.
kubectl get statefulset -n mysql1 --watch
Pode levar cerca de 10 minutos para o SatefulSet ficar pronto.
Quando os três pods estiverem em estado pronto, saia do comando usando
Ctrl+C
. Se você vir errosPodUnscheduleable
devido à CPU ou memória insuficientes, aguarde alguns minutos para que o plano de controle seja redimensionado a fim de acomodar a carga de trabalho grande.O resultado será assim:
NAME READY AGE dbc1 1/3 39s dbc1 2/3 50s dbc1 3/3 73s
Para inspecionar o posicionamento dos pods nos nós do cluster do GKE, execute este script:
bash ../scripts/inspect_pod_node.sh mysql1 mysql
A saída mostra o nome do pod, o nome do nó do GKE e a zona em que o nó é provisionado e é semelhante ao seguinte:
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
As colunas na saída representam o nome do host, a zona da nuvem e o nome do pod, respectivamente.
A política
topologySpreadConstraints
na especificação do StatefulSet (c1-mysql.yaml
) direciona o programador para colocar os pods de maneira uniforme no domínio de falha (topology.kubernetes.io/zone
).A política
podAntiAffinity
aplica a restrição que exige que os pods não sejam colocados no mesmo nó de cluster do GKE (kubernetes.io/hostname
). Para os pods de instância do MySQL, essa política resulta na implantação uniforme dos pods nas três zonas da região do Google Cloud. Com esse posicionamento, você terá alta disponibilidade do cluster do MySQL InnoDB colocando cada instância de banco de dados em um domínio de falha separado.
Preparar o cluster principal do MySQL InnoDB
Para configurar um cluster do InnoDB do MySQL, siga estas etapas:
No terminal do Cloud Shell, defina as configurações de replicação de grupo para que as instâncias do MySQL sejam adicionadas ao seu cluster.
bash ../scripts/c1-clustersetup.sh
O script se conecta remotamente a cada uma das três instâncias do MySQL para definir e manter as seguintes variáveis de ambiente:
group_replication_ip_allowlist
: permite que a instância do cluster se conecte a qualquer instância do grupo.binlog_transaction_dependency_tracking='WRITESET'
: permite transações paralelas que não entrem em conflito.
Nas versões do MySQL anteriores à 8.0.22, use
group_replication_ip_whitelist
em vez degroup_replication_ip_allowlist
.Abra um segundo terminal para que não seja necessário criar um shell para cada pod.
Conecte-se ao MySQL Shell no 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"'
Verifique a lista de permissões de replicação do grupo do MySQL para se conectar a outras instâncias.
\sql SELECT @@group_replication_ip_allowlist;
O resultado será assim:
+----------------------------------+ | @@group_replication_ip_allowlist | +----------------------------------+ | mysql.mysql1.svc.cluster.local | +----------------------------------+
Verifique se o
server-id
é exclusivo em cada uma das instâncias.\sql SELECT @@server_id;
O resultado será assim:
+-------------+ | @@server_id | +-------------+ | 21 | +-------------+
Configurar cada instância para uso do cluster do InnoDB do MySQL e criar uma conta de administrador em cada instância.
\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 as instâncias precisam ter o mesmo nome de usuário e senha para que o cluster do InnoDB do MySQL funcione corretamente. Cada comando produz um resultado semelhante a este:
... 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.
Verifique se a instância está pronta para ser usada em um cluster do MySQL InnoDB.
dba.checkInstanceConfiguration()
O resultado será assim:
... The instance 'dbc1-0.mysql.mysql1.svc.cluster.local:3306' is valid to be used in an InnoDB cluster. { "status": "ok" }
Também é possível se conectar a cada instância do MySQL e repetir esse comando. Por exemplo, execute este comando para verificar o status da instância
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()"'
Criar o cluster principal do MySQL InnoDB
Em seguida, crie o cluster do MySQL InnoDB usando o comando createCluster
do MySQL Admin. Comece com a instância dbc1-0
, que será
a instância principal do cluster e, em seguida, adicione duas réplicas adicionais
ao cluster.
Para inicializar o cluster do MySQL InnoDB, siga estas etapas:
Criar o cluster do MySQL InnoDB
var cluster=dba.createCluster('mycluster');
A execução do comando
createCluster
aciona estas operações:- Implantar o esquema de metadados.
- Verifique se a configuração está correta para replicação de grupos.
- Registre-o como a instância de origem do novo cluster.
- Crie as contas internas necessárias, como a conta de usuário de replicação.
- Inicie a replicação de grupo.
Esse comando inicializa um cluster do MySQL InnoDB com o host
dbc1-0
como principal. A referência do cluster é armazenada na variável de cluster.A resposta será semelhante a:
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.
Adicione a segunda instância ao cluster.
cluster.addInstance('icadmin@dbc1-1.mysql', {password: os.getenv("MYSQL_ROOT_PASSWORD"), recoveryMethod: 'clone'});
Adicionar a instância restante ao cluster.
cluster.addInstance('icadmin@dbc1-2.mysql', {password: os.getenv("MYSQL_ROOT_PASSWORD"), recoveryMethod: 'clone'});
O resultado será assim:
... The instance 'dbc1-2.mysql:3306' was successfully added to the cluster.
Verifique o status do cluster.
cluster.status()
Esse comando mostra o status do cluster. A topologia consiste em três hosts, uma instância primária e duas secundárias. Se quiser, chame
cluster.status({extended:1})
.O resultado será assim:
{ "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" }
Como alternativa, é possível chamar
cluster.status({extended:1})
para ver mais detalhes do status.
Criar um banco de dados de exemplo
Para criar um banco de dados de amostra, siga estas etapas:
Crie um banco de dados e carregar dados nele.
\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) );
Insira dados de amostra no banco de dados. Para inserir dados, é necessário estar conectado à instância principal do cluster.
INSERT INTO loan (firstname, lastname, status) VALUES ( 'Fred','Flintstone','pending'); INSERT INTO loan (firstname, lastname, status) VALUES ( 'Betty','Rubble','approved');
Verifique se a tabela contém as três linhas inseridas na etapa anterior.
SELECT * FROM loan;
O resultado será assim:
+---------+-----------+------------+----------+ | loan_id | firstname | lastname | status | +---------+-----------+------------+----------+ | 1 | Fred | Flintstone | pending | | 2 | Betty | Rubble | approved | +---------+-----------+------------+----------+ 2 rows in set (0.0010 sec)
Criar um ClusterSet do MySQL InnoDB
É possível criar um ClusterSet MySQL InnoDB para gerenciar a replicação do cluster principal para os clusters de réplica, usando um canal de replicação dedicado do ClusterSet.
Um MySQLInnoDB ClusterSet fornece tolerância a desastres para implantações de clusters do MySQL InnoDB vinculando um cluster MySQL primário InnoDB a uma ou mais réplicas próprias em locais alternativos, como várias zonas e várias regiões.
Se você tiver fechado o MySQL Shell, crie um novo shell executando este comando em um novo terminal do 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 criar um ClusterInnoDB MySQLSet, siga estas etapas:
No terminal do MySQL Shell, consiga um objeto de cluster.
\js cluster=dba.getCluster()
O resultado será assim:
<Cluster:mycluster>
Inicialize um cluster do MySQL InnoDB com o cluster do InnoDB do MySQL armazenado no objeto do cluster como principal.
clusterset=cluster.createClusterSet('clusterset')
O resultado será assim:
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>
Verifique o status do ClusterSet do MySQL InnoDB.
clusterset.status()
O resultado será assim:
{ "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." }
Opcionalmente, é possível chamar
clusterset.status({extended:1})
para receber mais detalhes sobre o status, incluindo informações sobre o cluster.Saia do MySQL Shell.
\q
Implantar um roteador MySQL
É possível implantar um roteador MySQL para direcionar o tráfego de aplicativos do cliente para os clusters adequados. O roteamento é baseado na porta de conexão do aplicativo que emite uma operação de banco de dados:
- As gravações são roteadas para a instância do cluster principal no ClusterSet principal.
- As leituras podem ser roteadas para qualquer instância no cluster principal.
Quando você inicia um roteador MySQL, ele é inicializado na implantação do ClusterSet do MySQL InnoDB. As instâncias do roteador do MySQL conectadas com o MySQLInnoDB ClusterSet estão cientes das mudanças controladas ou de failovers de emergência e do tráfego direto para o novo cluster principal.
Para implantar um roteador MySQL, siga estas etapas:
No terminal do Cloud Shell, implante o roteador do MySQL.
kubectl apply -n mysql1 -f c1-router.yaml
O resultado será assim:
configmap/mysql-router-config created service/mysql-router created deployment.apps/mysql-router created
Verifique se a implantação do MySQL Roteador está pronta.
kubectl -n mysql1 get deployment mysql-router --watch
Quando os três pods estiverem prontos, a saída vai ser semelhante a esta:
NAME READY UP-TO-DATE AVAILABLE AGE mysql-router 3/3 3 0 3m36s
Se você vir um erro
PodUnschedulable
no console, aguarde um ou dois minutos enquanto o GKE provisiona mais nodes. Atualize e você verá3/3 OK
.Inicie o MySQL Shell em qualquer membro do cluster atual.
kubectl -n mysql1 exec -it dbc1-0 -- \ /bin/bash -c 'mysqlsh --uri="root:$MYSQL_ROOT_PASSWORD@dbc1-0.mysql"'
Esse comando se conecta ao pod
dbc1-0
e inicia um shell conectado à instância do MySQL dedbc1-0
.Verifique a configuração do roteador.
clusterset=dba.getClusterSet() clusterset.listRouters()
O resultado será assim:
{ "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::": { ... } } }
Saia do MySQL Shell.
\q
Execute esse script para inspecionar o posicionamento dos pods do MySQL Router.
bash ../scripts/inspect_pod_node.sh mysql1 | sort
O script mostra o nó e a colocação da zona do Cloud de todos os pods no namespace
mysql1
, em que a saída é semelhante a esta: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
É possível observar que os pods do MySQL Router estão distribuídos igualmente entre as zonas. Ou seja, não é colocado no mesmo node que um pod do MySQL ou no mesmo nó de outro pod do roteador do MySQL.
Gerenciar upgrades de clusters do GKE e do MySQL InnoDB
As atualizações para MySQL e Kubernetes são lançadas regularmente. Siga as práticas recomendadas operacionais para atualizar o ambiente de software regularmente. Por padrão, o GKE gerencia os upgrades de clusters e pools de nodes para você. O Kubernetes e o GKE também oferecem recursos adicionais para facilitar os upgrades de software do MySQL.
Plano para upgrades do GKE
É possível tomar medidas proativas e definir configurações para reduzir os riscos e facilitar um upgrade mais tranquilo do cluster quando estiver executando serviços com estado, incluindo:
Clusters padrão: siga as práticas recomendadas do GKE para fazer upgrade de clusters. Escolha uma estratégia de upgrade apropriada para garantir que os upgrades aconteçam durante o período da janela de manutenção:
- Escolha upgrades súbitos se a otimização de custos for importante e se as cargas de trabalho estiverem tolerar um encerramento otimizado em menos de 60 minutos.
- Escolha upgrades azul-verde se as cargas de trabalho forem menos tolerantes a interrupções e um aumento temporário do custo devido ao maior uso de recursos for aceitável.
Para saber mais, consulte Fazer upgrade de um cluster que executa uma carga de trabalho com estado. Os clusters do Autopilot são atualizados automaticamente, com base no canal de lançamento que você selecionou.
Use as janelas de manutenção para garantir que os upgrades aconteçam quando você quiser. Antes da janela de manutenção, verifique se os backups do banco de dados foram concluídos.
Antes de permitir o tráfego para os nodes do MySQL atualizados, use as Sondagens de prontidão e atividades para verificar se estão prontas para tráfego.
Crie sondagens que avaliem se a replicação está sincronizada antes de aceitar o tráfego. Isso pode ser feito com scripts personalizados, dependendo da complexidade e da escala do seu banco de dados.
Definir uma política de orçamento de interrupção de pod (PDB)
Quando um cluster do MySQL InnoDB está em execução no GKE, é preciso ter um número suficiente de instâncias em execução a qualquer momento para atender ao requisito de quórum.
Neste tutorial, considerando um cluster MySQL de três instâncias, duas instâncias precisam
estar disponíveis para formar um quórum. Com uma política PodDisruptionBudget
, é possível limitar o número de pods que podem ser encerrados a qualquer momento. Isso é
útil para operações de estado estável dos serviços com estado e para
upgrades de cluster.
Para garantir que um número limitado de pods seja interrompido simultaneamente, defina o PDB para sua carga de trabalho como maxUnavailable: 1
. Isso garante que, em qualquer ponto da
operação do serviço, apenas um pod não esteja em execução.
O manifesto de política PodDisruptionBudget
a seguir define o máximo de pods indisponíveis para um do seu aplicativo MySQL.
Para aplicar a política de PDB ao cluster, siga estas etapas:
Aplique a política de PDB usando
kubectl
.kubectl apply -n mysql1 -f mysql-pdb-maxunavailable.yaml
Veja o status do PDB.
kubectl get poddisruptionbudgets -n mysql1 mysql-pdb -o yaml
Na seção
status
da saída, veja as contagens de podscurrentHealthy
edesiredHealthy
. O resultado será assim:status: ... currentHealthy: 3 desiredHealthy: 2 disruptionsAllowed: 1 expectedPods: 3 ...
Planejar upgrades binários do MySQL
O Kubernetes e o GKE oferecem recursos para facilitar os upgrades para o binário do MySQL. No entanto, é necessário realizar algumas operações para se preparar para os upgrades.
Lembre-se das seguintes considerações antes de iniciar o processo de upgrade:
- Os upgrades devem ser realizados primeiro em um ambiente de teste. Para sistemas de produção, é preciso realizar mais testes em um ambiente de pré-produção.
- Em algumas versões binárias, não é possível fazer downgrade da versão depois da atualização. Dedique um tempo para entender as implicações de um upgrade.
- As origens de replicação podem ser replicadas para uma versão mais recente. No entanto, geralmente não é possível copiar de uma versão mais recente para uma mais antiga.
- Faça um backup completo do banco de dados antes de implantar a versão atualizada.
- Considere a natureza efêmera dos pods do Kubernetes. Todo estado de configuração armazenado pelo pod que não está no volume permanente será perdido quando o pod for reimplantado.
- Para upgrades binários do MySQL, use o mesmo PDB, estratégia de atualização de pool de nós e sondagens, conforme descrito anteriormente.
Em um ambiente de produção, siga estas práticas recomendadas:
- Crie uma imagem de contêiner com a nova versão do MySQL.
- Mantenha as instruções de criação de imagem em um repositório de controle de origem.
- Use um pipeline automatizado de build e teste de imagens, como o Cloud Build, e armazene o binário da imagem em um registro de imagens, como o Artifact Registry.
Para manter este tutorial simples, você não criará nem manterá uma imagem de contêiner. Em vez disso, use as imagens públicas do MySQL.
Implante o binário MySQL atualizado
Para realizar o upgrade binário do MySQL, você emite um comando declarativo que modifica a versão da imagem do recurso StatefulSet. O GKE executa as etapas necessárias para interromper o pod atual, implantar um novo pod com o binário atualizado e anexar o disco permanente ao novo pod.
Verifique se o PDB foi criado.
kubectl get poddisruptionbudgets -n mysql1
Veja a lista de conjuntos com estado.
kubectl get statefulsets -n mysql1
Veja a lista de pods em execução usando o rótulo
app
.kubectl get pods --selector=app=mysql -n mysql1
Atualizar a imagem do MySQL no conjunto com estado.
kubectl -n mysql1 \ set image statefulset/dbc1 \ mysql=mysql/mysql-server:8.0.30
O resultado será assim:
statefulset.apps/mysql image updated
Verifique o status dos pods de encerramento e dos novos pods.
kubectl get pods --selector=app=mysql -n mysql1
Validar o upgrade binário do MySQL
Durante o upgrade, é possível verificar o status do lançamento, os novos pods e o serviço atual.
Valide o upgrade executando o comando
rollout status
.kubectl rollout status statefulset/dbc1 -n mysql1
O resultado será assim:
partitioned roll out complete: 3 new pods have been updated...
Inspecione o conjunto com estado para confirmar a versão da imagem.
kubectl get statefulsets -o wide -n mysql1
O resultado será assim:
NAME READY AGE CONTAINERS IMAGES dbc1 3/3 37m mysql mysql/mysql-server:8.0.30
Verifique o status do 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\")"'
Para cada instância do cluster, procure os valores de status e versão na saída. O resultado será assim:
... "status": "ONLINE", "version": "8.0.30" ...
Reverter o último lançamento de implantação do app
Quando você reverte a implantação de uma versão binária atualizada, o processo de lançamento é revertido e um novo conjunto de pods é implantado com a versão de imagem anterior.
Para reverter a implantação para a versão de trabalho anterior, use o comando rollout undo
:
kubectl rollout undo statefulset/dbc1 -n mysql1
O resultado será assim:
statefulset.apps/dbc1 rolled back
Escalonar o cluster do banco de dados horizontalmente
Para escalonar o cluster do InnoDB do MySQL horizontalmente, você adiciona outros nós ao pool de nós do cluster do GKE (obrigatório apenas se você estiver usando o Standard), implanta outras instâncias do MySQL e, em seguida, adiciona cada instância ao MySQL existente Cluster do InnoDB.
Adicionar nodes ao cluster padrão
Essa operação não é necessária se você estiver usando um cluster do Autopilot.
Para adicionar nós ao cluster padrão, siga as instruções abaixo para o Cloud Shell ou o Console do Google Cloud. Para ver as etapas detalhadas, consulte Redimensionar um pool de nodes.
gcloud
No Cloud Shell, redimensione o pool de nodes padrão para oito instâncias em cada grupo gerenciado.
gcloud container clusters resize ${CLUSTER_NAME} \
--node-pool default-pool \
--num-nodes=8
Console
Para adicionar nós ao cluster padrão:
- Abra a página
gkemulti-west1
cluster no Console do Google Cloud. - Selecione Nodes e clique em pool padrão.
- Role para baixo até Grupos de instâncias.
- Para cada grupo de instâncias, redimensione o valor
Number of nodes
de 5 para 8 nodes.
Adicionar pods do MySQL ao cluster principal
Para implantar outros pods do MySQL de modo a escalonar o cluster horizontalmente, siga estas etapas:
No Cloud Shell, atualize o número de réplicas na implantação do MySQL de três réplicas para cinco réplicas.
kubectl scale -n mysql1 --replicas=5 -f c1-mysql.yaml
Verifique o andamento da implantação.
kubectl -n mysql1 get pods --selector=app=mysql -o wide
Para determinar se os pods estão prontos, use a sinalização
--watch
para observar a implantação. Se você estiver usando clusters do Autopilot e vir errosPod Unschedulable
, isso poderá indicar que o GKE está provisionando nós para acomodar os pods adicionais.Defina as configurações de replicação de grupo para as novas instâncias do MySQL a serem adicionadas ao cluster.
bash ../scripts/c1-clustersetup.sh 3 4
O script envia os comandos para as instâncias em execução nos pods com ordinais 3 a 4.
Abra o MySQL Shell.
kubectl -n mysql1 \ exec -it dbc1-0 -- \ /bin/bash \ -c 'mysqlsh \ --uri="root:$MYSQL_ROOT_PASSWORD@dbc1-0.mysql"'
Configurar as duas novas instâncias do 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")});
Os comandos verificam se a instância está configurada corretamente para o uso do cluster do MySQL InnoDB e realizam as alterações de configuração necessárias.
Adicione uma das novas instâncias ao cluster principal.
cluster = dba.getCluster() cluster.addInstance('icadmin@dbc1-3.mysql', {password: os.getenv("MYSQL_ROOT_PASSWORD"), recoveryMethod: 'clone'});
Adicione uma segunda instância nova ao cluster principal.
cluster.addInstance('icadmin@dbc1-4.mysql', {password: os.getenv("MYSQL_ROOT_PASSWORD"), recoveryMethod: 'clone'});
Acessar o status do ClusterSet, que também inclui o status do cluster.
clusterset = dba.getClusterSet() clusterset.status({extended: 1})
O resultado será assim:
"domainName": "clusterset", "globalPrimaryInstance": "dbc1-0.mysql:3306", "metadataServer": "dbc1-0.mysql:3306", "primaryCluster": "mycluster", "status": "HEALTHY", "statusText": "All Clusters available."
Saia do MySQL Shell.
\q
Limpar
Para evitar cobranças na sua conta do Google Cloud pelos recursos usados no tutorial, exclua o projeto que os contém ou mantenha o projeto e exclua os recursos individuais.
Excluir o projeto
A maneira mais fácil de evitar o faturamento é excluir o projeto criado para o tutorial.
Delete a Google Cloud project:
gcloud projects delete PROJECT_ID
A seguir
- Saiba como a integração do MySQL de observabilidade do Google Cloud coleta métricas de desempenho relacionadas ao InnoDB.
- Saiba mais sobre o backup para o GKE, um serviço para fazer backup e restaurar cargas de trabalho no GKE.
- Conheça melhor o recurso Volumes persistentes.