DevOps Mind
Storage no Kubernetes – Revisão para a prova CKA
Quando comecei a estudar para a prova CKA (Certified Kubernetes Administrator), confesso que o tópico de storage eu sempre deixava para depois. Mas após passar alguns perrengues para resolver problemas com Volumes no k8s(Alô Kubecost!), percebi que dominar storage no K8s não é opcional – especialmente se você está se preparando para o CKA, onde representa 10% da prova. Neste artigo, vou revisar os três principais pontos que caem na prova: storage classes, tipos de volumes e persistent volumes.

Tópicos
O Que é Storage no Kubernetes?
Antes de mergulharmos nos detalhes, é importante entender o básico. No Kubernetes, storage é o mecanismo que permite que os dados das aplicações persistam mesmo após a reinicialização de um pod. Isso é crucial para bancos de dados, sistemas de arquivos e qualquer aplicação que precise manter estado.
Na documentação oficial do k8s é possível obter detalhes de todos elementos que compõem a parte de Storage: https://kubernetes.io/docs/concepts/storage
O Kubernetes oferece várias formas de gerenciar storage, desde volumes temporários até volumes persistentes. E é aqui que entram os três tópicos principais que vamos revisar:
- Implementar Storage Classes e Dynamic Volume Provisioning
- Configurar Volume Types, Access Modes e Reclaim Policies
- Gerenciar Persistent Volumes e Persistent Volume Claims
Vamos começar pelo primeiro.
Implementando Storage Classes e Dynamic Volume Provisioning
Uma das coisas que mais me ajudou a entender storage classes foi pensar nelas como “templates” para provisionar volumes dinamicamente. Em vez de criar manualmente cada Persistent Volume (PV), você define uma StorageClass que o Kubernetes usa para provisionar volumes sob demanda quando um Persistent Volume Claim (PVC) é criado.
Por exemplo, imagine que você está usando um cluster na AWS. Você pode criar uma StorageClass no k8s para provisionar volumes EBS automaticamente:
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: aws-ebs
provisioner: kubernetes.io/aws-ebs
parameters:
type: gp2
reclaimPolicy: Delete
volumeBindingMode: Immediate
Aqui, o provisioner
define o plugin de provisionamento (no caso, AWS EBS), e o reclaimPolicy
define o que acontece com o volume quando o PVC é deletado (Delete
ou Retain
). O volumeBindingMode
controla quando o volume é provisionado (Immediate
ou WaitForFirstConsumer
).
Dica para a prova: Saiba criar e aplicar uma StorageClass usando kubectl
. Pratique também a criação de PVCs que referenciem uma StorageClass específica.
Dica extra
Outro ponto importante para saber sobre StorageClass
No k8s o StorageClass local-storage
não suporta Dynamic Volume Provisioning porque ele usa o provisionador "kubernetes.io/no-provisioner"
. Esse provisionador indica que os volumes precisam ser criados manualmente pelo administrador, ao contrário de provisionadores como "kubernetes.io/aws-ebs"
ou "kubernetes.io/gce-pd"
, que criam volumes dinamicamente quando um PVC é solicitado.
Isso significa que, se um PVC for criado referenciando local-storage
, o Kubernetes não criará um novo PV automaticamente. O administrador deve garantir que os volumes já existam e estejam disponíveis para serem vinculados ao PVC.
Dynamic Volume Provisioning no Kubernetes
Primeiro, vamos entender por que precisamos dele. Em vez de criar manualmente cada PV (Persistent Volume), o dynamic provisioning permite que volumes sejam criados automaticamente quando um PVC é solicitado.
Vantagens do Provisionamento Dinâmico:
✔️ Reduz a necessidade de criar PVs manualmente.
✔️ Escala automaticamente conforme a demanda de armazenamento.
✔️ Suporta diferentes backends de armazenamento (AWS, GCP, Azure, etc.).
Aqui está um exemplo completo:
- Primeiro, criamos uma StorageClass que será responsável pelo provisionamento dinâmico:
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: fast-dynamic
provisioner: kubernetes.io/aws-ebs # Mude conforme seu ambiente
parameters:
type: gp2
fsType: ext4
encrypted: "true"
reclaimPolicy: Delete
volumeBindingMode: WaitForFirstConsumer # Importante para performance
- Agora, criamos um PVC que usará esta StorageClass:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: dynamicpvc
spec:
storageClassName: fast-dynamic # Referencia a StorageClass criada
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
- Por fim, um Pod que usa este PVC:
apiVersion: v1
kind: Pod
metadata:
name: dynamic-pod
spec:
containers:
- name: app
image: nginx
volumeMounts:
- name: dynamic-storage
mountPath: /data
volumes:
- name: dynamic-storage
persistentVolumeClaim:
claimName: dynamicpvc
Para verificar se está funcionando:
# Verifica a StorageClass
kubectl get sc fast-dynamic
# Verifica o PVC
kubectl get pvc dynamicpvc
# Verifica o PV criado dinamicamente
kubectl get pv
Pontos importantes que caem na prova CKA:
- A StorageClass precisa ter um
provisioner
válido para seu ambiente volumeBindingMode: WaitForFirstConsumer
é uma best practice para otimizar recursosreclaimPolicy
define o que acontece com o volume quando o PVC é deletado- Os
parameters
variam conforme o provisioner usado
Em ambientes cloud, você pode ter diferentes StorageClasses para diferentes necessidades:
# StorageClass para alta performance
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: premium-dynamic
annotations:
storageclass.kubernetes.io/is-default-class: "false"
provisioner: kubernetes.io/aws-ebs
parameters:
type: io1
iopsPerGB: "50"
encrypted: "true"
---
# StorageClass para uso geral
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: standard-dynamic
annotations:
storageclass.kubernetes.io/is-default-class: "true"
provisioner: kubernetes.io/aws-ebs
parameters:
type: gp2
encrypted: "true"
Para testar em um ambiente local como Minikube:
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: local-dynamic
provisioner: k8s.io/minikube-hostpath
reclaimPolicy: Delete
volumeBindingMode: WaitForFirstConsumer
Na prova CKA, é importante saber:
- Como criar uma StorageClass para provisionamento dinâmico
- Como definir uma StorageClass como default
- Como verificar se o provisionamento dinâmico está funcionando
- Como troubleshoot problemas comuns (verificar eventos, logs do provisioner)
Resumo – Funcionamento do Provisionamento Dinâmico
1️⃣ O PVC solicita um volume.
2️⃣ O Kubernetes verifica se há um PV manualmente disponível para essa solicitação.
3️⃣ Se não há um PV estático compatível, ele usa a StorageClass que cria o PV de forma dinâmica
.
4️⃣ O Kubernetes cria automaticamente um PV no AWS EBS (ou outro provisionador configurado).
5️⃣ O volume é vinculado ao PVC e pode ser montado pelos Pods.
Configurando Volume Types, Access Modes e Reclaim Policies
Outro ponto importante é entender os tipos de volumes, modos de acesso e políticas de reclaim. Vamos falar de cada um:
Tipos de Volumes
Kubernetes suporta vários tipos de volumes, como:
- AWS EBS: Para clusters na AWS.
- NFS: Para sistemas de arquivos em rede.
- HostPath: Usa um diretório do nó (não recomendado para produção).
- EmptyDir: Volume temporário que dura enquanto o pod estiver ativo.
Modos de Acesso
Os modos de acesso definem como o volume pode ser montado:
- ReadWriteOnce (RWO): Apenas um nó pode montar o volume para leitura e escrita.
- ReadOnlyMany (ROX): Vários nós podem montar o volume apenas para leitura.
- ReadWriteMany (RWX): Vários nós podem montar o volume para leitura e escrita.
Reclaim Policies
A política de reclaim define o que acontece com o volume quando o PVC é deletado:
- Delete: O volume é removido.
- Retain: O volume é mantido, mas precisa ser limpo manualmente.
Exemplo prático:
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-example
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
hostPath:
path: /mnt/data
Dica para a prova: Entenda as diferenças entre os modos de acesso e quando usar cada política de reclaim. Isso pode cair em questões teóricas ou práticas.
Gerenciando Persistent Volumes e Persistent Volume Claims
Persistent Volumes (PVs) e Persistent Volume Claims (PVCs) são o coração do sistema de storage no Kubernetes. Um PV é um recurso de armazenamento no cluster, enquanto um PVC é uma solicitação de armazenamento feita por um usuário.
Criando um PVC
Aqui está um exemplo de PVC que solicita 5Gi de armazenamento:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: my-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
storageClassName: aws-ebs
Quando você aplica esse PVC, o Kubernetes tenta encontrar um PV que corresponda aos requisitos ou provisiona um novo volume usando a StorageClass especificada.
Vinculando PVs e PVCs
Primeiramente, vamos criar o PV, considerando que não temos um Storage Class a ser utilizado e vamos gerenciar os Persistent Volumes manualmente:
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-example
spec:
storageClassName: manual
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
hostPath:
path: "/var/log/webapp"
Este manifesto cria um PV chamado pv-example
com as seguintes características:
- Armazena 10Gi de dados
- Usa um caminho no host (
/var/log/webapp
) como backend de armazenamento - Apenas um Pod pode escrever ao mesmo tempo (
ReadWriteOnce
) - Associa-se à StorageClass
manual
, o que significa que não usa provisionamento dinâmico
Se você já tem um PV criado manualmente, pode vincular um PVC a ele usando o campo volumeName
:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: my-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
volumeName: pv-example
Exemplo de Pod usando o PVC:
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- name: my-container
image: nginx
volumeMounts:
- mountPath: "/usr/share/nginx/html"
name: my-storage
volumes:
- name: my-storage
persistentVolumeClaim:
claimName: my-pvc
Dica para a prova: Pratique a criação de PVs e PVCs, e entenda como eles se relacionam. Saiba também como verificar o status de um PVC usando kubectl get pvc
.
Exercício prático – Integrando todos os conceitos
Para fixar o conhecimento, recomendo criar um ambiente de laboratório e praticar os seguintes cenários:
- Crie uma StorageClass para provisionamento dinâmico.
- Crie um PVC que use essa StorageClass.
- Monte o PVC em um pod e verifique se o volume foi provisionado corretamente.
- Teste diferentes políticas de reclaim e modos de acesso.
Vou criar todos os manifestos necessários para um exercício prático completo de storage no Kubernetes. Vamos usar o Minikube como ambiente de laboratório.
- Primeiro, a StorageClass para provisionamento dinâmico:
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: lab-storage
provisioner: k8s.io/minikube-hostpath
reclaimPolicy: Delete
volumeBindingMode: Immediate
- PVC usando a StorageClass:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: lab-pvc
spec:
storageClassName: lab-storage
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
- Pod que monta o volume:
apiVersion: v1
kind: Pod
metadata:
name: lab-pod
spec:
containers:
- name: app
image: nginx
volumeMounts:
- name: data-volume
mountPath: "/data"
command: ["/bin/sh", "-c"]
args: ["while true; do echo $(date) >> /data/test.txt; sleep 5; done"]
volumes:
- name: data-volume
persistentVolumeClaim:
claimName: lab-pvc
Aplicando todos os manifestos e validando o estado dos recursos:

