Este documento destina-se a administradores de bases de dados, arquitetos da nuvem e profissionais de operações interessados na implementação de uma topologia do MySQL de elevada disponibilidade no Google Kubernetes Engine.
Siga este tutorial para saber como implementar um MySQL InnoDB Cluster e um MySQL InnoDB ClusterSet, além do middleware MySQL Router no seu cluster do GKE e como fazer atualizações.
Crie um cluster do GKE
Nesta secção, cria um cluster do GKE regional. Ao contrário de um cluster zonal, o painel de controlo de um cluster regional é replicado em várias zonas, pelo que uma indisponibilidade numa única zona não torna o painel de controlo indisponível.
Para criar um cluster do GKE, siga estes passos:
Piloto automático
No Cloud Shell, crie um cluster do GKE Autopilot na região
us-west1
.gcloud container clusters create-auto $CLUSTER_NAME \ --location=$CONTROL_PLANE_LOCATION
Obtenha as credenciais do cluster do GKE.
gcloud container clusters get-credentials $CLUSTER_NAME \ --location=$CONTROL_PLANE_LOCATION
Implemente um serviço em três zonas. Este tutorial usa uma implementação do Kubernetes. Uma implementação é um objeto da API Kubernetes que lhe permite executar várias réplicas de pods distribuídas entre os nós num cluster.
kubectl apply -f prepare-for-ha.yaml
Por predefinição, o Autopilot aprovisiona recursos em duas zonas. A implementação definida em
prepare-for-ha.yaml
garante que o Autopilot aprovisiona nós em três zonas no seu cluster, definindoreplicas:3
,podAntiAffinity
comrequiredDuringSchedulingIgnoredDuringExecution
etopologyKey: "topology.kubernetes.io/zone"
.Verifique o estado da implementação.
kubectl get deployment prepare-three-zone-ha --watch
Quando vir três pods no estado pronto, cancele este comando com
CTRL+C
. O resultado é semelhante ao seguinte: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 este script para validar se os seus pods foram implementados em três zonas.
bash ../scripts/inspect_pod_node.sh default
Cada linha do resultado corresponde a um agrupamento e a segunda coluna indica a zona. O resultado é semelhante ao seguinte:
gk3-gkemulti-west1-default-pool-eb354e2d-z6mv us-west1-b prepare-three-zone-ha-7885d77d9c-8f7qb gk3-gkemulti-west1-nap-25b73chq-739a9d40-4csr us-west1-c prepare-three-zone-ha-7885d77d9c-98fpn gk3-gkemulti-west1-default-pool-160c3578-bmm2 us-west1-a prepare-three-zone-ha-7885d77d9c-phmhj
Standard
No Cloud Shell, crie um cluster padrão do GKE na região
us-west1
.gcloud container clusters create $CLUSTER_NAME \ --location=$CONTROL_PLANE_LOCATION \ --machine-type="e2-standard-2" \ --disk-type="pd-standard" \ --num-nodes="5"
Obtenha as credenciais do cluster do GKE.
gcloud container clusters get-credentials $CLUSTER_NAME \ --location=$CONTROL_PLANE_LOCATION
Implemente StatefulSets do MySQL
Nesta secção, implementa um StatefulSet do MySQL. Um StatefulSet é um controlador do Kubernetes que mantém uma identidade única persistente para cada um dos respetivos pods.
Cada StatefulSet consiste em três réplicas do MySQL.
Para implementar o StatefulSet do MySQL, siga estes passos:
Crie um espaço de nomes para o StatefulSet.
kubectl create namespace mysql1
Crie o segredo do MySQL.
kubectl apply -n mysql1 -f secret.yaml
A palavra-passe é implementada com cada pod e é usada por comandos e scripts de gestão para a implementação do MySQL InnoDB Cluster e do ClusterSet neste tutorial.
Crie a StorageClass.
kubectl apply -n mysql1 -f storageclass.yaml
Esta classe de armazenamento usa o tipo de disco persistente
pd-balanced
que equilibra o desempenho e o custo. O campovolumeBindingMode
está definido comoWaitForFirstConsumer
, o que significa que o GKE atrasa o aprovisionamento de um PersistentVolume até o pod ser criado. Esta definição garante que o disco é aprovisionado na mesma zona onde o pod está agendado.Implemente o StatefulSet de pods de instâncias do MySQL.
kubectl apply -n mysql1 -f c1-mysql.yaml
Este comando implementa o StatefulSet composto por três réplicas. Neste tutorial, o cluster MySQL principal é implementado em três zonas no
us-west1
. O resultado é semelhante ao seguinte:service/mysql created statefulset.apps/dbc1 created
Neste tutorial, os limites e os pedidos de recursos estão definidos para valores mínimos para poupar custos. Ao planear uma carga de trabalho de produção, certifique-se de que define estes valores adequadamente para as necessidades da sua organização.
Verifique se o StatefulSet foi criado com êxito.
kubectl get statefulset -n mysql1 --watch
O StatefulSet pode demorar cerca de 10 minutos a ficar pronto.
Quando todos os 3 pods estiverem no estado pronto, saia do comando com
Ctrl+C
. Se virPodUnscheduleable
erros devido a CPU ou memória insuficientes, aguarde alguns minutos para que o plano de controlo seja redimensionado de forma a acomodar a grande carga de trabalho.O resultado é semelhante ao seguinte:
NAME READY AGE dbc1 1/3 39s dbc1 2/3 50s dbc1 3/3 73s
Para inspecionar o posicionamento dos seus pods nos nós do cluster do GKE, execute este script:
bash ../scripts/inspect_pod_node.sh mysql1 mysql
O resultado mostra o nome do pod, o nome do nó do GKE e a zona onde o nó é aprovisionado, 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 anfitrião, a zona na nuvem e o nome do pod, respetivamente.
A política
topologySpreadConstraints
na especificação StatefulSet (c1-mysql.yaml
) direciona o programador para colocar os pods uniformemente no domínio de falhas (topology.kubernetes.io/zone
).A política
podAntiAffinity
aplica a restrição de que os pods não podem ser colocados no mesmo nó do cluster do GKE (kubernetes.io/hostname
). Para os pods da instância do MySQL, esta política resulta na implementação dos pods de forma uniforme nas três zonas na região Google Cloud . Este posicionamento permite a alta disponibilidade do cluster MySQL InnoDB ao colocar cada instância da base de dados num domínio de falha separado.
Prepare o cluster InnoDB do MySQL principal
Para configurar um cluster InnoDB do MySQL, siga estes passos:
No terminal do Cloud Shell, defina as configurações de replicação de grupo para as instâncias do MySQL a adicionar ao cluster.
bash ../scripts/c1-clustersetup.sh
O script vai estabelecer ligação 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 no cluster se ligue a qualquer instância no grupo.binlog_transaction_dependency_tracking='WRITESET'
: permite transações paralelizadas que não entram 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 não ter de criar uma shell para cada Pod.
Estabeleça ligação 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"'
Valide a lista de autorizações da replicação de grupo do MySQL para estabelecer ligação a outras instâncias.
\sql SELECT @@group_replication_ip_allowlist;
O resultado é semelhante ao seguinte:
+----------------------------------+ | @@group_replication_ip_allowlist | +----------------------------------+ | mysql.mysql1.svc.cluster.local | +----------------------------------+
Verifique se o
server-id
é único em cada uma das instâncias.\sql SELECT @@server_id;
O resultado é semelhante ao seguinte:
+-------------+ | @@server_id | +-------------+ | 21 | +-------------+
Configure cada instância para utilização do cluster MySQL InnoDB e crie 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 têm de ter o mesmo nome de utilizador e palavra-passe para que o cluster MySQL InnoDB funcione corretamente. Cada comando produz um resultado semelhante ao seguinte:
... 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 num cluster InnoDB do MySQL.
dba.checkInstanceConfiguration()
O resultado é semelhante ao seguinte:
... The instance 'dbc1-0.mysql.mysql1.svc.cluster.local:3306' is valid to be used in an InnoDB cluster. { "status": "ok" }
Opcionalmente, pode estabelecer ligação a cada instância do MySQL e repetir este comando. Por exemplo, execute este comando para verificar o estado na 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()"'
Crie o cluster InnoDB do MySQL principal
Em seguida, crie o cluster InnoDB do MySQL com o comando MySQL Admin
createCluster
. Comece pela instância dbc1-0
, que vai ser a instância principal do cluster. Em seguida, adicione duas réplicas adicionais ao cluster.
Para inicializar o MySQL InnoDB Cluster, siga estes passos:
Crie o cluster InnoDB do MySQL.
var cluster=dba.createCluster('mycluster');
A execução do comando
createCluster
aciona estas operações:- Implemente o esquema de metadados.
- Verifique se a configuração está correta para a replicação de grupos.
- Registe-o como a instância inicial do novo cluster.
- Crie as contas internas necessárias, como a conta de utilizador de replicação.
- Inicie a replicação de grupo.
Este comando inicializa um cluster MySQL InnoDB com o anfitrião
dbc1-0
como o principal. A referência do cluster é armazenada na variável do cluster.O resultado tem um aspeto semelhante ao seguinte:
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'});
Adicione a instância restante ao cluster.
cluster.addInstance('icadmin@dbc1-2.mysql', {password: os.getenv("MYSQL_ROOT_PASSWORD"), recoveryMethod: 'clone'});
O resultado é semelhante ao seguinte:
... The instance 'dbc1-2.mysql:3306' was successfully added to the cluster.
Valide o estado do cluster.
cluster.status()
Este comando mostra o estado do cluster. A topologia consiste em três anfitriões, uma instância principal e duas secundárias. Opcionalmente, pode ligar para
cluster.status({extended:1})
.O resultado é semelhante ao seguinte:
{ "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" }
Opcionalmente, pode ligar para
cluster.status({extended:1})
para obter detalhes adicionais do estado.
Crie uma base de dados de amostra
Para criar uma base de dados de exemplo, siga estes passos:
Crie uma base de dados e carregue dados na base de dados.
\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) );
Inserir dados de amostra na base de dados. Para inserir dados, tem de ter ligação à 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 no passo anterior.
SELECT * FROM loan;
O resultado é semelhante ao seguinte:
+---------+-----------+------------+----------+ | loan_id | firstname | lastname | status | +---------+-----------+------------+----------+ | 1 | Fred | Flintstone | pending | | 2 | Betty | Rubble | approved | +---------+-----------+------------+----------+ 2 rows in set (0.0010 sec)
Crie um ClusterSet do MySQL InnoDB
Pode criar um ClusterSet do MySQL InnoDB para gerir a replicação do cluster principal para clusters de réplica, usando um canal de replicação do ClusterSet dedicado.
Um MySQL InnoDB ClusterSet oferece tolerância a desastres para implementações do MySQL InnoDB Cluster, associando um MySQL InnoDB Cluster principal a uma ou mais réplicas do mesmo em localizações alternativas, como várias zonas e várias regiões.
Se fechou o MySQL Shell, crie uma nova shell executando este comando num 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 MySQL InnoDB ClusterSet, siga estes passos:
No terminal do MySQL Shell, obtenha um objeto de cluster.
\js cluster=dba.getCluster()
O resultado é semelhante ao seguinte:
<Cluster:mycluster>
Inicialize um MySQL InnoDB ClusterSet com o MySQL InnoDB Cluster existente armazenado no objeto de cluster como o principal.
clusterset=cluster.createClusterSet('clusterset')
O resultado é semelhante ao seguinte:
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 estado do seu MySQL InnoDB ClusterSet.
clusterset.status()
O resultado é semelhante ao seguinte:
{ "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, pode chamar
clusterset.status({extended:1})
para obter detalhes adicionais do estado, incluindo informações sobre o cluster.Saia do MySQL Shell.
\q
Implemente um MySQL Router
Pode implementar um MySQL Router para direcionar o tráfego da aplicação cliente para os clusters adequados. O encaminhamento baseia-se na porta de ligação da aplicação que emite uma operação de base de dados:
- As gravações são encaminhadas para a instância do cluster principal no ClusterSet principal.
- As leituras podem ser encaminhadas para qualquer instância no cluster principal.
Quando inicia um MySQL Router, este é inicializado em relação à implementação do MySQL InnoDB ClusterSet. As instâncias do MySQL Router associadas ao MySQL InnoDB ClusterSet têm conhecimento de quaisquer comutações controladas ou failovers de emergência e direcionam o tráfego para o novo cluster principal.
Para implementar um MySQL Router, siga estes passos:
No terminal do Cloud Shell, implemente o MySQL Router.
kubectl apply -n mysql1 -f c1-router.yaml
O resultado é semelhante ao seguinte:
configmap/mysql-router-config created service/mysql-router created deployment.apps/mysql-router created
Verifique a prontidão da implementação do MySQL Router.
kubectl -n mysql1 get deployment mysql-router --watch
Quando os três pods estiverem prontos, o resultado é semelhante ao seguinte:
NAME READY UP-TO-DATE AVAILABLE AGE mysql-router 3/3 3 0 3m36s
Se vir um erro
PodUnschedulable
na consola, aguarde um ou dois minutos enquanto o GKE aprovisiona mais nós. Atualize a página e deverá ver3/3 OK
.Inicie o MySQL Shell em qualquer membro do cluster existente.
kubectl -n mysql1 exec -it dbc1-0 -- \ /bin/bash -c 'mysqlsh --uri="root:$MYSQL_ROOT_PASSWORD@dbc1-0.mysql"'
Este comando liga-se ao pod
dbc1-0
e, em seguida, inicia um shell ligado à instância do MySQLdbc1-0
.Valide a configuração do router.
clusterset=dba.getClusterSet() clusterset.listRouters()
O resultado é semelhante ao seguinte:
{ "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 este script para inspecionar o posicionamento dos pods do MySQL Router.
bash ../scripts/inspect_pod_node.sh mysql1 | sort
O script mostra o posicionamento do nó e da zona na nuvem de todos os pods no espaço de nomes
mysql1
, em que o resultado é semelhante ao seguinte: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
Pode observar que os pods do router MySQL estão distribuídos igualmente pelas zonas, ou seja, não estão colocados no mesmo nó que um pod MySQL nem no mesmo nó que outro pod do router MySQL.
Faça a gestão das atualizações do GKE e do MySQL InnoDB Cluster
As atualizações do MySQL e do Kubernetes são lançadas regularmente. Siga as práticas recomendadas operacionais para atualizar regularmente o seu ambiente de software. Por predefinição, o GKE gere as atualizações de clusters e node pools por si. O Kubernetes e o GKE também oferecem funcionalidades adicionais para facilitar as atualizações de software do MySQL.
Planeie as atualizações do GKE
Pode tomar medidas proativas e definir configurações para mitigar o risco e facilitar uma atualização mais suave do cluster quando estiver a executar serviços com estado, incluindo:
Clusters padrão: siga as práticas recomendadas do GKE para atualizar clusters. Escolha uma estratégia de atualização adequada para garantir que as atualizações ocorrem durante o período de manutenção:
- Escolha atualizações de picos se a otimização de custos for importante e se as suas cargas de trabalho puderem tolerar um encerramento normal em menos de 60 minutos.
- Escolha atualizações azul-verde se as suas cargas de trabalho forem menos tolerantes a interrupções e um aumento temporário do custo devido a uma maior utilização de recursos for aceitável.
Para saber mais, consulte o artigo Atualize um cluster que execute uma carga de trabalho com estado. Os clusters do Autopilot são atualizados automaticamente com base no canal de lançamento que selecionou.
Use janelas de manutenção para garantir que as atualizações ocorrem quando pretende. Antes da janela de manutenção, certifique-se de que as cópias de segurança da base de dados são bem-sucedidas.
Antes de permitir o tráfego para os nós do MySQL atualizados, use Readiness Probes e Liveness Probes para garantir que estão prontos para o tráfego.
Crie sondagens que avaliem se a replicação está sincronizada antes de aceitar tráfego. Isto pode ser feito através de scripts personalizados, consoante a complexidade e a escala da sua base de dados.
Defina uma política de orçamento de interrupção de pods (PDB)
Quando um cluster InnoDB do MySQL está a ser executado no GKE, tem de haver um número suficiente de instâncias em execução em qualquer altura para cumprir o requisito de quórum.
Neste tutorial, dado um cluster do MySQL de três instâncias, duas instâncias têm de estar disponíveis para formar um quórum. Uma política de PodDisruptionBudget
permite-lhe
limitar o número de agrupamentos que podem ser terminados em qualquer altura. Isto é útil para as operações de estado estável dos seus serviços com estado e para as atualizações de clusters.
Para garantir que um número limitado de pods são interrompidos em simultâneo, defina o PDB para a sua carga de trabalho como maxUnavailable: 1
. Isto garante que, em qualquer ponto da operação do serviço, não há mais do que um pod em execução.
O manifesto da política PodDisruptionBudget
seguinte define o número máximo de pods indisponíveis como um para a sua aplicação MySQL.
Para aplicar a política de PDB ao seu cluster, siga estes passos:
Aplique a política de PDB através do
kubectl
.kubectl apply -n mysql1 -f mysql-pdb-maxunavailable.yaml
Veja o estado da PDB.
kubectl get poddisruptionbudgets -n mysql1 mysql-pdb -o yaml
Na secção
status
do resultado, consulte as quantidades decurrentHealthy
edesiredHealthy
pods. O resultado é semelhante ao seguinte:status: ... currentHealthy: 3 desiredHealthy: 2 disruptionsAllowed: 1 expectedPods: 3 ...
Planeie as atualizações binárias do MySQL
O Kubernetes e o GKE oferecem funcionalidades para facilitar as atualizações do binário do MySQL. No entanto, tem de realizar algumas operações para se preparar para as atualizações.
Tenha em atenção as seguintes considerações antes de iniciar o processo de atualização:
- As atualizações devem ser realizadas primeiro num ambiente de teste. Para sistemas de produção, deve realizar mais testes num ambiente de pré-produção.
- Para algumas versões binárias, não pode reverter a versão depois de fazer uma atualização. Dedique tempo a compreender as implicações de uma atualização.
- As origens de replicação podem ser replicadas para uma versão mais recente. No entanto, a cópia de uma versão mais recente para uma versão mais antiga não é normalmente suportada.
- Certifique-se de que tem uma cópia de segurança completa da base de dados antes de implementar a versão atualizada.
- Tenha em atenção a natureza efémera dos pods do Kubernetes. Qualquer estado de configuração armazenado pelo pod que não esteja no volume persistente é perdido quando o pod é reimplementado.
- Para atualizações binárias do MySQL, use o mesmo PDB, estratégia de atualização do conjunto de nós e sondas, conforme descrito anteriormente.
Num ambiente de produção, deve seguir estas práticas recomendadas:
- Crie uma imagem do contentor com a nova versão do MySQL.
- Persista as instruções de compilação de imagens num repositório de controlo de origem.
- Use um pipeline de compilação e testes de imagens automatizado, como o Cloud Build, e armazene o ficheiro binário da imagem num registo de imagens, como o Artifact Registry.
Para manter este tutorial simples, não vai criar nem persistir uma imagem de contentor. Em alternativa, vai usar as imagens públicas do MySQL.
Implemente o ficheiro binário do MySQL atualizado
Para fazer a atualização binária do MySQL, emite um comando declarativo que modifica a versão da imagem do recurso StatefulSet. O GKE executa os passos necessários para parar o pod atual, implementar um novo pod com o binário atualizado e anexar o disco persistente ao novo pod.
Verifique se o PDB foi criado.
kubectl get poddisruptionbudgets -n mysql1
Obtenha a lista de conjuntos com estado.
kubectl get statefulsets -n mysql1
Obtenha a lista de Pods em execução com a etiqueta
app
.kubectl get pods --selector=app=mysql -n mysql1
Atualize a imagem do MySQL no conjunto com estado.
kubectl -n mysql1 \ set image statefulset/dbc1 \ mysql=mysql/mysql-server:8.0.30
O resultado é semelhante ao seguinte:
statefulset.apps/mysql image updated
Verifique o estado dos pods de terminação e dos novos pods.
kubectl get pods --selector=app=mysql -n mysql1
Valide a atualização binária do MySQL
Durante a atualização, pode verificar o estado da implementação, os novos pods e o serviço existente.
Confirme a atualização executando o comando
rollout status
.kubectl rollout status statefulset/dbc1 -n mysql1
O resultado é semelhante ao seguinte:
partitioned roll out complete: 3 new pods have been updated...
Confirme a versão da imagem inspecionando o conjunto com estado.
kubectl get statefulsets -o wide -n mysql1
O resultado é semelhante ao seguinte:
NAME READY AGE CONTAINERS IMAGES dbc1 3/3 37m mysql mysql/mysql-server:8.0.30
Verifique o estado 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 estado e versão na saída. O resultado é semelhante ao seguinte:
... "status": "ONLINE", "version": "8.0.30" ...
Reverter a implementação do lançamento da última app
Quando reverte a implementação de uma versão binária atualizada, o processo de implementação é invertido e é implementado um novo conjunto de pods com a versão da imagem anterior.
Para reverter a implementação para a versão de trabalho anterior, use o comando rollout undo
:
kubectl rollout undo statefulset/dbc1 -n mysql1
O resultado é semelhante ao seguinte:
statefulset.apps/dbc1 rolled back
Expanda o cluster da base de dados horizontalmente
Para dimensionar o cluster do MySQL InnoDB horizontalmente, adicione nós adicionais ao conjunto de nós do cluster do GKE (apenas necessário se estiver a usar o Standard), implemente instâncias adicionais do MySQL e, em seguida, adicione cada instância ao cluster do MySQL InnoDB existente.
Adicione nós ao seu cluster padrão
Esta operação não é necessária se estiver a usar um cluster do Autopilot.
Para adicionar nós ao seu cluster Standard, siga as instruções abaixo para o Cloud Shell ou a Google Cloud consola. Para ver passos detalhados, consulte o artigo Redimensione um conjunto de nós
gcloud
No Cloud Shell, redimensione o node pool predefinido para oito instâncias em cada grupo de instâncias gerido.
gcloud container clusters resize ${CLUSTER_NAME} \
--node-pool default-pool \
--num-nodes=8
Consola
Para adicionar nós ao cluster padrão:
- Abra a
gkemulti-west1
página Cluster na Google Cloud consola. - Selecione Nodes e clique em default pool.
- Desloque a página para baixo até Grupos de instâncias.
- Para cada grupo de instâncias, redimensione o valor de
Number of nodes
de 5 para 8 nós.
Adicione pods do MySQL ao cluster principal
Para implementar pods MySQL adicionais para dimensionar o cluster horizontalmente, siga estes passos:
No Cloud Shell, atualize o número de réplicas na implementação do MySQL de três réplicas para cinco réplicas.
kubectl scale -n mysql1 --replicas=5 -f c1-mysql.yaml
Verifique o progresso da implementação.
kubectl -n mysql1 get pods --selector=app=mysql -o wide
Para determinar se os pods estão prontos, use a flag
--watch
para monitorizar a implementação. Se estiver a usar clusters do Autopilot e vir errosPod Unschedulable
, isto pode indicar que o GKE está a aprovisionar nós para acomodar os pods adicionais.Configure as definições de replicação de grupos para as novas instâncias do MySQL a adicionar ao cluster
bash ../scripts/c1-clustersetup.sh 3 4
O script envia os comandos para as instâncias em execução nos pods com os 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"'
Configure 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 a utilização do MySQL InnoDB Cluster e fazem 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 nova instância ao cluster principal.
cluster.addInstance('icadmin@dbc1-4.mysql', {password: os.getenv("MYSQL_ROOT_PASSWORD"), recoveryMethod: 'clone'});
Obtenha o estado do ClusterSet, que também inclui o estado do cluster.
clusterset = dba.getClusterSet() clusterset.status({extended: 1})
O resultado é semelhante ao seguinte:
"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