1

Reformatei a última réplica do meu banco numa "migração simples" de disco

Ontem eu quase perdi um banco de dados inteiro. A culpa foi minha, e a sequência de erros é boa demais pra não compartilhar.

Contexto rápido: rodo um cluster Kubernetes localmente (k3s), com Longhorn cuidando do storage. Um node morreu (o SSD do sistema parou de aceitar escrita) e eu acabei precisando trocar. Aproveitei pra consolidar o storage: jogar os HDDs grandes todos num nó só e deixar os outros dois rodando só em NVMe. Plano de 20 minutos. No papel.

Não foi um erro isolado! Foram quatro, em fila, cada um destravando o próximo:

flowchart TD
    P["Migração de storage<br/>(mover HDDs pra 1 nó)"]
    P --> A1["#1 fstab monta por /dev/sdb,<br/>não por UUID"]
    A1 --> A2["Reboot reordena os devices"]
    A2 --> A3["Discos montam TROCADOS<br/>Longhorn: DiskFilesystemChanged"]
    P --> B1["#2 Não confirmei qual<br/>máquina física era qual"]
    B1 --> B2["Desliguei e abri o nó ERRADO"]
    B2 --> C1["#3 mkfs no disco que saiu"]
    C1 --> C2{"#4 Chequei se algum volume<br/>tinha a última cópia ali?"}
    C2 -->|"'0 faulted', achei seguro"| BOOM["Ultima replica viva<br/>de um banco apagada"]
    BOOM --> S1["Backup pg_dump das 06h"]
    BOOM --> S2["Humano: 'valida antes de promover'"]
    S1 --> R["Restore + cluster recuperado"]
    S2 --> R

Erro 1, fstab por device. Meu /etc/fstab montava os discos por /dev/sdb, /dev/sdc, o nome que o kernel dá na ordem que ele acha os discos. Reiniciei a máquina e o kernel enumerou numa ordem diferente. Cada disco montou no lugar do outro. O Longhorn olhou, viu que o disco no caminho esperado não era o que ele tinha registrado, e marcou tudo como "filesystem changed". Vários volumes degradados de uma vez, do nada.

Erro 2, máquina errada. O rótulo que eu tinha na cabeça não batia com o hostname que o cluster usava. Desliguei e abri o nó errado, e tirei o HDD errado: o que ainda tinha dado, não o que eu queria esvaziar.

Erro 3 e 4, o mkfs sem análise devida. Pra reintegrar o disco no nó novo, formatei. mkfs, limpo. Antes eu até olhei: "tem volume sem cópia? não, zero faulted". Falsa segurança. O Longhorn contava como "cópia" uma réplica parada num disco prestes a sair, e essa era a última cópia viva de um banco interno meu (uma fila de tasks de uns agentes autônomos que rodo). O mkfs passou por cima. Dado vivo, evaporado.

Pra deixar o tamanho do tropeço claro, o antes e depois do storage:

AntesDepois
AHDD grande + NVMeNVMe só (HDD saiu; era o plano, mas no nó errado)
BHDDs + NVMeHDDs + NVMe (ainda a migrar)
C (storage)2 HDDs2 HDDs + o HDD grande

O que salvou

Duas coisas, e nenhuma delas foi esperteza minha no momento.

Backup. Um pg_dump que roda todo dia às 6 da manhã num volume separado. Quando fui ver, os backups de dois dias antes estavam com 0 bytes: tinham falhado durante a crise do SSD e não houve nenhum alerta na stack de monitoria (outra lição). Mas o da manhã pegou. Íntegro. Recuperei o banco até ali. Perdi uma janela de horas, mas era dado operacional, recriável.

Não estar sozinho. No meio da bagunça, quando eu já ia "promover" a réplica sobrevivente achando que tinha dado, veio um "calma, valida primeiro se esse disco tem a ver com o banco" (eu conversando com o Claude hehe). Validei. Não tinha dado nenhum ali. Se eu tivesse seguido, teria sobrescrito o backup com vazio. O passo mais perigoso foi barrado por uma pergunta simples antes do irreversível.

Teve até um plot twist bom: os discos do outro nó, que eu achava corrompidos, estavam só montados nos lugares trocados. Remontei por UUID, apontei os caminhos certos, e dezenas de réplicas voltaram. O banco do produto, esse, nunca chegou perto de ser afetado. Ficou saudável o tempo todo, isolado do resto. Pelo menos uma coisa eu tinha feito direito antes.

As lições, aprendidas na marra!

  • Monte disco de dados por UUID, nunca por /dev/sdX. E põe nofail, senão um disco que saiu trava o boot inteiro esperando ele.
  • 0 faulted não te dá permissão pra formatar. Antes de qualquer mkfs num disco que vai sair, cheque réplica por réplica se alguma é a última cópia de alguém.
  • Confirme qual máquina física é qual antes de desligar. Rótulo na cabeça não conta.
  • Migração de storage é um nó por vez. Manter redundância durante a janela não é luxo.
  • Backup que "rodou com sucesso" pode ter gerado um arquivo de 0 byte. Valide o tamanho, não só o exit code.
  • E mantenha alguém olhando. A melhor proteção contra o erro irreversível foi uma pergunta feita por outra pessoa na hora certa.

No fim deu tudo certo. Cluster de pé, banco restaurado, produto intacto. Mas foi por backup e por uma segunda pessoa atenta, não por competência minha naquele momento. Tô deixando registrado mais pra mim do que pra vocês.

Minha stack (pra os curiosos)

O cluster é k3s + Longhorn, rodando em três nós em casa:

CPURAMStorage físicoPapel
Node 1Intel i5-10400 (6c/12t)32 GBNVMe 1 TB (Micron)control-plane
Node 2Intel i5-10400 (6c/12t)32 GBSSD 256 GB (sistema) + 3 HDDs (4 TB + 5 TB + 4 TB)worker
Node 32× Xeon E5-2680 v2 (20c/40t)188 GBSSD 256 GB (sistema) + 2× 2 TB + 12 TB (HDD)storage / o nó "gordo"

O Node 3 virou o nó de storage justamente por isso: muita RAM e baia de disco sobrando. Os HDDs do Node 2 ainda vão migrar pra ele numa Fase 2, que agora vou fazer com bem mais calma (e um nó por vez).

E já que você chegou até aqui, o jabá: esse cluster não é só lab. É onde rodam, em produção, dois produtos meus, o zelfy.io (gestão pessoal de verdade num lugar só: finanças, saúde, estudos e reflexões) e o boladecristal.com.br. Pois é, eu quase torrei o storage que segura os meus próprios produtos. A ironia ficou registrada.

Alguém aí já apagou produção (ou quase) numa operação que parecia trivial? Conta a sua.

Carregando publicação patrocinada...