- Para testar diferentes políticas de reclaim, aqui está uma StorageClass com Retain:
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: lab-storage-retain
provisioner: k8s.io/minikube-hostpath
reclaimPolicy: Retain
volumeBindingMode: WaitForFirstConsumer
- PVC com modo de acesso ReadOnlyMany:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: lab-pvc-rom
spec:
storageClassName: lab-storage
accessModes:
- ReadOnlyMany
resources:
requests:
storage: 1Gi
- Deployment para testar múltiplos pods lendo o mesmo volume:
apiVersion: apps/v1
kind: Deployment
metadata:
name: lab-deployment
spec:
replicas: 2
selector:
matchLabels:
app: lab-app
template:
metadata:
labels:
app: lab-app
spec:
containers:
- name: app
image: nginx
volumeMounts:
- name: shared-data
mountPath: "/data"
readOnly: true
volumes:
- name: shared-data
persistentVolumeClaim:
claimName: lab-pvc-rom
Comandos para testar e verificar:
# Criar recursos
kubectl apply -f storage-class.yaml
kubectl apply -f pvc.yaml
kubectl apply -f pod.yaml
# Verificar status
kubectl get sc
kubectl get pvc
kubectl get pv
kubectl get pods
# Verificar se o volume está funcionando
kubectl exec lab-pod -- ls /data
kubectl exec lab-pod -- cat /data/test.txt
# Testar diferentes políticas
kubectl delete pod lab-pod
kubectl delete pvc lab-pvc
kubectl get pv # Se reclaimPolicy=Retain, o PV permanecerá
# Testar modo ReadOnlyMany
kubectl apply -f deployment.yaml
kubectl get pods
kubectl describe pods # Verificar se os volumes montaram corretamente
Exercícios adicionais que você pode fazer:
- Tente criar um PVC com tamanho maior que o disponível e observe o comportamento
- Delete um PVC com reclaimPolicy=Retain e veja o que acontece com o PV
- Tente montar um volume ReadWriteOnce em múltiplos pods e observe o resultado
- Crie um pod com volume ReadOnlyMany e tente escrever nele
Dominar o tópico de storage no Kubernetes é essencial não apenas para a prova CKA, mas também para o dia a dia de um administrador de clusters. Revisamos os principais conceitos, como storage classes, tipos de volumes, modos de acesso e persistent volumes, além de práticas que vão te ajudar a se preparar para a prova.
Siga revisando os conteúdos para a prova CKA, veja o post abaixo sobre o tópico prova CKA para o item “Monitor cluster and application resource usage“: