Ir para o conteúdo principal

persistentvolume.yml

Descrição: este arquivo cria um PersistentVolume no Kubernetes.

Um PersistentVolume, também chamado de PV, é um recurso de armazenamento do cluster. Ele representa um volume persistente disponível para uso por aplicações, podendo ser criado manualmente por um administrador ou dinamicamente por uma StorageClass.

Diferente do PersistentVolumeClaim, que é o pedido de armazenamento feito pelo usuário ou aplicação, o PersistentVolume representa o volume disponível ou provisionado no cluster.

Em termos simples:

Pod
  ↓ monta
PersistentVolumeClaim
  ↓ reivindica
PersistentVolume
  ↓ representa
armazenamento real

No arquivo de referência do cluster, o recurso aparece como:

Recurso: persistentvolumes
Tipo: PersistentVolume
Versão: v1

TIPO:       PersistentVolume
VERSÃO:    v1

DESCRIÇÃO:
    PersistentVolume (PV) é um recurso de armazenamento provisionado por um administrador.
    Ele é análogo a um nó. Mais informações:
    https://kubernetes.io/docs/concepts/storage/persistent-volumes

Quando usar PersistentVolume

Use PersistentVolume quando você precisa representar armazenamento persistente disponível no cluster.

Use PV quando:

  • o administrador quer provisionar volumes manualmente;
  • o cluster não usa provisionamento dinâmico para aquele tipo de storage;
  • existe um volume NFS já disponível;
  • existe um disco local específico;
  • existe storage externo que precisa ser registrado no Kubernetes;
  • você quer controlar manualmente capacidade, modo de acesso e política de retenção;
  • precisa associar um volume existente a um PVC;
  • precisa usar Retain para preservar dados após remoção do PVC;
  • precisa representar storage específico por labels;
  • precisa definir nodeAffinity para volume local;
  • precisa controlar mountOptions;
  • precisa fazer binding manual com claimRef ou volumeName.

Exemplos comuns:

  • volume NFS institucional;
  • disco local de um nó específico;
  • volume CSI já existente;
  • volume com dados legados;
  • volume preservado após remoção de PVC;
  • storage criado manualmente pelo administrador;
  • volume compartilhado para aplicações de laboratório;
  • volume com política Retain para dados importantes.

Quando PersistentVolume não é o recurso indicado

PersistentVolume não é o melhor recurso quando o problema exige outro tipo de controle.

Necessidade Recurso mais indicado Motivo
Solicitar armazenamento dentro de um namespace PersistentVolumeClaim PVC é o pedido do usuário/aplicação.
Provisionar volumes automaticamente StorageClass + PVC StorageClass define provisionador e políticas.
Executar aplicação Deployment, StatefulSet, Job ou CronJob PV apenas representa armazenamento.
Montar volume em um Pod Pod usando PVC Pod monta PVC, não PV diretamente em uso comum.
Guardar configuração pequena ConfigMap PV não é para configuração simples.
Guardar senha/token/certificado Secret PV não é cofre de credenciais.
Criar armazenamento temporário emptyDir PV é para persistência.
Criar identidade fixa por réplica StatefulSet + volumeClaimTemplates StatefulSet cria PVC por réplica.
Controlar CPU/memória ResourceQuota, LimitRange ou resources PV não controla recursos computacionais.
Publicar aplicação na rede Service ou Ingress PV não expõe aplicação.
Isolar tráfego NetworkPolicy PV não controla rede.

Uso em cenário de universidade

Em uma universidade, um PersistentVolume pode ser usado para representar armazenamento institucional disponível para sistemas acadêmicos, administrativos, laboratoriais e de pesquisa.

Exemplos:

  • export NFS institucional usado por aplicações internas;
  • volume local dedicado para laboratório;
  • storage externo de pesquisa;
  • volume preservado para dados de sistema administrativo;
  • volume compartilhado para arquivos de aplicação;
  • volume manual para homologação;
  • volume de dados legado migrado para Kubernetes;
  • volume com política Retain para evitar exclusão automática;
  • volume usado por PVCs de projetos específicos.

