Script de backup do Mysql e armazenamento no S3 da AWS

Criando um script de backup de banco de dados Mysql em Shell Script e armazenando no S3 da AWS

Script de backup do Mysql e armazenamento no S3 da AWS

Fala pessoal tudo beleza?

Esse artigo é uma extensão de um artigo que escrevi há alguns anos, onde fiz a criação de um simples script de backup para bancos Mysql.

Hoje estarei refatorando aquele primeiro script e adicionando uma opção para poder armazenar o backup no S3 da AWS.

Caso queira ver o primeiro artigo que escrevi, acesse aqui.

Instalando AWS S3 CLI

Primeiro vamos instalar e configurar a ferramenta de CLI que a AWS fornece para podermos interagir com os recursos na nuvem.

A instalação será feita em um sistema Linux, para a instalação em outros sistemas, pode ser encontrado nesse link.

Execute os comandos:

$ curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"

$ unzip awscliv2.zip

$ sudo ./aws/install

Podemos confirmar se a instalação ocorreu com sucesso, com o comando:

$ aws --version

aws-cli/2.10.3 Python/3.9.11 Linux/5.10.0-21-amd64 exe/x86_64.debian.11 prompt/off

Caso já tenha o aws-cli instalado, poderá verificar se há alguma atualização para ser feita. No terceiro comando mostrado acima, pode usar a flag --update para atualizar para a versão mais recente.

$ sudo ./aws/install --update

You can now run: /usr/local/bin/aws --version

Criando usuário na AWS

Agora é necessário configurar o aws-cli com as credenciais de um usuário, para isso é necessário ter uma conta na AWS.

Nesse artigo irei pressupor que você já tem uma conta na AWS, não irei abordar o processo de criação de conta, mas iremos passar pela criação de um usuário programático e gerar as credenciais.

Com o foco na segurança, esse usuário terá um permissão restrita a um determinado bucket no S3, podendo apenas realizar ações nesse bucket e não tendo acesso nenhum a outros bucket que não seja o que definimos.

Acesse o console da AWS e navegue até a sessão do IAM.

  1. No menu esquerdo, clique em Usuários.
  2. Na tela de listagem de usuários, clique em Adicionar usuários.
  3. Informe o nome de usuário, nesse exemplo vamos criar um usuário chamado backup-s3. Clique em Próximo.
  4. Nessa tela, iremos adicionar uma política ao usuário. Clique no card Anexar políticas diretamente.
  5. Na listagem de políticas, clique em Criar política.
  6. Na tela de criação, clique na aba JSON para informar a política manualmente.
  7. Copie a seguinte política e cole no editor de política - Altere o nome do bucket conforme sua preferência, nesse exemplo estou usando backups-aristides-dev
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "s3:PutObject",
                "s3:GetObject",
                "s3:DeleteObject"
            ],
            "Resource": [
                "arn:aws:s3:::backups-aristides-dev/*"
            ]
        },
        {
            "Sid": "VisualEditor1",
            "Effect": "Allow",
            "Action": [
                "s3:ListBucket"
            ],
            "Resource": [
                "arn:aws:s3:::backups-aristides-dev"
            ]
        }
    ]
}
  1. Clique em Próximo duas vezes até chegar na tela para informar o nome da política.
  2. Informe o nome BackupS3ReadWriteAccess e clique em Criar política.
  3. Nesse ponto, a política foi criada. Volte para a aba inicial e procure na listagem a política que acabou de ser criada, selecione ela e clique em Próximo.
  4. Revise os dados e clique em Criar usuário.

Até aqui acabamos de criar um usuário e anexamos uma política para que esse usuário tenha acesso somente a um bucket chamado backups-aristides-dev. Com essa política, o usuário poderá executar as ações de Leitura/Escrita/Remoção de arquivos dentro do bucket.

Para dar continuidade precisamos que o bucket já esteja criado. Para isso crie um bucket pela console da AWS com o mesmo nome que foi definido por você ao criar a política, no meu caso backups-aristides-dev. Não irei abordar a criação por se tratar de um passo simples, apenas informe o nome e deixe as opções padrões do bucket.

Gerar credenciais de segurança

Após a criação do usuário e do bucket, acesse novamente a listagem de usuários do IAM e clique sobre o usuário backup-s3 que acabamos de criar.

  1. Na aba Credenciais de segurança, na sessão Chaves de acesso, clique em Criar chave de acesso.
  2. Selecione a opção Command Line Interface (CLI), marque o checkbox Compreendo a recomendação acima e quero prosseguir para criar uma chave de acesso. e clique em Próximo.
  3. Caso queira deixar alguma descrição (essa informação é opcional), informe na caixa de texto e clique em Criar chave de acesso.
  4. Esse passo é muito importante, as chaves geradas serão mostradas apenas uma vez na tela. Clique em Baixar arquivo .csv e salve em um lugar seguro as credenciais.
  5. Após baixar o arquivo .csv, clique em Concluído.

Configurando AWS S3 CLI

Após todo os passos acima de criação de usuário e geração das chaves de acesso, devemos configurar a ferramente de CLI para podermos interagir com o S3.

Execute o comando abaixo para configurar o acesso e informe as credenciais do usuário criado.

$ aws configure

AWS Access Key ID [None]: <access-key-id>
AWS Secret Access Key [None]: <secret-access-key>
Default region name [None]: us-east-1
Default output format [None]: json

Para validarmos o acesso, vamos copiar um arquivo para o bucket e em seguida listarmos.

# Cria um arquivo de teste com conteúdo
$ touch teste.txt && echo "Backup Mysql" > teste.txt

# Copia o arquivo criado para o bucket
$ aws s3 cp teste.txt s3://backups-aristides-dev/
upload: ./teste.txt to s3://backups-aristides-dev/teste.txt

