Kubernetes foi desenhado para cargas sem estado. Pod é descartável, morre e nasce em outro nó, e isso funciona lindamente enquanto não há nada para preservar. No momento em que aparece um banco de dados, uma fila com persistência ou um diretório de uploads, a abstração fica mais complicada — e é onde a maioria dos incidentes de dado em Kubernetes acontece.
O modelo não é difícil. O que confunde são dois detalhes que só mostram consequência depois: o modo de acesso e a política de retenção.
O modelo, em quatro objetos
| Objeto | O que é | Quem cria |
|---|---|---|
| PersistentVolume (PV) | Um pedaço de armazenamento real | Provisionado dinamicamente, ou pelo administrador |
| PersistentVolumeClaim (PVC) | O pedido: "quero 20 GB com essas características" | O time da aplicação |
| StorageClass | O tipo de armazenamento disponível e como provisioná-lo | O time de plataforma |
| CSI driver | A integração com o storage de verdade | Instalado no cluster |
O fluxo: a aplicação declara um PVC referenciando uma StorageClass; o driver provisiona o volume; o PV é criado e ligado ao PVC; o pod monta.
Na prática moderna você quase nunca cria PV na mão — o provisionamento dinâmico faz isso. O que você define é a StorageClass, e as escolhas dela decidem quase tudo.
O modo de acesso: a armadilha número um
Três modos, e a confusão sobre eles causa mais dor do que qualquer outro detalhe:
| Modo | Significa | Suportado por |
|---|---|---|
| ReadWriteOnce (RWO) | Montável para escrita por um nó de cada vez | Praticamente todo storage de bloco |
| ReadOnlyMany (ROX) | Leitura por vários nós | Vários |
| ReadWriteMany (RWX) | Escrita por vários nós ao mesmo tempo | Só storage de arquivo: NFS, CephFS |
O ponto que engana: RWO é por nó, não por pod. Dois pods no mesmo nó podem compartilhar um volume RWO; em nós diferentes, não.
A consequência prática aparece assim: você tem um Deployment com três réplicas e um PVC RWO. Uma réplica sobe, as outras ficam pendentes para sempre, porque foram agendadas em outros nós. O sintoma é "meu pod não sai de Pending" e a causa está no modo de acesso.
Duas saídas corretas:
- Se as réplicas precisam compartilhar o mesmo dado, você precisa de RWX — ou seja, storage de arquivo.
- Se cada réplica precisa do próprio volume, o objeto certo não é Deployment: é StatefulSet.
StatefulSet: quando a identidade importa
Deployment trata os pods como intercambiáveis. StatefulSet dá a cada um identidade estável — nome previsível, ordem de inicialização e, o mais importante, um volume próprio que o acompanha.
Quando um pod de StatefulSet morre, o substituto recebe o mesmo nome e reconecta ao mesmo volume. É exatamente o que um nó de banco de dados replicado precisa.
Use StatefulSet quando: cada réplica tem seu próprio dado, a ordem de inicialização importa, ou outros componentes precisam alcançar cada réplica individualmente pelo nome.
Dois detalhes que surpreendem:
- Os volumes de um StatefulSet não são apagados quando você apaga o StatefulSet. É proteção deliberada contra perda de dado — e significa que limpeza de ambiente exige remoção explícita dos PVCs. Também significa que "apaguei e recriei" não limpa o estado, o que confunde durante diagnóstico.
- Redimensionar volume é possível na maioria das StorageClasses, mas quase sempre só para cima. Planeje o crescimento; encolher exige migração de dado.
A política de retenção: o campo que apaga dados
Toda StorageClass tem uma política que define o que acontece com o volume quando o PVC é removido:
- Delete — o volume e o dado são apagados. É o padrão na maioria das StorageClasses.
- Retain — o volume permanece, desvinculado, aguardando ação manual.
Leia de novo: o padrão apaga o dado. Alguém remove um namespace para limpar, os PVCs vão junto, e o volume do banco é destruído. Não é um caso hipotético; é um dos incidentes mais comuns em Kubernetes.
A recomendação: StorageClass separada com política de retenção para dados críticos. Custa uma definição e evita perda irreversível. Some a isso proteção contra remoção acidental de namespace e, principalmente, backup que não dependa do cluster.
Backup: o cluster não protege o seu dado
Isso precisa ser dito sem rodeio: Kubernetes não faz backup. Réplica não é backup, snapshot de volume no mesmo storage não é backup, e o fato de o pod reiniciar sozinho não protege contra nada que aconteça ao dado.
O que precisa existir:
- Backup da aplicação feito pela ferramenta apropriada — para banco de dados, a ferramenta do banco, com recuperação a ponto no tempo. Copiar arquivos de um banco em execução gera cópia inconsistente.
- Backup dos volumes, com ferramenta que entenda Kubernetes e capture também os objetos do cluster.
- Destino fora do cluster e fora do mesmo storage.
- Restauração testada, em cluster diferente, cronometrada.
- Backup dos manifestos, em repositório — reconstruir o cluster é aplicar o código, mas só se o código existir.
Snapshot de volume, quando o driver suporta, é útil para reversão rápida. Não substitui backup, pela mesma razão de sempre: mora no mesmo lugar que o dado.
A pergunta que vem antes: isso devia rodar no cluster?
Vale fazer honestamente, porque a resposta frequentemente é não.
Argumentos para rodar banco fora do Kubernetes:
- Bancos têm requisitos operacionais próprios: tuning, failover, backup com ponto no tempo, atualização de versão maior. Operadores ajudam, e não eliminam a necessidade de alguém que entenda o banco.
- Latência de storage em rede prejudica banco com escrita intensa.
- A complexidade de diagnosticar um problema de banco aumenta quando ele está dentro do cluster.
- Rodar banco em VM dedicada, com storage local rápido, é mais simples, mais rápido e mais fácil de operar.
Argumentos para rodar dentro:
- Ambiente de desenvolvimento e homologação, onde a facilidade vale mais que o desempenho.
- Cargas com estado leve: cache, fila, busca, com reconstrução possível.
- Times com operador maduro implantado e gente que sabe operá-lo.
O padrão que mais recomendamos para cliente com infraestrutura própria: aplicações sem estado no Kubernetes, bancos em VM dedicada — frequentemente no mesmo cluster de virtualização, com storage local rápido e alta disponibilidade no nível da VM. Entrega o melhor dos dois mundos e reduz bastante a superfície de problema.
Isso não é dogma. É a resposta que menos dá trabalho na maioria dos ambientes de porte médio.
Escolher a StorageClass certa
| Necessidade | Opção |
|---|---|
| Banco no cluster, alta performance | Storage de bloco local, com replicação pela própria aplicação |
| Volume replicado entre nós | Ceph RBD, ou solução de storage distribuído do cluster |
| Compartilhado entre réplicas (RWX) | NFS ou CephFS |
| Dado temporário | Volume efêmero, sem PVC |
| Arquivo grande, acesso por HTTP | Storage de objetos, não volume |
O último item é subestimado: upload de usuário, imagem, documento e relatório raramente precisam de sistema de arquivos. Storage de objetos resolve melhor, escala melhor, tem backup mais simples e elimina a necessidade de RWX — que é a fonte de metade dos problemas descritos aqui.
Erros comuns
- Deployment com múltiplas réplicas sobre PVC RWO, e pods presos em Pending.
- Achar que RWO é por pod, quando é por nó.
- Usar Deployment onde o correto é StatefulSet.
- StorageClass com política Delete em dado crítico.
- Apagar namespace e perder o volume do banco.
- Considerar réplica ou snapshot como backup.
- Backup de banco copiando arquivos com o banco em execução.
- Backup armazenado no mesmo storage do cluster.
- Nunca restaurar em cluster diferente para testar.
- Dimensionar o volume sem folga, e descobrir que não dá para encolher depois.
- Rodar banco de produção no cluster sem ninguém que saiba operá-lo.
- Usar volume compartilhado para arquivos que deveriam estar em storage de objetos.
Onde a Solvefy/Cloud entra
Estado em Kubernetes é onde vemos os incidentes mais caros — e a maioria é evitável no desenho. Revisamos e implantamos: StorageClasses com política de retenção adequada ao risco, escolha correta entre Deployment e StatefulSet, modo de acesso compatível com a arquitetura, backup real dos volumes e dos bancos com restauração testada em cluster separado, e a decisão fundamentada sobre o que deve mesmo rodar dentro do cluster. Para clientes com infraestrutura própria, montamos o desenho combinado — Kubernetes para aplicação, VM dedicada com alta disponibilidade para banco.
Seu dado no cluster sobrevive a um `kubectl delete` errado? Diagnóstico gratuito, sem compromisso, em solvefy.cloud.
Solvefy/Cloud — Infraestrutura que cresce com você.