Uso recomendado em ambiente universitário:

  • administradores criam PVs quando o storage é manual ou pré-existente;
  • usuários e aplicações consomem storage via PersistentVolumeClaim;
  • StorageClass deve ser preferida quando houver provisionamento dinâmico adequado;
  • usar labels para classificar finalidade, tipo e ambiente do PV;
  • usar Retain quando os dados não podem ser apagados automaticamente;
  • usar Delete apenas quando a política de descarte estiver clara;
  • documentar origem do volume e finalidade em annotations;
  • usar nodeAffinity para volumes locais;
  • evitar hostPath em ambiente compartilhado salvo necessidade controlada;
  • limitar PVCs por namespace com ResourceQuota;
  • definir política de backup fora do PV quando os dados forem importantes;
  • revisar impacto antes de apagar PV ou PVC.

Exemplo completo: persistentvolume.yml

apiVersion: v1
kind: PersistentVolume

metadata:
  name: pv-minha-aplicacao-dados
  labels:
    app: minha-aplicacao
    ambiente: homologacao
    tipo: nfs
    finalidade: dados
  annotations:
    descricao: "PersistentVolume exemplo para dados persistentes da aplicação"

spec:
  capacity:
    storage: 10Gi

  accessModes:
    - ReadWriteOnce

  persistentVolumeReclaimPolicy: Retain

  storageClassName: manual

  volumeMode: Filesystem

  mountOptions:
    - hard
    - nfsvers=4.1

  nfs:
    server: servidor-nfs.exemplo.local
    path: /dados/minha-aplicacao
    readOnly: false

Explicação linha por linha

apiVersion: v1

Define a versão da API usada pelo manifesto.

Para PersistentVolume, normalmente é:

apiVersion: v1

Significado:

  • v1: versão estável da API core do Kubernetes.

Use exatamente v1 para PersistentVolume.


kind: PersistentVolume

Define o tipo de recurso que será criado.

kind: PersistentVolume

Significado:

  • PersistentVolume: recurso que representa armazenamento persistente disponível no cluster.

Não confundir com:

  • PersistentVolumeClaim: pedido de uso de um volume persistente;
  • StorageClass: classe e provisionador de storage;
  • Pod: recurso que monta o PVC;
  • VolumeSnapshot: snapshot de volume;
  • ConfigMap: configuração não sensível;
  • Secret: dado sensível;
  • emptyDir: volume temporário do Pod.

metadata

metadata identifica e organiza o PV.

metadata:
  name: pv-minha-aplicacao-dados
  labels:
    app: minha-aplicacao
  annotations:
    descricao: "PV exemplo"

metadata.name

Nome do PV.

name: pv-minha-aplicacao-dados

Uso:

  • identifica o PV no cluster;
  • aparece em kubectl get pv;
  • pode ser referenciado por PVC usando volumeName;
  • deve ser único no cluster.

Exemplos bons:

name: pv-app-web-dados
name: pv-nfs-laboratorio
name: pv-banco-homologacao
name: pv-uploads-sistema

Regras práticas:

  • use letras minúsculas;
  • use hífen;
  • evite acentos;
  • evite espaços;
  • escolha nome curto e claro;
  • use prefixo pv- quando ajudar na padronização.

metadata.namespace

O campo metadata.namespace aparece no kubectl explain porque faz parte de ObjectMeta, mas PersistentVolume é recurso de escopo de cluster.

Ou seja, normalmente o PV é criado assim:

metadata:
  name: pv-dados

E não assim:

metadata:
  name: pv-dados
  namespace: meu-projeto

Explicação:

  • PVC é namespaced;
  • PV é cluster-scoped;
  • um PVC em um namespace reivindica um PV disponível no cluster.

metadata.labels

Labels são pares chave/valor usados para organização, filtros e seleção por PVC.

labels:
  tipo: nfs
  ambiente: homologacao
  finalidade: dados

Uso:

  • filtrar PVs com kubectl;
  • organizar volumes;
  • permitir binding por selector no PVC;
  • classificar tipo de storage;
  • indicar finalidade do volume.

