Storage no Kubernetes: PV, PVC, StorageClass e o estado que não devia estar lá

Volume no Kubernetes confunde por causa do modo de acesso e da política de retenção. O que quebra, quando usar StatefulSet e o que não devia rodar no cluster.

Equipe Solvefy 7 min de leitura

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

ObjetoO que éQuem cria
PersistentVolume (PV)Um pedaço de armazenamento realProvisionado dinamicamente, ou pelo administrador
PersistentVolumeClaim (PVC)O pedido: "quero 20 GB com essas características"O time da aplicação
StorageClassO tipo de armazenamento disponível e como provisioná-loO time de plataforma
CSI driverA integração com o storage de verdadeInstalado 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:

ModoSignificaSuportado por
ReadWriteOnce (RWO)Montável para escrita por um nó de cada vezPraticamente todo storage de bloco
ReadOnlyMany (ROX)Leitura por vários nósVários
ReadWriteMany (RWX)Escrita por vários nós ao mesmo tempoSó 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

NecessidadeOpção
Banco no cluster, alta performanceStorage de bloco local, com replicação pela própria aplicação
Volume replicado entre nósCeph RBD, ou solução de storage distribuído do cluster
Compartilhado entre réplicas (RWX)NFS ou CephFS
Dado temporárioVolume efêmero, sem PVC
Arquivo grande, acesso por HTTPStorage 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ê.

Faça agora o seu diagnóstico e orçamento

Inicie com um diagnóstico gratuito da sua infraestrutura e receba uma proposta personalizada — com escopo, cronograma e valores.