# Lista o conteúdo do bucket
$ aws s3 ls s3://backups-aristides-dev/
2023-03-11 18:45:18          13 teste.txt

Podemos validar também se o nosso usuário tem acesso para visualizar outros buckets:

# Para listar todos os bucket no S3
$ aws s3 ls
An error occurred (AccessDenied) when calling the ListBuckets operation: Access Denied

# Copiando um arquivo para outro bucket
$ aws s3 cp teste.txt s3://meu-bucket-pessoal/       
upload failed: ./teste.txt to s3://meu-bucket-pessoal/teste.txt An error occurred (AccessDenied) when calling the PutObject operation: Access Denied

Show de bola, como visto acima o usuário criado tem acesso somente a um determinado bucket. Com isso nós garantimos uma segurança a mais para o nosso script de backup.

Script de backup Mysql

Nesse script, deixei toda parte do código comentado para um melhor entendimento de cada linha. Mas em resumo o script executará os seguintes passos:

  1. Define algumas variáveis que serão usadas durante a execução do script.
  2. Define o nome dos bancos de dados que devem ser realizado o backup.
  3. Verifica se o diretório de armazenamento dos arquivos e do log existem, caso não, serão criados.
  4. Faz um loop nos bancos de dados para realizar o backup, compactar e sincronizar com o S3.
  5. O script irá sincronizar todo o conteúdo do diretório de backup, caso um arquivo já exista no S3, esse não será enviado novamente.
  6. Remove arquivos de backups antigos conforme a quantidade de dias determinada. Essa remoção será somente do servidor, no S3 os arquivos irão ser mantidos normalmente.

Abaixo segue todo o código de backup:

#!/bin/bash
# 
# Autor: Aristides Neto
# Email: [email protected]
#
# Data: 11/03/2023
#
# Realiza o backup de bancos de dados MySQL
# Sincroniza com o S3 da AWS
#

# Define usuario e senha do banco
USER='root'
PASS='root'

# Datas
DIA=`date +%d`
MES=`date +%m`
ANO=`date +%Y`
DATA_ATUAL=`date +%Y-%m-%d-%H-%M`

# Data de Inicio do Backup
DATA_INICIO=`date +%d/%m/%Y-%H:%M:%S`

# Caminho do arquivo de log
LOG_DIR=/var/log/backup
LOG=$LOG_DIR/backup_db_$ANO$MES$DIA.log

# Diretorio onde serão salvos os backups
DIR_BK=/backups/mysql

# Lista dos bancos de dados que serão realizados o backup
DATABASES=(banco01 banco02)

# Verifica se existe o diretorio para armazenar os logs
if [ ! -d $LOG_DIR ]; then
    mkdir $LOG_DIR
fi

# Verifica se existe o diretorio para o backup
if [ ! -d $DIR_BK ]; then
    mkdir -p $DIR_BK
fi

# Inicio do backup
echo -e "MYSQLDUMP Iniciado em $DATA_INICIO\n" >> $LOG

# Loop para backupear todos os bancos
for db in "${DATABASES[@]}"; do
    # Mysql DUMP
    # Para backupear procedures e functions foi adicionado o --routines
    echo "...Realizando backup do banco ...........................[ $db ]" >> $LOG
    mysqldump --routines -u$USER -p$PASS $db > $DIR_BK/$db'_'$DATA_ATUAL.sql

    # Compacta o arquivo sql em BZ2
    echo "...Compactando arquivo de backup ........................[ $db ]" >> $LOG
    bzip2 $DIR_BK/$db'_'$DATA_ATUAL.sql

    # Sincroniza o diretório local com o bucket S3
    aws s3 sync $DIR_BK s3://backups-aristides-dev
    echo "...Sincronização do diretório de backup com S3 ..........[ OK ]" >> $LOG
done

DATA_FINAL=`date +%d/%m/%Y-%H:%M:%S`
echo -e "\nMYSQLDUMP Finalizado em $DATA_FINAL\n" >> $LOG

# Remove arquivos de backups antigos - 5 dias
find $DIR_BK -type f -mtime +5 -exec rm -rf {} \;

Para executar esse script recomendo que seja feito com o usuário root, pois serão criados diretórios e arquivos em locais que serão necessárias permissões de super usuário. Caso deseja executar com um usuário não root, certifique que terá as permissões corretas.

Log de execução do script

Ao executar o script, será criado um arquivo de log no caminho definido na variável LOG => /var/log/backup que conterá informações do banco backupeado e sincronização com o S3.

Esse é um arquivo bem simples, mas é uma forma de monitorar o andamento do backup.

MYSQLDUMP Iniciado em 11/03/2023-19:00:34

...Realizando backup do banco ...........................[ banco01 ]
...Compactando arquivo de backup ........................[ banco01 ]
...Sincronização do diretório de backup com S3 ..........[ OK ]

...Realizando backup do banco ...........................[ banco02 ]
...Compactando arquivo de backup ........................[ banco02 ]
...Sincronização do diretório de backup com S3 ..........[ OK ]

MYSQLDUMP Finalizado em 11/03/2023-19:04:14

Conclusão

Esse é um script simples, que não contém validações em caso de possíveis erros nos comandos executados. É uma boa prática e recomendado adicionar validações nos comandos executados e validar se foi executado com sucesso ou não.

Não será o foco desse artigo essa implementação, mas recomendo que tenha validações e em casos de erros tenha um alerta, seja o envio de um e-mail ou uma notificação em um canal como o Slack, Microsoft Teams ou outro. Esses programas disponibilizam um webhook para esses casos que irá te ajudar a enviar as notificações.

Espero que seja útil esse script e qualquer dúvida, melhorias ou comentários, não deixe de comentar abaixo.

Até a próxima.