Snapshot, backup ou clone de VPS: qual escolher?
Snapshot fica na infraestrutura do provedor e não substitui backup. Veja o que cada opção restaura e o que corrigir na VPS clonada antes de iniciá-la.
O que são, na prática, um snapshot, um backup e um clone
Um snapshot de uma VPS é uma imagem do disco do servidor, mantida pelo fornecedor na infraestrutura dele, dentro da sua conta. Um backup é uma cópia independente dos seus dados, que pode restaurar noutro local sem a ajuda do fornecedor que mantinha o original. Um clone é uma nova instância criada a partir de um snapshot. Por isso, começa por ser uma cópia exata do original, incluindo a identidade.
Cada um resolve problemas diferentes. Um snapshot permite reverter uma atualização que correu mal em poucos minutos, mas deixa de estar disponível se a conta for encerrada. Um backup sobrevive ao desaparecimento do fornecedor, mas demora mais tempo a restaurar porque primeiro é necessário reconstruir a máquina. Um clone fornece um segundo servidor em execução numa única operação, mas também cria duas máquinas que acreditam ser a mesma máquina.
Por que um snapshot de VPS não é um backup
O problema está no domínio de falha, não na qualidade da imagem. Um snapshot fica na plataforma de armazenamento do provedor, normalmente na mesma região do servidor de origem e sempre dentro da mesma conta. Um único evento pode afetar o servidor e o snapshot ao mesmo tempo.
- A conta é suspensa, um pagamento falha ou alguém rouba as credenciais de acesso.
- Uma pessoa ou um script com acesso à API elimina a instância. Em muitos provedores, eliminar uma instância também elimina os snapshots associados. Consulte o comportamento documentado pelo provedor antes de assumir o contrário.
- A região tem uma falha e tudo o que está nela fica inacessível ao mesmo tempo.
- Algum processo executado como root no servidor encontra o token da API do provedor que foi deixado em
/roote elimina os snapshots antes de apagar o disco.
Um backup é a cópia que sobrevive aos quatro casos. O teste consiste numa pergunta: se a conta no provedor deixasse de existir esta tarde, o que ainda seria possível restaurar e onde essa restauração seria feita? Tudo o que falha nesse teste é uma ferramenta de rollback. Continue a criar snapshots, porque nada permite restaurar mais depressa. Depois, mantenha uma segunda cópia num armazenamento que não seja controlado pelo provedor.
A regra antiga continua válida: três cópias dos dados, em dois tipos de armazenamento, sendo uma delas fora da plataforma. Um snapshot do provedor e um repositório de backup restic numa infraestrutura separada aplicam essa regra com dois componentes móveis.
Por que um snapshot de uma base de dados em execução pode ser restaurado com problemas
O snapshot de um fornecedor copia o dispositivo de blocos tal como está num determinado instante. Não pede às aplicações que parem primeiro e não consegue ver os dados que ainda estão na cache de páginas. Por isso, a imagem é, no máximo, consistente após uma falha. Fica exatamente como o disco ficaria se alguém desligasse o cabo de alimentação.
A maior parte da stack lida com esta situação. ext4 e XFS reproduzem o journal durante a montagem, por isso o sistema de ficheiros fica disponível. O PostgreSQL reproduz o seu write-ahead log ao arrancar, como mostra o log:
LOG: database system was not properly shut down; automatic recovery in progressO InnoDB faz o mesmo e apresenta as suas próprias linhas de recuperação após uma falha durante o arranque. Essa recuperação é o funcionamento esperado da base de dados. Por isso, um snapshot de um único volume de um PostgreSQL ou MySQL sem atividade geralmente é restaurado sem problemas.
Existem casos em que a consistência após uma falha não é suficiente. São esses casos que causam os problemas mais graves. Se os seus dados estiverem distribuídos por dois volumes, o disco raiz e o disco de dados separado são capturados em instantes diferentes. Assim, os ficheiros de dados e o diretório de logs podem ficar incoerentes, e a recuperação não terá dados corretos para reproduzir. Qualquer ficheiro que uma aplicação escreva sem chamar fsync, como um upload recebido parcialmente ou um ficheiro de fila, pode ser restaurado truncado. Tudo o que a aplicação mantiver em memória e gravar periodicamente não estará na imagem.
Por isso, grave um dump no disco antes de criar o snapshot. Assim, a imagem contém um ficheiro que sabe ser internamente consistente, independentemente do estado dos ficheiros de dados ativos.
sudo -u postgres pg_dumpall --clean --file=/var/backups/pg-$(date +%F).sql
sudo mysqldump --single-transaction --routines --all-databases > /var/backups/mysql-$(date +%F).sql--single-transaction fornece um dump consistente das tabelas InnoDB sem bloquear as escritas, porque o dump é executado dentro de uma transação com repeatable-read. Não abrange tabelas MyISAM, que precisam de um lock ou de um servidor parado. Confirme que o dump não está vazio nem truncado antes de confiar nele: tail -n 1 /var/backups/mysql-$(date +%F).sql num mysqldump completo termina com um comentário Dump completed.
Se tiver um volume de dados separado, pode congelá-lo durante os segundos necessários para criar o snapshot:
sudo fsfreeze -f /srv
# take the snapshot from your provider's panel or API
sudo fsfreeze -u /srvCongele apenas um volume de dados. Nunca congele /. Um sistema de ficheiros raiz congelado bloqueia todas as escritas no servidor, incluindo a shell que usaria para introduzir o comando de descongelamento. Assim, ficará sem acesso ao sistema e terá de aguardar um hard reset.
A parte externa: restic ou Borg
O snapshot é a parte rápida. A cópia externa é a parte que sobrevive ao seu fornecedor. O restic é uma boa opção padrão porque elimina duplicados, cifra no cliente e grava em armazenamento de objetos compatível com S3, SFTP ou um diretório normal. Um VPS de armazenamento como destino externo funciona bem neste caso, porque os repositórios de backup precisam de capacidade, não de IOPS.
sudo apt update && sudo apt install -y restic
sudo sh -c 'umask 077; head -c 24 /dev/urandom | base64 > /root/.restic-pass'
sudo chmod 600 /root/.restic-pass
sudo cat /root/.restic-passCopie agora essa frase-passe para um gestor de palavras-passe, num dispositivo que não seja este servidor. Não é possível abrir um repositório restic sem ela, e não existe um caminho de recuperação. Se a única cópia da palavra-passe estava no servidor que acabou de perder, o backup é apenas dados cifrados sem utilidade.
export RESTIC_REPOSITORY="s3:https://s3.example.com/vps-backups"
export RESTIC_PASSWORD_FILE=/root/.restic-pass
export AWS_ACCESS_KEY_ID="..."
export AWS_SECRET_ACCESS_KEY="..."
sudo -E restic init
sudo -E restic backup /etc /srv /var/backups
sudo -E restic snapshotssudo -E mantém essas variáveis, porque, sem ele, o root recebe um ambiente limpo e o restic informa que não foi especificada nenhuma localização de repositório. restic snapshots deve listar a execução que acabou de fazer, com o respetivo host e os caminhos. Verifique o próprio repositório regularmente e leia alguns dados de volta, em vez de verificar apenas a estrutura:
sudo -E restic check --read-data-subset=5%
sudo -E restic restore latest --target /tmp/restore-check
sudo -E restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --pruneUm backup não testado é uma suposição. Faça um restauro para outro VPS pelo menos uma vez, cronometre-o e registe o tempo, porque esse número é o seu objetivo real de recuperação. Borg é a outra opção sólida e armazena o repositório através de SSH, em vez de armazenamento de objetos; os compromissos estão descritos em comparação entre restic e BorgBackup.
O que corrigir antes de colocar um VPS clonado em produção
Um clone é uma réplica exata. Esse é o objetivo e também o problema. Tudo o que tornava o original único é duplicado, e as duplicações entram em conflito.
Regenerar as chaves de host SSH. O clone transporta os ficheiros /etc/ssh/ssh_host_* do original, por isso os dois servidores apresentam a mesma identidade de host. Quem controlar um deles pode fazer-se passar pelo outro perante todos os clientes que aceitaram essa chave. O SSH não apresenta nenhum aviso, porque a chave é a que o cliente esperava.
sudo rm -f /etc/ssh/ssh_host_*
sudo ssh-keygen -A
sudo systemctl restart ssh
ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pubssh-keygen -A grava uma chave nova de cada tipo esperado pelo daemon. A impressão digital do último comando tem de ser diferente da do original. A sessão atual continua ativa depois do reinício, porque reiniciar o sshd não fecha as ligações estabelecidas. Faça isto antes de alguém se ligar ao clone. Se deixar para mais tarde, todos os clientes que já confiaram na chave herdada recebem WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! e têm de executar ssh-keygen -R <host> primeiro.
Repor o machine ID. /etc/machine-id é um identificador único que o systemd gera uma vez, no primeiro arranque, e que o clone herda.
sudo truncate -s 0 /etc/machine-id
sudo rm -f /var/lib/dbus/machine-id
sudo ln -s /etc/machine-id /var/lib/dbus/machine-id
sudo rebootUm /etc/machine-id vazio indica ao systemd que deve gerar um valor novo no arranque seguinte. É por isso que deve truncar o ficheiro em vez de o eliminar. A duplicação causa dois problemas. Em imagens que obtêm o endereço por DHCP, o systemd-networkd deriva por predefinição o identificador do cliente DHCP a partir do machine ID. Assim, os dois clones pedem uma concessão como se fossem o mesmo cliente, e o servidor atribui-lhes o mesmo endereço. Além disso, o journald identifica cada entrada com o machine ID, por isso um coletor de logs central agrupa os dois servidores sob uma única máquina. Execute cat /etc/machine-id depois do reboot e confirme que o valor mudou.
Alterar o hostname.
sudo hostnamectl set-hostname web-02
grep 127.0.1.1 /etc/hostshostnamectl grava /etc/hostname e aplica o nome imediatamente. Não altera /etc/hosts, por isso edite a linha 127.0.1.1 para corresponder. Se ignorar este passo, o novo nome não resolve para lado nenhum. Todas as chamadas sudo ficam à espera de uma resolução falhada e apresentam sudo: unable to resolve host web-02: Name or service not known.
Rodar todas as credenciais incorporadas na imagem. O clone contém os segredos do original, e agora duas máquinas podem agir como o original. Reveja os ficheiros authorized_keys do SSH, os tokens de API do fornecedor e do DNS, os ficheiros .env das aplicações, as palavras-passe das bases de dados, as chaves privadas TLS, os tokens de registo dos sistemas de monitorização, a palavra-passe do repositório restic e tudo o resto. Este comando encontra a maioria:
sudo grep -rIlE 'PASSWORD|SECRET|TOKEN|API_KEY' /etc /srv /opt /home 2>/dev/null
sudo find / -name '.env' -not -path '/proc/*' -not -path '/sys/*' 2>/dev/nullSe o clone for uma cópia de teste que nunca vai servir tráfego, revogue as credenciais em vez de as rodar. Um servidor de staging com um token de API de produção ativo é um servidor de produção com pior aplicação de correções.
Desativar os jobs que agora são executados duas vezes. Dois servidores com o mesmo crontab contactam os mesmos sistemas externos no mesmo minuto.
systemctl list-timers --all
sudo crontab -l
sudo ls -l /etc/cron.d /etc/cron.dailyO caso do restic merece atenção, porque pode corromper a retenção em vez de apenas falhar de forma evidente. O restic identifica cada snapshot com o nome do host, e restic forget --keep-daily 7 aplica a sua política por host. Dois servidores que comunicam o mesmo nome de host são tratados como um único host. Assim, os sete snapshots "diários" podem ser todos provenientes do clone, enquanto os snapshots do original são removidos. Corrija o hostname antes da primeira execução da cópia de segurança ou pare o timer no clone. O caso do certbot é mais simples: dois servidores a renovar os mesmos nomes atingem o limite de certificados duplicados da autoridade de certificação, e a execução que perde falha com um erro sobre demasiados certificados já emitidos para esse conjunto exato de nomes. Um clone cujo domínio ainda aponta para o original também não pode concluir um desafio HTTP, por isso desative a renovação nesse servidor.
Tratar do agente de monitorização. A maioria dos agentes identifica o servidor pelo hostname ou por um ficheiro de ID gravado no momento da instalação. Assim, dois agentes que comunicam como se fossem o mesmo host misturam as métricas numa única série. Os gráficos de CPU passam a mostrar valores que nenhuma máquina produziu sozinha, e os alertas ficam instáveis. Pare e remova o agente do clone ou registe-o novamente com o novo hostname, seguindo o procedimento documentado pelo fornecedor.
Verificar a configuração de rede relativamente ao endereço do original. Se a imagem contiver um endereço estático no netplan, o clone reivindica um IP que pertence a outra máquina.
ip -br addr
sudo grep -r addresses /etc/netplan/Limpar o estado do cloud-init se este clone se tornar um template.
sudo cloud-init clean --logsIsto remove o estado do cloud-init em /var/lib/cloud, por isso o arranque seguinte executa novamente os módulos de primeiro arranque. Entre eles está a geração das chaves de host SSH quando não existem chaves presentes. Algumas versões também disponibilizam uma flag para repor o machine ID. Execute cloud-init clean --help na sua própria imagem para verificar o que a sua versão suporta, em vez de confiar numa lista de flags encontrada noutro local.
Quando usar cada opção
Reverter uma atualização arriscada: crie um snapshot. Faça-o alguns minutos antes da alteração, execute a atualização e restaure a imagem se algo correr mal. A restauração elimina todas as gravações feitas desde o snapshot. Por isso, num servidor que recebe tráfego em produção, faça primeiro um dump da base de dados e saiba exatamente que janela de dados perderia. Para um do-release-upgrade num servidor que pode ficar offline durante dez minutos, um snapshot é todo o plano necessário.
Migrar para um plano maior: implemente um clone. Crie o clone a partir de um snapshot no plano maior, percorra a lista de identidades acima e teste-o no próprio IP antes de encaminhar qualquer tráfego. Reduza o TTL do DNS um dia antes para que a mudança seja rápida e mantenha o servidor original em execução até o novo servidor ter recebido tráfego real. Confirme primeiro que o plano maior é realmente mais rápido para a sua carga de trabalho, usando o mesmo método de benchmark nos dois servidores, porque ter mais vCPUs num hardware mais ocupado nem sempre representa uma atualização.
Criar um template: faça um snapshot de uma máquina limpa. Instale e aplique hardening a um servidor e remova tudo o que for específico antes de criar a imagem. Não deixe host keys, mantenha o machine ID vazio, remova qualquer authorized_keys pessoal e credenciais, e limpe o cloud-init. Faça o snapshot nesse estado. Cada instância implementada a partir dele gera a sua própria identidade no primeiro boot, pelo que a lista de verificação acima deixa de ser apenas uma lista de verificação. Combine-o com os primeiros dez minutos padrão num VPS novo para que o template já contenha o trabalho que, de outro modo, teria de repetir.
FAQ
Um snapshot de um VPS é um backup?
Não, porque partilha um domínio de falha com o servidor de origem. O snapshot fica no armazenamento do fornecedor, na sua conta, normalmente na mesma região. Uma suspensão da conta, uma chave de API roubada ou a eliminação acidental de uma instância podem remover o servidor e os respetivos snapshots numa única ação. Em muitos fornecedores, eliminar uma instância elimina também os respetivos snapshots por predefinição. Um snapshot é o rollback mais rápido disponível, por isso continue a criá-los e mantenha uma segunda cópia cifrada numa infraestrutura que não seja controlada pelo fornecedor.
Tenho de parar a base de dados antes de criar um snapshot?
Nem sempre, mas tem de aceitar o resultado obtido. Um snapshot do fornecedor é consistente após falha, o que significa que a imagem corresponde ao estado que o disco teria depois de uma falha de energia. PostgreSQL e InnoDB recuperam desse estado durante o arranque, e o PostgreSQL regista database system was not properly shut down; automatic recovery in progress enquanto o faz. A recuperação não é garantida quando os dados abrangem dois volumes que foram capturados em instantes diferentes ou quando uma aplicação escreve sem fsync. Escreva primeiro um pg_dumpall ou um mysqldump --single-transaction no disco, para que a imagem contenha um ficheiro cuja consistência possa confirmar.
Porque é que dois servidores clonados entram em conflito por causa do mesmo endereço IP?
Porque partilham /etc/machine-id. Nas imagens que usam DHCP, o systemd-networkd cria o identificador do cliente DHCP a partir do machine ID por predefinição. Assim, os dois clones pedem um lease como se fossem o mesmo cliente e o servidor DHCP oferece o mesmo endereço a ambos. Trunque /etc/machine-id para zero bytes, remova /var/lib/dbus/machine-id, crie novamente o symlink para /etc/machine-id e reinicie, para que o systemd gere um novo valor. A outra causa comum é um endereço estático escrito em /etc/netplan/, que o clone copiou sem alterações. Verifique com ip -br addr.
Qual é a forma mais rápida de confirmar que um clone pode ser colocado em produção com segurança?
Compare quatro elementos com o servidor original. Execute ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub em ambos e confirme que as impressões digitais são diferentes. Execute cat /etc/machine-id em ambos e confirme que os valores são diferentes. Execute hostnamectl status e confirme que o nome é novo e resolve corretamente, para que sudo não apresente um aviso. Depois execute systemctl list-timers --all e pare todos os timers que comunicam com um sistema partilhado, como backups, renovação de certificados ou um agente de monitorização, até decidir qual das máquinas será responsável por essa tarefa.