Kubernetes – MySQL InnoDB Cluster
O MySQL é um software de base de dados de extrema importância na tecnologia atual. Este software é amplamente utilizado como base de dados em muitos CMSs populares na web, como o WordPress, Joomla, entre outros. O foco deste artigo é o MySQL Cluster, usando os produtos da Oracle, gratuito e funcional.
Este artigo irá descrever os passos para criar um cluster MySQL InnoDB dentro do nosso cluster Kubernetes, dando continuidade aos artigos anteriores.
O que é um cluster MySQL InnoDB?
Um cluster MySQL InnoDB é uma solução de alta disponibilidade que permite a falha de um sistema sem interromper o serviço. Normalmente, um dos sistemas age como master e os outros como slaves. No caso de o master falhar ou ser desligado para manutenção, por exemplo, um dos slaves é eleito como novo master. Isso mantém a disponibilidade para armazenar e entregar os dados existentes nas bases de dados. O MySQL já oferece uma solução de cluster de alta disponibilidade (HA) desde a versão 5.7, e esse projeto foi aprimorado até a versão 8, que será utilizada neste artigo em continuação aos artigos anteriores.
Cluster MySQL InnoDB no Kubernetes
O Kubernetes é um projeto eficaz para orquestrar containers, nos quais são executados vários tipos de software para realizar tarefas específicas.
A ideia de ter um cluster MySQL InnoDB a funcionar dentro de containers, orquestrados pelo Kubernetes, é a mesma de todos os outros softwares que são executados em containers. Isso nos permite dimensionar horizontalmente o número de instâncias conforme necessário para atender a uma determinada carga de trabalho, seja aumentando ou diminuindo. Se as aplicações precisarem de mais disponibilidade, podemos aumentar, e vice-versa.
O Kubernetes também trata de reiniciar qualquer aplicação ou replicar a mesma se esta falhar por algum motivo. No caso do MySQL, se um nó do cluster precisar de manutenção, o POD será iniciado em outro nó do cluster Kubernetes. Isso garante que o serviço MySQL permaneça funcional e disponível.
Desafios
Devido à minha limitação de recursos, seria necessário ter muitos servidores e sistemas de armazenamento profissionais para realizar testes de desempenho reais desses sistemas. Isso não seria fácil de obter em casa, dada a necessidade de hardware e redundância.
Portanto, vamos explorar como configurar um cluster MySQL InnoDB no nosso cluster Kubernetes, com um nó mestre e três nós de trabalho. Isso funcionará de forma mais lenta, mas permitirá que sigamos o caminho de testar este sistema.
Vamos ver como colocar em funcionamento o cluster MySQL InnoDB e como aceder a ele através de outra aplicação no cluster, que será o phpMyAdmin. Esta aplicação web de gestão de base de dados MySQL nos permitirá realizar análises no nosso cluster MySQL, bem como em outros aspetos relacionados ao mesmo cluster, como a importação de dados, por exemplo.
No entanto, o conhecimento adquirido através destas experiências possui um grande valor na vida profissional. É crucial compreender e testar todos estes conceitos.
Oracle MySQL Operator
O Oracle MySQL Operator é um sistema de administração de bases de dados fiável que é frequentemente a escolha padrão para hospedagem web popular, incluindo o WordPress. Oferece várias funcionalidades importantes:
- Solução de auto-recuperação: O Oracle MySQL Operator pode criar e dimensionar clusters MySQL InnoDB em execução no Kubernetes. Utiliza o plugin Group Replication para criar grupos tolerantes a falhas que podem funcionar num modo de único primário, onde apenas um servidor aprova atualizações de cada vez, ou num modo de múltiplos primários, onde todos os servidores podem aceitar atualizações simultaneamente. Este plugin de replicação multi-mestre oferece vantagens como capacidade de atualização em qualquer local, resolução de conflitos incorporada, gestão de adesão a grupos e capacidades de recuperação distribuída automática.
- Cópia de segurança e restauro: Os utilizadores podem criar cópias de segurança sob demanda ou agendar cópias de segurança automáticas de bases de dados para o Armazenamento de Objetos numa hora predefinida. Além disso, o operador suporta a recuperação de bases de dados a partir de cópias de segurança existentes.
- Arquitetura: Utiliza o InnoDB e o Group Replication para criar e dimensionar clusters MySQL no Kubernetes. Se as instâncias do cluster falharem, o MySQL Operator recuperá-las-á automaticamente para o cluster. As Reivindicações de Volume Persistente do Kubernetes permitem armazenar dados em armazenamento ligado em rede ou discos locais.
- Desempenho: O operador utiliza Definições de Recursos Personalizados (CRDs) para estender a API do Kubernetes. Os utilizadores do MySQL Operator podem interagir com clusters MySQL através destes objetos de recursos de terceiros.
- Facilidade de utilização: Criar um Cluster MySQL com o Oracle MySQL Operator é simples. Os utilizadores definem um ficheiro YAML e utilizam o kubectl para o submeter diretamente ao Kubernetes. O operador monitoriza os recursos do Cluster MySQL e toma as medidas necessárias para criar e administrar um cluster MySQL.
Em resumo, o Oracle MySQL Operator é uma solução robusta para administrar bases de dados MySQL em ambientes Kubernetes. Fornece funcionalidades para alta disponibilidade, cópia de segurança e recuperação, bem como facilidade de administração, tornando-o uma escolha valiosa para hospedagem web e outras aplicações.
Preparação do Armazenamento
Em um artigo anterior sobre o armazenamento do nosso cluster Kubernetes, configuramos um servidor para agir com armazenamento NFS para os nossos projetos.
Neste artigo, usaremos o mesmo armazenamento NFS para armazenar as bases de dados do cluster MySQL. Visto que é o único que tenho disponível.
Claro que a nível profissional, devemos usar no mínimo servidores com TrueNAS com alta disponibilidade, até sistemas de hardware da Dell e outros. Que têm como funcionalidade disponibilizar serviços como o NFS.
O ideal seria termos as bases de dados de cada servidor MySQL armazenadas em um NAS diferente, a fim de termos redundância, se um NAS falhar ou necessitar de manutenção.
No entanto, no nosso servidor, iremos criar mais uma partilha dedicada à base de dados MySQL InnoDB Cluster. Que servirá para testarmos esta solução.
Os seguintes passos devem ser executados no kube-storage, o servidor de armazenamento NFS.
Criando a partilha
Para criarmos a partilha, executamos os seguintes comandos:
mkdir /mnt/InnoDBCluster -p chown -R nobody:nogroup /mnt/InnoDBCluster chmod 2770 /mnt/InnoDBCluster
Configurar a partilha
Para configurar a partilha do diretório “/mnt/InnoDBCluster”, execute o seguinte comando:
echo '/mnt/InnoDBCluster 192.168.16.0/24(rw,sync,no_subtree_check,insecure,no_root_squash)' >> /etc/exports
Ativando a Partilha
Para ativar a partilha, execute o seguinte comando:
exportfs -a
Neste momento, já temos o diretório “/mnt/InnoDBCluster” criado e já se encontra a ser partilhado, podendo ser usado pelo nosso cluster Kubernetes.
Kubernetes Storage
A fim de podermos usar a partilha que criamos no passo anterior no cluster. Temos de criar uma nova StorageClass, onde iremos usar a partilha e permitir que o Mysql reclame volumes nesta Classe.
Os seguintes passos, devem ser executados na maquina kube-master, o control plane do cluster kubernetes.
O Mysql cluster vai reclamar volumes na StorageClass que esteja configurada por defeito no kubernetes. No entanto nem sempre isto é desejado, em produção as bases de dados ficam em sistemas com discos SSD, para conseguirem um bom rendimento. No entanto não queremos que todas as aplicações usem a mesmo tipo de storage, depende da situação. Para o caso das bases de dados irei definir os volumes persistentes manualmente, a fim de simular a realidade em produção.
Criando uma StorageClass
Para criarmos a StorageClass, corremos o seguinte comando:
kubectl create -f - <<EOF
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: nfs-innodb-cluster
provisioner: nfs.csi.k8s.io
parameters:
server: kube-storage
share: /mnt/InnoDBCluster
reclaimPolicy: Retain
volumeBindingMode: Immediate
mountOptions:
- hard
- intr
- nfsvers=4.1
EOF
Criando os volumes persistentes
O MySQL cluster vai reclamar volumes com um determinado nome, que podemos prever, como o seguinte:
datadir-<NOME DO CLUSTER>-<NUMERO COMEÇANDO EM ZERO>
Sabendo que vou querer “3” instâncias e que vou dar o nome ao cluster de “innodbcluster”, sei que necessito de criar os volumes com os seguintes nomes:
datadir-innodbcluster-0
datadir-innodbcluster-1
datadir-innodbcluster-2
No vosso caso, podem desejar mais instâncias, no entanto, esta lógica serve bem.
Para criar os volumes persistentes para as três instâncias MySQL do cluster, execute o seguinte comando:
kubectl create -f - <<EOF
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: datadir-innodbcluster-0
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 10Gi
storageClassName: nfs-innodb-cluster
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: datadir-innodbcluster-1
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 10Gi
storageClassName: nfs-innodb-cluster
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: datadir-innodbcluster-2
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 10Gi
storageClassName: nfs-innodb-cluster
EOF
Este comando deve retornar o seguinte:
persistentvolumeclaim/datadir-innodbcluster-0 created
persistentvolumeclaim/datadir-innodbcluster-1 created
persistentvolumeclaim/datadir-innodbcluster-2 created
Devemos verificar se os volumes foram criados e se já estão com o STATUS de “Bound”, para isso, execute o seguinte comando:
kubectl get pvc
Este comando deve retornar algo idêntico ao seguinte:
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
datadir-innodbcluster-0 Bound pvc-e5b5f25f-1c98-410d-aa5e-f87e8db2497e 10Gi RWX nfs-innodb-cluster 7s
datadir-innodbcluster-1 Bound pvc-fe264a2b-addc-4237-b9e0-c94823e23b59 10Gi RWX nfs-innodb-cluster 7s
datadir-innodbcluster-2 Bound pvc-b558ca6c-fb61-4ff7-9878-c9aaeeb1d1e9 10Gi RWX nfs-innodb-cluster 7s
Não devemos continuar até que STATUS seja “Bound”.
Neste momento, já temos a nossa classe criada no nosso cluster Kubernetes e os volumes persistentes onde serão guardados os dados dos servidores MySQL.
Instalar o MySQL Operator
O MySQL Operator é um operador da Oracle que permite controlarmos o cluster MySQL InnoDB através das APIs do Kubernetes, um ou mais clusters InnoDB.
Instalando Custom Resource Definition (CRD)
O MySQL Operator usa Definições de Recursos Personalizados para estender o Kubernetes e assim poder realizar o seu trabalho. Para tal, necessitamos de instalar estas definições. Para isso, execute o seguinte comando:
kubectl apply -f https://raw.githubusercontent.com/mysql/mysql-operator/trunk/deploy/deploy-crds.yaml
Este comando deve retornar algo idêntico ao seguinte:
customresourcedefinition.apiextensions.k8s.io/innodbclusters.mysql.oracle.com configured
customresourcedefinition.apiextensions.k8s.io/mysqlbackups.mysql.oracle.com created
customresourcedefinition.apiextensions.k8s.io/clusterkopfpeerings.zalando.org created
customresourcedefinition.apiextensions.k8s.io/kopfpeerings.zalando.org created
Instalando o MySQL Operator
Para instalar o operador, basta executar o seguinte comando:
kubectl apply -f https://raw.githubusercontent.com/mysql/mysql-operator/trunk/deploy/deploy-operator.yaml
O comando deve retornar um resultado idêntico ao seguinte:
clusterrole.rbac.authorization.k8s.io/mysql-operator created
clusterrole.rbac.authorization.k8s.io/mysql-sidecar created
clusterrolebinding.rbac.authorization.k8s.io/mysql-operator-rolebinding created
clusterkopfpeering.zalando.org/mysql-operator created
namespace/mysql-operator created
serviceaccount/mysql-operator-sa created
deployment.apps/mysql-operator created
Verificar o operador
Devemos verificar se o operador foi criado e o seu estado. Para isso, execute o seguinte comando:
kubectl get deployment mysql-operator --namespace mysql-operator
O resultado deve ser algo idêntico ao seguinte, onde a coluna “READY” deve ter o valor “1/1”:
NAME READY UP-TO-DATE AVAILABLE AGE
mysql-operator 1/1 1 1 2m4s
Devemos aguardar até que o valor seja o esperado.
Criando o cluster InnoDB MySQL
Tendo o MySQL Operator pronto, podemos iniciar o processo de criar um ou mais clusters InnoDB MySQL. Neste artigo, iremos criar apenas um.
Criando Credenciais
O MySQL irá necessitar de uma palavra-passe para atribuir ao utilizador root no processo de instalação. Aqui uso a palavra-passe “password”, pois é um artigo de teste. Em produção, devemos ter mais cuidado, claro.
Para criarmos o segredo que contém a informação da conta root, execute o seguinte comando:
kubectl create secret generic mypwds \
--from-literal=rootUser=root \
--from-literal=rootHost=% \
--from-literal=rootPassword="password"
Deve retornar o seguinte:
secret/mypwds created
Definindo o nosso Cluster
Vou neste caso definir um cluster com três instâncias e 1 router, visto que criamos três volumes persistentes, já a contar com o número de instâncias. Se pretenderem que o cluster InnoDB MySQL tenha mais instâncias, devem adequar o número de volumes persistentes.
Neste caso, o cluster terá um master que permite leitura/escrita e dois slaves que permitirão apenas leitura. Outras configurações são possíveis, devemos consultar a documentação.
kubectl create -f - <<EOF
apiVersion: mysql.oracle.com/v2
kind: InnoDBCluster
metadata:
name: innodbcluster
spec:
secretName: mypwds
tlsUseSelfSigned: true
instances: 3
router:
instances: 1
EOF
Deve retornar o seguinte:
innodbcluster.mysql.oracle.com/innodbcluster created
Verificar o estado da criação das instâncias
Ao corrermos o comando anterior, o operador terá acesso às informações e com elas começa a preparar o cluster. Este processo pode ser bem demorado, pois o operador descarrega as imagens da Oracle, tanto do servidor MySQL como também a imagem do router, a serem usadas pelos containers.
Para vermos o estado deste processo, corremos o seguinte comando:
kubectl get innodbcluster --watch
Mostra o seguinte:
NAME STATUS ONLINE INSTANCES ROUTERS AGE
innodbcluster ONLINE 0 3 1 3m10s
Devemos esperar que o comando mostre a coluna “ONLINE” com “3”, o que indica que todas as instâncias foram criadas e estão online.
Como podemos ver no seguinte resultado:
NAME STATUS ONLINE INSTANCES ROUTERS AGE
innodbcluster ONLINE 3 3 1 30m8s
Este processo pode demorar muito, especialmente se os recursos do seu sistema forem limitados. Aguarde até que todas as instâncias do cluster InnoDB MySQL fiquem online.
Conectar ao servidor MySQL
Após todas as instâncias estarem online, prosseguimos e ligamo-nos ao serviço a fim de verificar o seu funcionamento. Iremos correr o seguinte comando que nos ligará ao serviço:
kubectl run --rm -it myshell --image=container-registry.oracle.com/mysql/community-operator -- mysqlsh root@innodbcluster --sql
Quando aparecer a seguinte frase, deve inserir a palavra-passe, que neste caso é “password”:
If you don't see a command prompt, try pressing enter.
Depois de inserida, irá mostrar algo do género:
If you don't see a command prompt, try pressing enter.
********
Save password for 'root@innodbcluster'? [Y]es/[N]o/Ne[v]er (default No): y
MySQL Shell 8.1.0
Copyright (c) 2016, 2023, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its affiliates.
Other names may be trademarks of their respective owners.
Type '\help' or '\?' for help; '\quit' to exit.
Creating a session to 'root@innodbcluster'
Fetching global names for auto-completion... Press ^C to stop.
Your MySQL connection id is 2922 (X protocol)
Server version: 8.1.0 MySQL Community Server - GPL
No default schema selected; type \use <schema> to set one.
MySQL innodbcluster:33060+ ssl SQL >
Podem confirmar o servidor a que estão ligados com o seguinte comando SQL, que deve ser inserido no terminal ligado ao SQL, depois de logarem:
SELECT @@hostname;
Deve retornar algo idêntico ao seguinte:
+-----------------+
| @@hostname |
+-----------------+
| innodbcluster-0 |
+-----------------+
1 row in set (0.0004 sec)
MySQL innodbcluster:33060+ ssl SQL >
Agora necessitamos preparar a conta de root para permitir que o phpMyAdmin faça login no serviço. Este passo é importante e sem ele não será possível fazer login em muitas aplicações PHP, como é o caso do phpMyAdmin. Para tal, corremos o seguinte comando SQL:
ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'password';
Neste momento, já temos o nosso cluster em funcionamento, configurada a conta root para permitir o login através do phpMyAdmin que será usado a seguir.
Instalar o phpMyAdmin
Para ter acesso e analisar com mais facilidade através de uma interface web, podemos instalar o phpMyAdmin. Ou podemos continuar pelo terminal do passo anterior.
Antes de mais, começamos por criar um segredo que contém a palavra-passe do MySQL. Para isso, corremos o seguinte comando para converter a palavra-passe para base64:
echo 'password' | base64
Deve retornar a palavra-passe em base64, como a seguir:
cGFzc3dvcmQ=
Agora criamos o segredo com o valor obtido, para isso corremos o seguinte comando:
kubectl apply -f - <<EOF
apiVersion: v1
kind: Secret
metadata:
name: mysql-secrets
type: Opaque
data:
root-password: cGFzc3dvcmQK
EOF
Deve retornar algo idêntico ao seguinte:
secret/mysql-pass created
Criar o phpMyAdmin
O passo seguinte é criar o phpMyAdmin e o respetivo serviço para acedermos ao mesmo.
Para instalarmos o phpMyAdmin no kubernetes corremos o seguinte comando:
kubectl apply -f - <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: phpmyadmin-deployment
labels:
app: phpmyadmin
spec:
replicas: 1
selector:
matchLabels:
app: phpmyadmin
template:
metadata:
labels:
app: phpmyadmin
spec:
containers:
- name: phpmyadmin
image: phpmyadmin/phpmyadmin
ports:
- containerPort: 80
env:
- name: PMA_HOST
value: innodbcluster
- name: PMA_PORT
value: "6446"
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-secrets
key: root-password
---
apiVersion: v1
kind: Service
metadata:
name: phpmyadmin-service
spec:
type: LoadBalancer
selector:
app: phpmyadmin
ports:
- protocol: TCP
port: 80
targetPort: 80
EOF
Devemos ver algo idêntico ao seguinte:
deployment.apps/phpmyadmin-deployment created
service/phpmyadmin-service created
Para confirmar o IP que foi entregue ao serviço do phpMyAdmin, corremos o seguinte comando:
kubectl get service/phpmyadmin-service
Que nos deve retornar algo idêntico ao seguinte:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
phpmyadmin-service LoadBalancer 10.109.206.158 192.168.16.60 80:31618/TCP 29m
Agora, basta aceder a partir de um computador que esteja na mesma rede através de um navegador ao endereço IP externo do serviço, que neste caso é “192.168.16.60”. Importa relembrar que este artigo leva em consideração os artigos anteriores, nos quais foi destinada a rede “192.168.16.0/24” para as máquinas do cluster, bem como para a Internet. Esta configuração corresponde à minha rede de testes, se a vossa for diferente, deverão adaptá-la à vossa própria rede.
Administrar o cluster MySQL InnoDB
Esta parte do artigo é dedicada à administração do nosso cluster MySQL InnoDB.
Para testarmos como podemos escalar, podendo ter 9 instâncias do Mysql e muitos routers deforma a simular alguma aplicação que necessite de muita resposta do cluster MySQL. Iremos necessitar sempre de um volume para cada instância.
Criando mais volumes persistentes
Vou criar mais 6 volumes persistentes, para que já estejam prontos, caso necessitarmos escalar as instâncias para cima. Como iremos ver com exemplos.
O seguinte comando irá criar estes volumes para usarmos:
for storageID in {3..8}; do
kubectl apply -f - <<EOF
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: datadir-innodbcluster-$storageID
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 10Gi
storageClassName: nfs-innodb-cluster
EOF
done
Este comando deve devolver o seguinte:
persistentvolumeclaim/datadir-innodbcluster-3 created
persistentvolumeclaim/datadir-innodbcluster-4 created
persistentvolumeclaim/datadir-innodbcluster-5 created
persistentvolumeclaim/datadir-innodbcluster-6 created
persistentvolumeclaim/datadir-innodbcluster-7 created
persistentvolumeclaim/datadir-innodbcluster-8 created
Se confirmarmos agora os volumes persistentes, com o seguinte comando:
kubectl get pvc
Deve mostrar que os volumes foram criados, e o seu “STATUS” dever ser “Bound”:
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
datadir-innodbcluster-0 Bound pvc-e5b5f25f-1c98-410d-aa5e-f87e8db2497e 10Gi RWX nfs-innodb-cluster 27h
datadir-innodbcluster-1 Bound pvc-fe264a2b-addc-4237-b9e0-c94823e23b59 10Gi RWX nfs-innodb-cluster 27h
datadir-innodbcluster-2 Bound pvc-b558ca6c-fb61-4ff7-9878-c9aaeeb1d1e9 10Gi RWX nfs-innodb-cluster 27h
datadir-innodbcluster-3 Bound pvc-b6e6332a-dc9f-44b3-873a-254eb22226f8 10Gi RWX nfs-innodb-cluster 2m6s
datadir-innodbcluster-4 Bound pvc-a7dbee23-a4e4-43c7-b174-32690175d260 10Gi RWX nfs-innodb-cluster 2m6s
datadir-innodbcluster-5 Bound pvc-689ed969-63aa-487d-806b-54c83d1e255b 10Gi RWX nfs-innodb-cluster 2m6s
datadir-innodbcluster-6 Bound pvc-78c7f774-700d-4a8b-8e40-fb8e41f7d9f0 10Gi RWX nfs-innodb-cluster 2m6s
datadir-innodbcluster-7 Bound pvc-99e2a690-1018-46fb-b1b1-5dbc48348175 10Gi RWX nfs-innodb-cluster 2m6s
datadir-innodbcluster-8 Bound pvc-c889c9ee-59c1-462e-a98a-0757dc5d60b0 10Gi RWX nfs-innodb-cluster 2m5s
Neste momento já temos 9 volumes criados, que podemos usar para o nosso cluster MySQL InnoDB.
Escalar o cluster MySQL InnoDB
Visto que a ideia de termos um cluster MySQL InnoDB dentro do nosso cluster Kubernetes é poder controlar o nosso cluster MySQL InnoDB como qualquer outra aplicação dentro do Kubernetes, escalando o numero de instâncias e routers conforme seja necessário. Tal como fazemos com as outras APPs, o wordpress por exemplo.
Para escalarmos iremos modificar e aplicar as definições desejadas para o cluster em um determinado momento. Para isso usamos a mesma lógica de quando criamos o cluster, no entanto não criamos mas aplicamos as novas definições.
Como podemos analisar no YAML embebido no seguinte comando, estou a definir o numero de instâncias de que necessito em determinado momento. Neste caso 9 instâncias:
kubectl apply -f - <<EOF
apiVersion: mysql.oracle.com/v2
kind: InnoDBCluster
metadata:
name: innodbcluster
spec:
secretName: mypwds
tlsUseSelfSigned: true
instances: 9
router:
instances: 1
EOF
Quando executamos este comando, o MySQL operator irá ter conhecimento das mudanças desejadas e começa a criar as instâncias que faltam para ficar de acordo com o que desejamos, instruímos.
Se corrermos o seguinte comando, podemos analisar as instâncias a serem criadas:
kubectl get innodbcluster --watch
Caso queiramos escalar para baixo, funciona da mesma maneira, só temos de definir o numero de instâncias desejadas, e aplicar no kubernetes.
Se pretendermos mais routers, o processo é o mesmo, definimos o numero desejados e aplicamos no kubernetes.
Desta forma permite nos escalar o MySQL InnoDB de forma simples através do Kubernetes.
Backups
O MySQL Operator também lida com automatização de backups. Permitindo criar vários backups com perfis diferentes. Para se adequar às necessidades. São usados crontabs seguindo a lógica do cron no Linux. Onde os trabalhos são agendados para correr em determinados períodos de tempo.
Neste artigo vou exemplificar como criar dois perfis de backup e agenda-los de forma diferente. De forma a percebermos como funciona esta multi configuração.
Um perfil irá fazer o backup de tudo, uma vez ao dia, que é importante quando os dados dos mesmos tem valor para uma empresa ou mesmo a nível pessoal.
O segundo perfil irá fazer o backup apenas de um schema/base de dados “TEST”, com muito valor para uma empresa ou pessoal, são feitas muitas modificações durante um dia, desta forma este backup terá de ser realizado de hora em hora.
Como tal para realizarmos backups, vamos necessitar de um volume para guarda los, em uma situação profissional estes backups devem ser guardados fora dos sistemas que estão a correr as bases de dados, pois não seria um backup mas apenas uma cópia, se o sistema avariar pode corromper as bases de dados e os supostos backups. Devemos criar uma StorageClasse à parte apenas para os backups, em um sistema diferente ou em vários, dentro e fora da empresa.
No entanto neste artigo, apenas vou criar um volume no mesmo StorageClass devido às limitações e porque é apenas um teste.
Criando o Volume de Backups
Para criarmos o volume de backups o processo é o mesmo, que criamos os outros volumes no artigo, no entanto vamos dar um nome que o identifique melhor, para isso corremos o seguinte comando:
kubectl create -f - <<EOF
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: innodbcluster-backup
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 10Gi
storageClassName: nfs-innodb-cluster
EOF
Neste momento já temos o nosso volume de backups, criado e pronto a ser usado.
Definindo os Perfis e Tarefas de backup
As modificações do nosso cluster MySQL InnoDB, são realizadas especificando propriedades para um determinado cluster. Podemos ter vários, neste artigo apenas um e é neste que temos de especificar as propriedades e o que ele deve ter e fazer, dentro dos limites da API claro.
Devemos através do phpMyAdmin por exemplo criar a base de dados “TEST” com uma ou mais tabelas, para podermos ver o backup da mesma a ser realizado. Desta forma ficamos mais seguros do seu seu funcionamento.
Para atualizarmos o nosso cluster, para que possa ter as tarefas agendadas para os backups e os perfis, corremos o seguinte comando, que tem embebido o YAML com a especificações do cluster:
kubectl apply -f - <<EOF
apiVersion: mysql.oracle.com/v2
kind: InnoDBCluster
metadata:
name: innodbcluster
spec:
instances: 2
router:
instances: 1
secretName: mypwds
tlsUseSelfSigned: true
backupProfiles:
- name: todos-os-schemas
dumpInstance:
storage:
persistentVolumeClaim:
claimName: innodbcluster-backup
- name: apenas-o-schema-test
dumpInstance:
dumpOptions:
includeSchemas: ["TEST"]
storage:
persistentVolumeClaim:
claimName: innodbcluster-backup
backupSchedules:
- name: todos-os-schemas
schedule: "0 0 * * *"
backupProfileName: todos-os-schemas
enabled: true
- name: apenas-o-schema-test
schedule: "0 * * * *"
backupProfileName: apenas-o-schema-test
enabled: true
EOF
Como podemos ver pelas especificações no comando anterior, temos dois perfis e duas tarefas com os nomes “todos-os-schemas e apenas-o-schema-test”.
Para vermos a lista de cronjobs/tarefas agendadas corremos o seguinte comando:
kubectl get cronjob.batch
Este comando deve retornar a lista de tarefas agendadas:
NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE
innodbcluster-apenas-o-schema-test-cb 0 * * * * False 0 <none> 44s
innodbcluster-todos-os-schemas-cb 0 0 * * * False 0 <none> 44s
No entanto quando estamos a configurar, gostamos de saber no momento se funciona e não esperar uma hora ou um dia para saber se as tarefas vão ser executadas. Para isso corremos os perfis manualmente a fim de confirmar a sua correta configuração.
Para corrermos estes perfis manualmente corremos o seguinte comando:
kubectl apply -f - <<EOF
apiVersion: mysql.oracle.com/v2
kind: MySQLBackup
metadata:
name: apenas-o-schema-test-manual
spec:
clusterName: innodbcluster
backupProfileName: apenas-o-schema-test
---
apiVersion: mysql.oracle.com/v2
kind: MySQLBackup
metadata:
name: todos-os-schemas-manual
spec:
clusterName: innodbcluster
backupProfileName: todos-os-schemas
EOF
Que deverá retornar o seguinte:
mysqlbackup.mysql.oracle.com/apenas-o-schema-test-manual created
mysqlbackup.mysql.oracle.com/todos-os-schemas-manual created
Para sabermos se funciona temos de verificar, corremos o seguinte comando para saber se está tudo bem com as tarefas manuais:
kubectl get job.batch
Este deve retornar o seguinte:
NAME COMPLETIONS DURATION AGE
apenas-o-schema-test-manual-20231001-021556 1/1 11s 5m44s
todos-os-schemas-manual-20231001-021556 1/1 10s 5m44s
Devemos verificar se a coluna “COMPLETIONS” está com o valor 1/1 em cada tarefa.
No entanto devemos verificar se estão os ficheiros de backup criados no nosso NAS. Para isso executamos o seguinte comando:
kubectl get pvc innodbcluster-backup
Este comando deve retornar algo idêntico ao seguinte:
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
innodbcluster-backup Bound pvc-5743cf2f-a5ec-44e4-9bda-e09bb8190ea9 10Gi RWX nfs-innodb-cluster 5h7m
Como podemos ver a coluna “VOLUME” mostra o nome do diretório criado no nosso Storage para este volume de backups. Com esta informação já podemos confirmar que dentro do diretório “/mnt/InnoDBCluster/pvc-5743cf2f-a5ec-44e4-9bda-e09bb8190ea9” foram criados os diretórios com os nomes começados por: apenas-o-schema-test-manual e todos-os-schemas-manual, que são os nomes das tarefas que corremos manualmente e que dentro deles existem ficheiros. Assim confirmamos que as configuração do Volume, bem como dos perfis funciona. Mas devemos no outro dia verificar se ele está a funcionar de forma automática.
Agora devemos remover as tarefas manuais que corremos pois já não são necessárias, queremos apenas as tarefas automáticas, para isso corremos o seguinte comando:
kubectl delete -f - <<EOF
apiVersion: mysql.oracle.com/v2
kind: MySQLBackup
metadata:
name: apenas-o-schema-test-manual
spec:
clusterName: innodbcluster
backupProfileName: apenas-o-schema-test
---
apiVersion: mysql.oracle.com/v2
kind: MySQLBackup
metadata:
name: todos-os-schemas-manual
spec:
clusterName: innodbcluster
backupProfileName: todos-os-schemas
EOF
Este conteúdo é importante em produção, devemos sempre implementar backups e com a maior redundância possível.
Os manuais do MySQL Operator na Oracle e no gitHub permite criar e usar de forma mais eficiente os backups, claro levando em conta as necessidades que temos e os limites das APIs.
Conclusão
Neste artigo, exploramos como configurar um cluster MySQL InnoDB no Kubernetes usando o MySQL Operator da Oracle. Começamos por preparar o armazenamento, instalamos o MySQL Operator, criamos o cluster MySQL InnoDB e configuramos o phpMyAdmin para aceder ao cluster através de uma interface web. Este é um cenário de teste e aprendizagem, e em ambiente de produção, deve considerar requisitos adicionais de segurança e escalabilidade.
A configuração de um cluster MySQL InnoDB no Kubernetes oferece alta disponibilidade e escalabilidade, tornando-a adequada para cargas de trabalho críticas. Pode expandir este cluster conforme necessário para corresponder às exigências da sua aplicação.
Lembre-se sempre de que a administração de bases de dados é uma tarefa crítica e que deve seguir as melhores práticas de segurança, além de efetuar cópias de segurança regulares dos seus dados para evitar perdas.