Exemplo:

kubectl get pv -l tipo=nfs

Exemplo de PVC selecionando PV por label:

selector:
  matchLabels:
    tipo: nfs
    finalidade: dados

metadata.annotations

Annotations são metadados livres.

annotations:
  descricao: "PV da aplicação"

Uso:

  • documentação;
  • rastreabilidade;
  • registrar origem do volume;
  • registrar caminho externo;
  • integração com ferramentas.

Cuidado:

  • não coloque senha, token ou chave em annotation;
  • annotations também ficam armazenadas no objeto Kubernetes.

Campos de metadata normalmente gerenciados pelo Kubernetes

O kubectl explain mostra vários campos de metadata, mas muitos são preenchidos pelo próprio cluster.

Normalmente você não escreve manualmente:

creationTimestamp:
deletionTimestamp:
resourceVersion:
uid:
generation:
managedFields:
selfLink:
ownerReferences:

Eles servem para controle interno do Kubernetes.


spec

spec descreve o volume persistente disponível.

spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: manual
  volumeMode: Filesystem
  nfs:
    server: servidor-nfs.exemplo.local
    path: /dados

Campos principais:

spec:
  accessModes
  capacity
  claimRef
  mountOptions
  nodeAffinity
  persistentVolumeReclaimPolicy
  storageClassName
  volumeAttributesClassName
  volumeMode
  fontes de volume

spec.capacity

Define a capacidade do volume.

capacity:
  storage: 10Gi

Uso:

  • informar tamanho disponível;
  • permitir comparação com resources.requests.storage do PVC;
  • ajudar no binding entre PV e PVC.

Exemplos:

storage: 1Gi
storage: 10Gi
storage: 100Gi
storage: 1Ti

Cuidado:

  • o PVC só faz bind se o PV atender ao tamanho solicitado;
  • capacidade declarada deve representar a capacidade real do armazenamento.

spec.accessModes

Define como o volume pode ser montado.

accessModes:
  - ReadWriteOnce

Valores comuns:

ReadWriteOnce
ReadOnlyMany
ReadWriteMany
ReadWriteOncePod

A disponibilidade real depende do tipo de storage e do driver/provisionador.


ReadWriteOnce

accessModes:
  - ReadWriteOnce

Também chamado de RWO.

Significado:

  • o volume pode ser montado como leitura/escrita por um único nó.

Uso comum:

  • banco simples;
  • aplicação com uma réplica;
  • volume usado por um Pod por vez;
  • storage comum em muitos clusters.

Cuidado:

  • não significa necessariamente um único Pod;
  • significa restrição de montagem por nó;
  • para múltiplas réplicas em nós diferentes, normalmente não é adequado.

ReadOnlyMany

accessModes:
  - ReadOnlyMany

Também chamado de ROX.

Significado:

  • o volume pode ser montado como somente leitura por muitos nós.

Uso:

  • arquivos compartilhados somente leitura;
  • conteúdo estático;
  • datasets de referência.

ReadWriteMany

accessModes:
  - ReadWriteMany

Também chamado de RWX.

Significado:

  • o volume pode ser montado como leitura/escrita por muitos nós.

Uso:

  • armazenamento compartilhado;
  • múltiplas réplicas lendo e escrevendo;
  • workloads que precisam compartilhar arquivos.

Cuidado:

  • depende de storage compatível;
  • concorrência de escrita precisa ser tratada pela aplicação.

ReadWriteOncePod

accessModes:
  - ReadWriteOncePod

Também chamado de RWOP.

Significado:

  • o volume pode ser montado como leitura/escrita por um único Pod.

Uso:

  • garantir exclusividade mais forte;
  • workloads que não toleram múltiplos montadores;
  • aplicações sensíveis a concorrência.

Cuidado:

  • depende de suporte do cluster e do driver CSI.

spec.persistentVolumeReclaimPolicy

Define o que acontece com o volume quando o PVC associado é removido.

persistentVolumeReclaimPolicy: Retain

Valores aceitos:

Retain
Delete
Recycle

Na prática moderna, os mais importantes são:

Retain
Delete

Retain

persistentVolumeReclaimPolicy: Retain

Significado:

  • quando o PVC é apagado, o PV continua existindo;
  • os dados permanecem;
  • o administrador precisa decidir o que fazer depois.

Uso:

  • dados importantes;
  • volumes manuais;
  • dados que não podem ser apagados automaticamente;
  • ambientes onde a recuperação manual é desejada.

Cuidado:

  • o PV pode ficar em estado Released;
  • pode exigir limpeza manual antes de reutilizar;
  • não disponibiliza automaticamente para outro PVC com dados antigos.

Delete

persistentVolumeReclaimPolicy: Delete

Significado:

  • quando o PVC é apagado, o volume externo pode ser apagado pelo provisionador.

Uso:

  • volumes temporários;
  • ambientes de teste;
  • provisionamento dinâmico;
  • dados que podem ser descartados com segurança.

Cuidado:

  • pode causar perda de dados;
  • use apenas quando a política de descarte estiver clara.

Recycle

persistentVolumeReclaimPolicy: Recycle

Significado:

  • política antiga de reciclagem básica do volume.

Cuidado:

  • está depreciada;
  • normalmente não deve ser usada em ambientes modernos.

spec.storageClassName

Define a StorageClass associada ao PV.

storageClassName: manual

Uso:

  • permitir binding com PVC que pede a mesma classe;
  • classificar tipo de armazenamento;
  • associar PV manual a uma classe lógica.

Exemplos:

storageClassName: manual
storageClassName: nfs
storageClassName: standard
storageClassName: local-path

Cuidado:

  • PVC com storageClassName diferente não fará bind com esse PV;
  • storageClassName: "" em PVC indica que ele não quer StorageClass.

spec.volumeMode

Define se o volume será usado como filesystem ou bloco.

volumeMode: Filesystem

Valores aceitos:

volumeMode: Filesystem
volumeMode: Block

Filesystem

Uso:

  • modo padrão e mais comum;
  • monta o volume como diretório;
  • aplicações acessam arquivos normalmente.

Block

Uso:

  • expõe volume como dispositivo de bloco;
  • aplicações que precisam acessar dispositivo diretamente;
  • cenários específicos de banco ou storage.

Cuidado:

  • é mais avançado;
  • no Pod, o consumo usa volumeDevices, não volumeMounts.

spec.mountOptions

Define opções de montagem.

mountOptions:
  - hard
  - nfsvers=4.1

Uso:

  • opções específicas do storage;
  • NFS;
  • tuning de filesystem;
  • parâmetros de montagem exigidos pela infraestrutura.

Cuidado:

  • opções inválidas podem fazer a montagem falhar;
  • o Kubernetes não valida todas as opções;
  • o suporte depende do tipo de volume.

spec.claimRef

Referencia o PVC associado ao PV.

claimRef:
  namespace: meu-projeto
  name: dados

Uso:

  • reservar PV para um PVC específico;
  • indicar binding existente;
  • recuperar ou controlar associação manual.

Campos comuns:

name
namespace
kind
apiVersion
uid
resourceVersion

Cuidado:

  • mexer manualmente em claimRef pode quebrar binding;
  • use com cuidado em recuperação ou binding estático;
  • em provisionamento normal, o Kubernetes preenche esse campo.

spec.nodeAffinity

Define afinidade de nó para o volume.

nodeAffinity:
  required:
    nodeSelectorTerms:
      - matchExpressions:
          - key: kubernetes.io/hostname
            operator: In
            values:
              - node-01

Uso:

  • volumes locais;
  • volumes acessíveis apenas em alguns nós;
  • storage com restrição de topologia.

Cuidado:

  • se o Pod for agendado em nó sem acesso ao volume, a montagem falha;
  • para volume local, nodeAffinity é essencial.

spec.volumeAttributesClassName

Define a classe de atributos de volume.

volumeAttributesClassName: fast-attributes

Uso:

  • integração com VolumeAttributesClass;
  • alteração ou seleção de atributos de volume;
  • cenários com CSI e suporte a modificação de atributos.

Cuidado:

  • depende da versão do Kubernetes e do suporte do driver CSI;
  • não é necessário para PV comum;
  • use somente quando a infraestrutura fornecer essa funcionalidade.

Fontes de volume em spec

Um PersistentVolume precisa definir uma fonte de volume.

Exemplos de fontes presentes no recurso:

awsElasticBlockStore
azureDisk
azureFile
cephfs
cinder
csi
fc
flexVolume
flocker
gcePersistentDisk
glusterfs
hostPath
iscsi
local
nfs
photonPersistentDisk
portworxVolume
quobyte
rbd
scaleIO
storageos
vsphereVolume

Em ambientes modernos, o uso mais comum costuma ser:

  • csi;
  • nfs;
  • local;
  • hostPath apenas para teste ou casos controlados.

Algumas fontes antigas existem na API por compatibilidade, mas podem estar obsoletas, descontinuadas ou substituídas por drivers CSI.


spec.csi

Define um volume fornecido por driver CSI.

csi:
  driver: exemplo.csi.driver
  volumeHandle: volume-123
  fsType: ext4

Campos principais:

Campo Função
driver nome do driver CSI
volumeHandle identificador do volume no backend
fsType tipo de filesystem
readOnly monta somente leitura
volumeAttributes atributos específicos
nodePublishSecretRef Secret usado na publicação no nó
controllerPublishSecretRef Secret usado pelo controlador
nodeStageSecretRef Secret usado no stage
controllerExpandSecretRef Secret usado na expansão
nodeExpandSecretRef Secret usado na expansão no nó

Uso:

  • integração com storage moderno;
  • cloud;
  • storage distribuído;
  • soluções de volume por CSI.

Cuidado:

  • depende do driver CSI instalado e configurado;
  • campos específicos variam conforme o driver.

spec.nfs

Define volume NFS.

nfs:
  server: servidor-nfs.exemplo.local
  path: /dados/minha-aplicacao
  readOnly: false

Campos:

Campo Função
server servidor NFS
path caminho exportado
readOnly monta como somente leitura

Uso:

  • armazenamento compartilhado;
  • ReadWriteMany quando o NFS permitir;
  • ambientes institucionais com servidor de arquivos.

Cuidado:

  • Kubernetes não gerencia o servidor NFS;
  • permissões e disponibilidade dependem do servidor;
  • performance depende da rede e do NFS.

spec.local

Define volume local em um nó.

local:
  path: /mnt/disco/dados

Uso:

  • disco local de nó específico;
  • workloads que aceitam dependência de nó;
  • cenários de alta performance local.

Cuidado:

  • exige nodeAffinity;
  • se o nó falhar, o volume pode ficar indisponível;
  • não é igual a storage distribuído.

Exemplo com nodeAffinity:

local:
  path: /mnt/disco/dados
nodeAffinity:
  required:
    nodeSelectorTerms:
      - matchExpressions:
          - key: kubernetes.io/hostname
            operator: In
            values:
              - node-01

spec.hostPath

Monta caminho do nó como volume.

hostPath:
  path: /dados/teste
  type: DirectoryOrCreate

Uso:

  • testes;
  • desenvolvimento local;
  • cenários controlados;
  • acesso a caminho específico do nó.

Cuidado:

  • não é recomendado para aplicações portáveis;
  • expõe filesystem do nó;
  • pode gerar risco de segurança;
  • prende o workload a características do nó.

spec.azureFile, azureDisk, awsElasticBlockStore, gcePersistentDisk e similares

Esses campos representam integrações históricas/in-tree com provedores ou tecnologias específicas.

Exemplos:

awsElasticBlockStore
azureDisk
azureFile
gcePersistentDisk
cinder
vsphereVolume
rbd
cephfs
glusterfs
iscsi
fc

Cuidado:

  • muitas integrações antigas foram substituídas por drivers CSI;
  • em clusters modernos, prefira CSI quando disponível;
  • o suporte real depende da versão e da configuração do cluster.

