Persistent Volumes e Persistent Volume Claims
1. Introdução ao Armazenamento Persistente no Kubernetes
1.1 Por que armazenamento efêmero não é suficiente (stateless vs. stateful)
Em ambientes Kubernetes, containers e pods são efêmeros por natureza. Quando um pod é reiniciado ou substituído, todo o armazenamento local é perdido. Para aplicações stateless (servidores web, APIs REST) isso é aceitável, mas para bancos de dados, sistemas de arquivos e aplicações que precisam manter estado, o armazenamento efêmero é insuficiente. Aí entram os Persistent Volumes (PV) e Persistent Volume Claims (PVC).
1.2 Visão geral do ciclo de vida de dados em containers e pods
O ciclo de vida dos dados em Kubernetes segue esta hierarquia:
- Container efêmero: dados desaparecem com o container
- emptyDir: dados persistem enquanto o pod existir
- hostPath: dados persistem no nó (não recomendado para produção)
- PersistentVolume: dados persistem independentemente do ciclo de vida do pod
1.3 O papel do DevOps na gestão de armazenamento persistente
Como profissional DevOps, você precisa:
- Provisionar e gerenciar volumes de forma automatizada
- Garantir alta disponibilidade e recuperação de desastres
- Implementar políticas de backup e snapshot
- Otimizar custos de armazenamento em cloud providers
2. Conceitos Fundamentais: PV e PVC
2.1 Persistent Volume (PV)
Um PV é um recurso no cluster que representa um pedaço de armazenamento provisionado pelo administrador. Ele tem um ciclo de vida independente de qualquer pod.
Ciclo de vida do PV:
- Available: disponível para ser vinculado
- Bound: vinculado a um PVC
- Released: PVC foi deletado, volume aguarda reclaim
- Failed: erro no volume
2.2 Persistent Volume Claim (PVC)
Um PVC é uma solicitação de armazenamento feita pelo usuário. O Kubernetes automaticamente encontra um PV que atenda aos requisitos (capacidade, modo de acesso) e faz o binding.
2.3 StorageClass
StorageClass permite provisionamento dinâmico. Em vez de criar PVs manualmente, você define uma classe de armazenamento que provisiona volumes automaticamente quando um PVC é criado.
3. Criando e Configurando Persistent Volumes
3.1 Exemplo de manifesto YAML para um PV
PV com hostPath (para desenvolvimento local):
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-hostpath
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
hostPath:
path: /data/volumes/pv1
PV com NFS:
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-nfs
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Retain
nfs:
server: 192.168.1.100
path: /exports/data
PV com AWS EBS:
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-ebs
spec:
capacity:
storage: 20Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Delete
awsElasticBlockStore:
volumeID: vol-0abcd1234efgh5678
fsType: ext4
3.2 Modos de acesso
- ReadWriteOnce (RWO): montado como leitura/escrita por um único nó
- ReadOnlyMany (ROX): montado como somente leitura por múltiplos nós
- ReadWriteMany (RWX): montado como leitura/escrita por múltiplos nós
3.3 Políticas de reclaim
- Retain: volume mantido após PVC ser deletado (requer limpeza manual)
- Delete: volume é deletado automaticamente
- Recycle: volume é limpo e fica disponível novamente (depreciado)
4. Trabalhando com Persistent Volume Claims
4.1 Manifesto YAML de um PVC
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-exemplo
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
storageClassName: "" # Deixa vazio para usar PVs estáticos
4.2 Vinculação (binding) automática e manual
Binding automático: o Kubernetes encontra um PV que atenda aos requisitos do PVC.
Binding manual com selector:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-selector
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
selector:
matchLabels:
tipo: "fast-storage"
4.3 Exemplo prático: PVC montado em um Pod
apiVersion: v1
kind: Pod
metadata:
name: pod-com-volume
spec:
containers:
- name: app
image: nginx
volumeMounts:
- name: dados
mountPath: /usr/share/nginx/html
volumes:
- name: dados
persistentVolumeClaim:
claimName: pvc-exemplo
Para StatefulSet:
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mysql
spec:
serviceName: mysql
replicas: 3
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:8.0
volumeMounts:
- name: dados-mysql
mountPath: /var/lib/mysql
volumeClaimTemplates:
- metadata:
name: dados-mysql
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
storageClassName: standard
5. Provisionamento Dinâmico com StorageClass
5.1 O que é uma StorageClass
StorageClass permite provisionamento dinâmico de volumes. Você define um provisioner (ex: ebs.csi.aws.com, pd.csi.storage.gke.io) e parâmetros específicos.
5.2 Exemplo de StorageClass para cloud providers
AWS EBS (gp3):
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: ebs-gp3
provisioner: ebs.csi.aws.com
parameters:
type: gp3
iops: "3000"
throughput: "125"
reclaimPolicy: Delete
volumeBindingMode: WaitForFirstConsumer
GCE Persistent Disk:
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: gce-pd-ssd
provisioner: pd.csi.storage.gke.io
parameters:
type: pd-ssd
replication-type: none
reclaimPolicy: Retain
Azure Disk:
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: azure-disk-premium
provisioner: disk.csi.azure.com
parameters:
skuname: Premium_LRS
reclaimPolicy: Delete
5.3 Uso de default StorageClass e anotações em PVC
Para definir uma StorageClass como padrão:
kubectl patch storageclass standard -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'
Um PVC sem storageClassName usará a StorageClass padrão:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-automatico
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
6. Boas Práticas e Cenários Comuns para DevOps
6.1 Gerenciamento de estado em StatefulSets
StatefulSets garantem:
- Ordem de deployment (0, 1, 2...)
- Identidade única (pod-0, pod-1)
- Volume dedicado para cada réplica via volumeClaimTemplates
6.2 Backup, snapshot e migração de volumes
Use ferramentas como Velero para backup e restore:
velero backup create meu-backup --include-namespaces producao
velero restore create --from-backup meu-backup
6.3 Segurança: permissões, acesso a NFS e criptografia
- Defina
fsGrouperunAsUserno securityContext do pod - Use NetworkPolicies para restringir acesso ao NFS
- Ative criptografia em repouso no storage class:
text parameters: encrypted: "true" kmsKeyId: "arn:aws:kms:us-east-1:123456789:key/abc-123"
7. Troubleshooting e Monitoramento de Volumes
7.1 Verificando status de PV e PVC
kubectl get pv
kubectl get pvc -n meu-namespace
kubectl describe pv pv-exemplo
kubectl describe pvc pvc-exemplo -n meu-namespace
7.2 Problemas comuns
PVC pendente:
- Verifique se existe PV com capacidade e modo de acesso compatíveis
- Verifique se a StorageClass existe e está acessível
PV não encontrado:
- Verifique se o PV foi criado no namespace correto
- Verifique se o PVC tem storageClassName vazio (para binding estático)
Conflitos de acesso:
- Um PV com ReadWriteOnce só pode ser montado em um nó por vez
7.3 Logs e eventos: como diagnosticar falhas de montagem
kubectl describe pod pod-com-volume
kubectl logs pod-com-volume -c app
kubectl get events --sort-by='.lastTimestamp'
Eventos comuns:
- FailedMount: erro ao montar volume no pod
- WaitForFirstConsumer: volume aguardando pod ser escalonado
- ProvisioningFailed: erro no provisionamento dinâmico
8. Conclusão
Persistent Volumes e Persistent Volume Claims são fundamentais para aplicações stateful no Kubernetes. Como profissional DevOps, dominar esses conceitos permite gerenciar armazenamento de forma eficiente, automatizada e segura. A combinação de PVs estáticos com StorageClasses dinâmicas oferece flexibilidade para diferentes cenários, desde desenvolvimento local até produção em cloud.
Lembre-se sempre de:
- Usar StatefulSets para aplicações stateful
- Implementar backups com Velero ou ferramentas similares
- Monitorar eventos e logs para troubleshooting rápido
- Seguir boas práticas de segurança e criptografia
Referências
- Kubernetes Documentation: Persistent Volumes — Documentação oficial completa sobre PVs, PVCs e ciclo de vida de volumes
- Kubernetes Documentation: Storage Classes — Guia oficial sobre provisionamento dinâmico com StorageClass
- AWS EBS CSI Driver Documentation — Documentação oficial do driver CSI para Amazon EBS no Kubernetes
- Velero Documentation: Backup and Restore — Tutorial oficial da ferramenta Velero para backup e migração de volumes Kubernetes
- Kubernetes Documentation: StatefulSet — Documentação oficial sobre StatefulSets e gerenciamento de estado em pods
- Kubernetes Documentation: Troubleshooting Volumes — Guia prático de troubleshooting para problemas com volumes no Kubernetes