Cada item desta checklist termina em algo que podes verificar: uma lista, o resultado de uma consulta, um passo do runbook com um responsável. Os exemplos assumem hosts Linux e PostgreSQL, e um destino com um ou vários fornecedores cloud.
Fase 1: descoberta — o que corre de facto
Ligações: quem fala com quem
As ligações estabelecidas com o processo que as detém e, depois, as portas em escuta:
sudo ss -tnp state established
sudo ss -tlnpUma fotografia do momento não apanha o job que se liga às 03:00. Recolhe uma amostra a cada cinco minutos durante uma semana que inclua um fecho de mês:
# /etc/cron.d/conn-sample (delete after discovery)
PATH=/usr/sbin:/usr/bin:/sbin:/bin
*/5 * * * * root ss -tnp state established >> /var/tmp/conn-$(hostname).logDepois conta os pares de processo e peer:
grep -h 'users:' /var/tmp/conn-*.log |
awk -F'"' '{n = split($1, a, " "); sub(/:[0-9]+$/, "", a[n-1]); print $2, "<->", a[n-1]}' |
sort | uniq -c | sort -rn | head -50Cada peer que não consigas identificar é uma dependência por documentar. A amostragem não apanha as ligações curtas, por isso ativa também log_connections no PostgreSQL durante essa semana.
Trabalho agendado
# as root
for u in $(cut -d: -f1 /etc/passwd); do crontab -u "$u" -l 2>/dev/null | sed "s/^/$u: /"; done
cat /etc/crontab; ls /etc/cron.d /etc/cron.hourly /etc/cron.daily /etc/cron.weekly /etc/cron.monthly
systemctl list-timers --allCada job precisa de um responsável e de um destino; os que escrevem numa base de dados continuam a escrever na cópia antiga depois do cutover se ninguém os parar.
Endereços hard-coded, montagens, entradas de hosts
sudo grep -rIEno '([0-9]{1,3}[.]){3}[0-9]{1,3}' /etc /opt /srv 2>/dev/null |
grep -vE ':(127[.]0[.]0[.]1|0[.]0[.]0[.]0)$' | sort -u
findmnt -t nfs,nfs4,cifs
grep -v '^#' /etc/hostsAcrescenta os diretórios das tuas aplicações e repete a pesquisa com o teu nome de domínio interno. Cada resultado é algo que muda com a migração.
Registos DNS e respetivos TTL
dig +short NS example.com
dig +noall +answer app.example.com @ns1.example.com
dig +short TXT example.comConsulta o servidor autoritativo: um resolver recursivo mostra o tempo que lhe resta em cache, não o TTL configurado. O TTL de cada registo que vai mudar define com quanta antecedência tens de o baixar. Na resposta TXT, procura entradas SPF ip4: dos relays de email do centro de dados.
Licenças ligadas ao hardware
lscpu | grep -E '^ *(Socket|Core|Thread)'
sudo dmidecode -s system-uuid
ip -br linkO software licenciado por socket ou por core, ou associado a um endereço MAC ou a um host ID, não passa tal e qual para uma VM nova. Lê essas condições antes de escolher a estratégia.
Volume de dados e crescimento
df -hT -x tmpfs -x devtmpfsSELECT datname, pg_size_pretty(pg_database_size(datname)) AS size
FROM pg_database ORDER BY pg_database_size(datname) DESC;Compara com há três meses para ver o crescimento e faz as contas à transferência. Imagina 2 TB por uma ligação de 1 Gbit/s da qual podes usar metade: 16 000 gigabits a 0,5 Gbit/s são 32 000 segundos, quase nove horas antes de qualquer restauro começar. Esse número escolhe a opção de migração de dados da fase 4.
Resultado: uma linha por carga de trabalho: responsável, hosts, peers, jobs, nomes DNS, volume de dados, licenças.
Fase 2: decide por carga de trabalho
Atribui a cada carga de trabalho um único destino:
- Retire: sem responsável e sem utilizadores reais numa semana de registos de ligações. Desliga-a antes de migrar.
- Retain: latência para equipamento nas instalações, uma licença que proíbe a cloud ou um fim de vida pouco depois da migração.
- Rehost: a opção por omissão com uma data de saída fixa. Mesmo sistema operativo e configuração, VM nova.
- Replatform: troca o componente que mais tempo de operação te custa por um gerido, como PostgreSQL gerido, e não mexas em mais nada.
- Refactor: só quando a carga de trabalho vai mudar de qualquer forma, nunca como pré-condição para sair.
- Repurchase: funções commodity como o email, o ticketing ou uma wiki. Verifica primeiro a exportação de dados e onde ficam guardados.
- Relocate: move a camada de virtualização inteira para uma versão alojada do mesmo hipervisor quando há demasiadas VMs perante uma data de saída fixa. Compra tempo, não poupança.
Num destino multi-cloud, acrescenta a cada linha o fornecedor, a região e o motivo: um fornecedor por carga de trabalho, com uma razão explícita. O nosso guia de estratégia multi-cloud analisa se um segundo fornecedor compensa. As cargas que mais falam entre si no registo da fase 1 partilham vaga e fornecedor.
Uma avaliação gratuita de migração para a cloud começa exatamente aqui: fazemos o inventário de ligações e de cron nos teus hosts, atribuímos a cada carga de trabalho um destino e uma vaga, e dimensionamos a migração de dados face à tua ligação. O nosso serviço de migração para a cloud trata do resto.
Fase 3: a landing zone, antes da primeira carga de trabalho
Nada é migrado enquanto isto não existir em código. Num destino multi-cloud, constrói-a por fornecedor, com um único fornecedor de identidade e um único conjunto de chaves de etiquetas.
- Contas ou projetos: uma por ambiente, mais uma para os registos de auditoria e outra para a rede partilhada. Nada corre na conta de gestão.
- Rede: intervalos de endereços que não se sobreponham aos do centro de dados, uma VPN site-to-site de volta a ele, uma ligação privada dedicada só se o tráfego da fase 1 a justificar, e reencaminhamento DNS nos dois sentidos.
- Identidade: federação a partir do teu fornecedor de identidade por SAML ou OIDC, MFA, nenhuma chave de longa duração para pessoas, roles para os serviços e uma conta break-glass que gera um alerta sempre que é usada.
- Infraestrutura como código: tudo em Terraform desde o primeiro dia, estado remoto com bloqueio, estado separado por ambiente e por fornecedor, alterações por merge requests revistos. Quando esta camada falta, a consultoria de Terraform é por onde começamos.
- Guardrails: políticas ao nível da organização que limitam as regiões à UE (residência de dados do RGPD, imposta e não apenas prometida), negam buckets públicos, exigem cifragem em repouso e protegem o registo de auditoria.
- Logging: registos de auditoria de todas as contas na conta de registos, com retenção explícita; métricas e logs (Prometheus, OpenTelemetry) a funcionar antes da primeira carga de trabalho, como baseline.
- Etiquetas de custo:
owner,cost-center,environment,app,migration-wave, impostas por política. Em minúsculas e com hífenes: pelo menos um grande fornecedor só aceita chaves de etiqueta em minúsculas.
A verificação de sobreposições, incluindo os pools de clientes VPN e as redes de parceiros:
import ipaddress
on_prem = ["10.0.0.0/16", "172.16.8.0/22", "192.168.50.0/24"]
cloud = ["10.0.128.0/17", "10.40.0.0/16"]
for a in on_prem:
for b in cloud:
if ipaddress.ip_network(a).overlaps(ipaddress.ip_network(b)):
print("overlap:", a, b)A landing zone está concluída quando um merge request cria uma conta com rede, identidade, guardrails e logging, e ninguém abre uma consola.
Fase 4: move os dados
Dump e restore
A indisponibilidade é dump, transferência, restore e verificação. Ensaia numa cópia e cronometra; se couber na janela com margem, não precisas de mais.
pg_dump -Fd -j 4 -f /backup/appdb appdb
rsync -a /backup/appdb/ migrate@TARGET_HOST:/restore/appdb/
pg_restore -h NEW_DB_HOST -U app -d appdb -j 4 --no-owner --no-privileges /restore/appdbAs bases de dados geridas normalmente não te dão superutilizador; daí as flags de propriedade.
Replicação e um cutover curto
Quando a cópia demora mais do que a janela, replica com antecedência e faz o cutover em minutos. A replicação lógica do PostgreSQL funciona entre versões major:
-- Source: needs wal_level = logical (changing it requires a restart)
CREATE PUBLICATION migration FOR ALL TABLES;
-- Target: load the schema first with pg_dump --schema-only, then
CREATE SUBSCRIPTION migration
CONNECTION 'host=10.0.2.7 dbname=appdb user=replicator password=REPLACE_ME'
PUBLICATION migration;As alterações de esquema não são replicadas, por isso o congelamento tem de cobrir o DDL. Os valores das sequências são acertados no cutover (passo 5 do runbook). E, assim que uma tabela sem chave primária nem replica identity é publicada, os UPDATE e DELETE sobre ela falham na origem, e isso parte a produção. Encontra primeiro essas tabelas:
SELECT n.nspname, c.relname FROM pg_class c
JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE c.relkind = 'r' AND n.nspname NOT IN ('pg_catalog', 'information_schema')
AND NOT EXISTS (SELECT 1 FROM pg_constraint p WHERE p.conrelid = c.oid AND p.contype = 'p');Os ficheiros levam duas passagens: uma cópia em massa dias antes e um delta final durante o congelamento.
rsync -aHAX --numeric-ids /srv/data/ migrate@TARGET_HOST:/srv/data/
rsync -aHAX --numeric-ids --delete /srv/data/ migrate@TARGET_HOST:/srv/data/Verifica a cópia
Conta as linhas de todas as tabelas dos dois lados. Nas tabelas que guardam dinheiro ou identidades, compara um hash:
SET TimeZone = 'UTC';
SELECT count(*), md5(string_agg(o::text, '|' ORDER BY o.id)) FROM orders o;Se as duas sessões não tiverem o mesmo fuso horário, os timestamps são impressos de forma diferente e os hashes nunca coincidem. Nas tabelas grandes, faz por intervalos de id. Para os ficheiros, um dry run com checksums lista todas as diferenças:
rsync -aHAXnci --delete /srv/data/ migrate@TARGET_HOST:/srv/data/Quanto tempo fica aberto o caminho de rollback
Enquanto as escritas não reabrirem do lado novo, o rollback é uma alteração de DNS sem perda de dados. A partir daí, o lado antigo fica para trás. Ou configuras replicação inversa no cutover (removes a subscrição de ida, publicas a partir da base de dados nova e subscreves a antiga com copy_data = false), ou acordas por escrito que um rollback tardio implica voltar a introduzir dados à mão. Fecha a janela com um evento de negócio, como a primeira faturação de fim de mês a correr bem do lado novo.
Fase 5: o runbook de cutover
Antes do dia
- T-14 dias: ensaio completo num clone, rollback incluído, com cada passo cronometrado.
- Um TTL antigo mais margem antes: baixa para 300 segundos todos os registos que mudam e confirma com
digcontra o servidor autoritativo. Um registo a 86400 precisa de pelo menos um dia; uma semana é mais seguro. - T-3 dias: congelamento de alterações dos dois lados: nem deploys, nem alterações de esquema ou de configuração.
- T-1 dia: reunião de go/no-go. Ensaio aprovado, lag quase a zero, último backup testado com um restauro, rollback escrito e uma pessoa identificada que decide o rollback.
No dia, por ordem
- 1Ativa a página de manutenção e interrompe as escritas da aplicação.
- 2Interrompe o cron e os timers nos hosts antigos:
systemctl stop cron(oucrond, conforme a distribuição) esystemctl stoppara cada unidade.timerdo teu inventário da fase 1. - 3Na origem, espera que o lag chegue a zero:
SELECT application_name, pg_wal_lsn_diff(pg_current_wal_lsn(), replay_lsn) FROM pg_stat_replication; - 4Corre o delta final do rsync.
- 5Acerta cada sequência, por exemplo
SELECT setval(pg_get_serial_sequence('orders', 'id'), (SELECT max(id) FROM orders));, e depois corre as consultas de verificação. - 6Faz os smoke tests do lado novo com o hostname real antes de mexer no DNS (comando abaixo).
- 7Muda o DNS ou o load balancer e repete os smoke tests a partir do exterior.
- 8Decide go ou no-go à hora fixada de antemão: o go reabre as escritas, o no-go executa o rollback.
curl -sS -o /dev/null -w '%{http_code} %{time_total}' --resolve app.example.com:443:203.0.113.10 https://app.example.com/healthzCritérios de go/no-go
- As contagens e os hashes coincidem, e todos os smoke tests passam.
- A taxa de erros e a latência p95 estão dentro do intervalo medido no lado antigo na semana anterior.
- Nenhum erro de replicação ou de aplicação desde a mudança.
Smoke tests
- Inicia sessão, lê um registo conhecido, cria e apaga um registo de teste.
- Corre um job em segundo plano; envia um email e confirma que passa no SPF.
- Uma chamada por integração externa: sandbox de pagamentos, SFTP de parceiros, webhooks.
O trigger de rollback
Uma frase, acordada antes do dia. Por exemplo: "Se algum critério de go/no-go falhar e não estiver resolvido às 02:00, ou se a taxa de 5xx ficar acima da baseline antiga durante 15 minutos nas primeiras 24 horas, fazemos rollback. Quem decide é o responsável pela migração; não se discute na chamada."
Mantém o lado antigo a responder ou a redirecionar durante alguns dias; alguns resolvers e clientes guardam em cache para lá do TTL.
Fase 6: depois da migração
- Desativa com método. Em cada host antigo,
sudo ss -tn state established '( sport = :5432 )'lista os clientes que ainda chegam à base de dados antiga; cada um é uma dependência que escapou. Mantém o host desligado duas semanas antes de o apagar, revoga as credenciais, túneis, regras de firewall e registos DNS, e cancela as licenças. Um host esquecido deixa de receber patches mas continua acessível, e os cron jobs dele continuam a correr. - Redimensiona com dados reais. Depois de algumas semanas que incluam um fecho de mês, dimensiona para o p95 observado mais margem, não para a alocação on-prem. Os descontos por compromisso vêm depois do rightsizing.
- Orçamentos e etiquetas. Alertas de orçamento por conta e uma lista semanal de recursos sem etiqueta.
- Testa o backup e a recuperação de desastres no novo ambiente. Um job de backup a verde não é um teste. Restaura uma base de dados numa instância nova e cronometra, guarda cópias noutra conta e noutra região, e compara o tempo de recuperação e a perda de dados medidos com o que o negócio aprovou. O nosso trabalho de backup e recuperação de desastres começa por esse restauro.
Erros comuns e como os apanhar cedo
- Intervalos de endereços sobrepostos: corre a verificação de sobreposições antes de existir a primeira rede.
- O consumidor esquecido: uma semana de amostragem com
ss, os registos de ligações da base de dados e a verificação comssdepois do cutover. - Allowlists presas aos IP antigos: firewalls de parceiros, fornecedores de pagamentos, peers SFTP, o teu próprio registo SPF. Faz a lista dos teus IP de saída na fase 1 e pergunta logo aí a cada responsável de integração.
- Um par muito conversador dividido pela VPN: a aplicação na cloud e a base de dados ainda on-prem. Multiplica o round trip pelas consultas de cada página: imagina 200 consultas com um round trip de 15 ms, o que soma 3 segundos.
- MTU do túnel:
ping -M do -s 1472 CLOUD_HOSTa partir do centro de dados envia um pacote de 1500 bytes que não pode ser fragmentado. Se falhar, baixa o tamanho até passar e ajusta o MTU ou o MSS clamping em conformidade; caso contrário, as respostas grandes ficam penduradas enquanto os pedidos pequenos funcionam. - Um rollback por ensaiar: se o ensaio o deixou de fora, não tens rollback.
Antes da primeira vaga, a avaliação gratuita de migração para a cloud cobre o que falha em silêncio: o mapa de dependências tirado dos teus próprios hosts, as verificações de intervalos de endereços e de TTL, as contas da migração de dados para a tua maior base de dados, e um rascunho do runbook da primeira vaga com critérios de go/no-go e um trigger de rollback.