status

status mostra o estado atual do PV.

Você normalmente não escreve status no YAML.

O Kubernetes e controladores de storage preenchem automaticamente.

No arquivo de referência aparecem campos como:

status:
  lastPhaseTransitionTime
  message
  phase
  reason

Use para diagnóstico:

kubectl get pv pv-minha-aplicacao-dados -o yaml
kubectl describe pv pv-minha-aplicacao-dados

status.phase

Mostra a fase atual do PV.

Valores comuns:

Available
Bound
Released
Failed
Pending

Available

PV está disponível e ainda não foi vinculado a um PVC.

Bound

PV está vinculado a um PVC.

Este é o estado esperado quando está em uso.

Released

O PVC associado foi removido, mas o PV ainda mantém referência/dados anteriores.

Comum com política Retain.

Failed

O volume falhou em algum processo de provisionamento, binding ou recuperação.

Pending

Estado de espera observado em alguns cenários.


status.lastPhaseTransitionTime

Mostra quando o PV mudou de fase pela última vez.

lastPhaseTransitionTime

Uso:

  • diagnóstico;
  • auditoria;
  • entender quando o volume mudou de estado.

status.message e status.reason

Mostram mensagem e motivo associados ao estado atual.

message
reason

Uso:

  • diagnóstico de falhas;
  • entender problemas de binding ou storage;
  • investigar erro reportado pelo controlador.

Manifesto mínimo funcional com NFS

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-nfs-dados
spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteMany
  persistentVolumeReclaimPolicy: Retain
  storageClassName: manual
  volumeMode: Filesystem
  nfs:
    server: servidor-nfs.exemplo.local
    path: /dados

Aplicar:

kubectl apply -f persistentvolume.yml

Verificar:

kubectl get pv
kubectl describe pv pv-nfs-dados

Manifesto recomendado para PV NFS manual

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-app-web-dados
  labels:
    tipo: nfs
    finalidade: dados
    ambiente: homologacao
  annotations:
    descricao: "PV NFS manual para aplicação web"
spec:
  capacity:
    storage: 50Gi
  accessModes:
    - ReadWriteMany
  persistentVolumeReclaimPolicy: Retain
  storageClassName: manual-nfs
  volumeMode: Filesystem
  mountOptions:
    - hard
    - nfsvers=4.1
  nfs:
    server: servidor-nfs.exemplo.local
    path: /exports/app-web
    readOnly: false

Manifesto para PV local

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-local-dados
  labels:
    tipo: local
    finalidade: dados
spec:
  capacity:
    storage: 100Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: local-manual
  volumeMode: Filesystem
  local:
    path: /mnt/dados/app
  nodeAffinity:
    required:
      nodeSelectorTerms:
        - matchExpressions:
            - key: kubernetes.io/hostname
              operator: In
              values:
                - node-01

Cuidado:

  • PV local precisa de nodeAffinity;
  • se o nó ficar indisponível, o volume local também fica;
  • não é storage distribuído.

Manifesto para PV hostPath de teste

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-hostpath-teste
spec:
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: manual-hostpath
  volumeMode: Filesystem
  hostPath:
    path: /tmp/pv-hostpath-teste
    type: DirectoryOrCreate

Uso:

  • teste;
  • laboratório;
  • ambiente local.

Cuidado:

  • não use como padrão em produção compartilhada;
  • expõe caminho do nó;
  • prende o volume a um nó específico de forma implícita.

Manifesto para PV CSI

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-csi-dados
spec:
  capacity:
    storage: 20Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: csi-manual
  volumeMode: Filesystem
  csi:
    driver: exemplo.csi.driver
    volumeHandle: volume-123
    fsType: ext4

Cuidado:

  • o driver CSI precisa existir no cluster;
  • volumeHandle precisa corresponder ao volume real no backend;
  • atributos e Secrets dependem do driver usado.

Exemplo de PVC reivindicando PV por StorageClass

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: app-web-dados
  namespace: meu-projeto
spec:
  accessModes:
    - ReadWriteMany
  storageClassName: manual-nfs
  resources:
    requests:
      storage: 10Gi

Esse PVC pode fazer bind com um PV compatível que tenha:

storageClassName: manual-nfs
accessModes:
  - ReadWriteMany
capacity:
  storage: 50Gi

Exemplo de PVC reivindicando PV por label

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: app-web-dados
  namespace: meu-projeto
spec:
  accessModes:
    - ReadWriteMany
  storageClassName: manual-nfs
  resources:
    requests:
      storage: 10Gi
  selector:
    matchLabels:
      finalidade: dados
      tipo: nfs

Exemplo de PVC reivindicando PV específico

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: app-web-dados
  namespace: meu-projeto
spec:
  volumeName: pv-app-web-dados
  accessModes:
    - ReadWriteMany
  storageClassName: manual-nfs
  resources:
    requests:
      storage: 10Gi

Cuidado:

  • o PV precisa existir;
  • precisa ser compatível;
  • se não for compatível, o PVC ficará Pending.

Comandos úteis

Aplicar

kubectl apply -f persistentvolume.yml

Ver PersistentVolumes

kubectl get pv

Ver PV específico

kubectl get pv pv-app-web-dados

Ver detalhes

kubectl describe pv pv-app-web-dados

Ver YAML real aplicado

kubectl get pv pv-app-web-dados -o yaml

Ver PVCs

kubectl get pvc -A

Ver StorageClasses

kubectl get storageclass

Ver eventos de um namespace

kubectl get events -n meu-projeto --sort-by=.lastTimestamp

Filtrar PV por label

kubectl get pv -l tipo=nfs

Ver PVs Bound

kubectl get pv | grep Bound

Ver PVs Available

kubectl get pv | grep Available

Apagar PV

kubectl delete pv pv-app-web-dados

Cuidado:

Apagar um PV pode afetar dados reais dependendo do tipo de volume, do provisionador e da política de reclaim.

Relação com outros manifestos

Um PV normalmente faz parte do conjunto de armazenamento do cluster.

Uso típico:

PersistentVolume
  ↓
PersistentVolumeClaim
  ↓
Pod / Deployment / StatefulSet

Em um projeto completo:

Namespace
  ├── PersistentVolumeClaim
  ├── ConfigMap
  ├── Secret
  ├── Deployment
  │   └── Pod monta PVC
  ├── Service
  └── Ingress

Cluster
  ├── PersistentVolume
  └── StorageClass

PV + PVC

PVC reivindica um PV compatível.

PV + StorageClass

PV pode ter storageClassName.

PVC com a mesma storageClassName pode fazer bind com ele.

PV + Pod

Pod normalmente não usa PV diretamente.

Pod monta PVC, e PVC está vinculado a PV.

PV + StatefulSet

StatefulSet normalmente cria PVCs por réplica.

Esses PVCs podem gerar PVs dinamicamente ou fazer bind com PVs existentes.

PV + ResourceQuota

ResourceQuota limita solicitações de armazenamento no namespace via PVC, não diretamente pelo PV.


Erros comuns

PV fica Available e PVC fica Pending

Possíveis causas:

  • storageClassName diferente;
  • accessModes incompatíveis;
  • PVC pede mais storage do que o PV oferece;
  • selector do PVC não bate com labels do PV;
  • volumeMode incompatível;
  • volumeName aponta para outro PV;
  • PV já está reservado por claimRef.

Verificar:

kubectl describe pvc app-web-dados -n meu-projeto
kubectl describe pv pv-app-web-dados

PVC não encontra PV por StorageClass errada

PV:

storageClassName: manual-nfs

PVC:

storageClassName: nfs

Isso não faz bind.

Corrigir para usar o mesmo nome.


Capacidade insuficiente

PV:

capacity:
  storage: 5Gi

PVC:

resources:
  requests:
    storage: 10Gi

O PVC não deve fazer bind porque o PV não atende ao tamanho solicitado.


AccessMode incompatível

PV:

accessModes:
  - ReadWriteOnce

PVC:

accessModes:
  - ReadWriteMany

O PVC não deve fazer bind porque o PV não oferece o modo pedido.


Volume local sem nodeAffinity

PV local sem nodeAffinity é configuração problemática.

Correto:

local:
  path: /mnt/dados/app
nodeAffinity:
  required:
    nodeSelectorTerms:
      - matchExpressions:
          - key: kubernetes.io/hostname
            operator: In
            values:
              - node-01

Usar hostPath como se fosse storage de produção

hostPath acessa um caminho no nó.

Problemas:

  • baixa portabilidade;
  • risco de segurança;
  • dependência do nó;
  • dados não são distribuídos;
  • pode quebrar se o Pod for para outro nó.

Prefira storage apropriado ou CSI quando possível.


Apagar PVC e perder dados com política Delete

Se o PV ou a StorageClass usa:

persistentVolumeReclaimPolicy: Delete

apagar o PVC pode apagar o volume real.

Antes de apagar PVC/PV, verifique:

kubectl get pv
kubectl describe pv NOME_DO_PV

PV Released não volta automaticamente para Available

Com política Retain, ao apagar o PVC o PV pode ficar:

Released

Isso indica que os dados ainda existem.

Cuidado:

  • o PV não fica automaticamente pronto para outro PVC;
  • o administrador precisa limpar dados e ajustar referência quando apropriado;
  • reutilizar sem limpeza pode expor dados antigos.

Usar PV manual quando StorageClass resolveria melhor

Se o cluster tem provisionamento dinâmico confiável, muitas vezes basta criar PVC.

Fluxo preferido:

PVC + StorageClass → PV criado automaticamente

PV manual é útil quando:

  • volume já existe;
  • storage é estático;
  • política exige controle manual;
  • o administrador precisa associar volume específico.

Checklist para uso em produção

Antes de aplicar um PersistentVolume em ambiente compartilhado:

  • nome claro;
  • labels claras;
  • annotations úteis;
  • capacidade representa o volume real;
  • accessModes compatível com o storage;
  • storageClassName compatível com PVC esperado;
  • volumeMode correto;
  • fonte de volume correta (nfs, csi, local, etc.);
  • persistentVolumeReclaimPolicy definida conscientemente;
  • política Delete não apagará dados importantes por acidente;
  • política Retain tem processo de limpeza/reuso definido;
  • mountOptions são válidas para o tipo de volume;
  • nodeAffinity definida para volume local;
  • Secrets referenciados existem quando o driver precisa;
  • PVC correspondente foi planejado;
  • backup foi planejado se os dados forem importantes;
  • impacto de apagar PVC/PV é conhecido;
  • hostPath foi evitado salvo necessidade controlada;
  • StorageClass dinâmica foi considerada antes de PV manual.

Resumo

Use PersistentVolume para representar armazenamento persistente disponível no cluster.

O PV controla:

  • capacidade do volume;
  • modos de acesso;
  • política de reclaim;
  • classe de armazenamento;
  • modo filesystem ou bloco;
  • fonte real do volume;
  • opções de montagem;
  • afinidade de nó;
  • estado de vínculo com PVC.

O PV não é:

  • o pedido do usuário;
  • o Pod;
  • a aplicação;
  • backup automático;
  • controle de CPU/memória;
  • configuração pequena;
  • segredo;
  • publicação de rede.

Para aplicação web comum com arquivos persistentes, o conjunto mínimo geralmente é:

PersistentVolume + PersistentVolumeClaim + Deployment + Service + Ingress

Quando há provisionamento dinâmico, muitas vezes o usuário cria apenas:

PersistentVolumeClaim

e o cluster cria o PV automaticamente por meio de uma StorageClass.

Para ambiente institucional compartilhado, o conjunto recomendado é:

StorageClass + PersistentVolume/PersistentVolumeClaim
+ Namespace + ResourceQuota + LimitRange + ServiceAccount + Role/RoleBinding
+ ConfigMap + Secret + Deployment + Service + Ingress + NetworkPolicy + PDB