Introdução
Os containers possuem sistemas de arquivos graváveis, mas esse armazenamento está vinculado ao próprio container. Os volumes do Kubernetes oferecem aos Pods uma maneira mais clara de gerenciar arquivos. Alguns volumes são efêmeros e destinados a dados temporários dentro de um único Pod. Outros volumes são persistentes e podem manter os dados disponíveis mesmo quando um Pod é excluído e recriado.
Neste laboratório, você utilizará um volume emptyDir para dados temporários locais do Pod e, em seguida, criará um PersistentVolumeClaim (PVC) e o montará em dois Pods diferentes para comprovar que os dados sobrevivem à substituição do Pod.
Preparar um Namespace para Prática de Volumes
Nesta etapa, você preparará um namespace limpo e confirmará que o cluster possui os recursos de armazenamento necessários para este laboratório.
Comece em /home/labex/project. Você escreverá os manifestos de Pod e PVC neste diretório.
mkdir -p /home/labex/project
cd /home/labex/project
Verifique se o servidor da API do Kubernetes está acessível. Se a VM acabou de iniciar e o nó ainda não está pronto, aguarde alguns segundos e execute o comando novamente.
kubectl get nodes --request-timeout=5s
A saída esperada inclui:
NAME STATUS ROLES AGE VERSION
labex-v135 Ready control-plane ... v1.35...
Aguarde até que o Pod de rede do cluster esteja pronto (Ready):
kubectl wait --namespace kube-system --for=condition=Ready pod -l k8s-app=calico-node --timeout=120s
Saída esperada:
pod/calico-node-... condition met
Este laboratório utiliza um PersistentVolumeClaim posteriormente. Confirme se a StorageClass padrão standard existe e, em seguida, aguarde o Pod do provisionador de armazenamento do minikube.
kubectl get storageclass standard
kubectl wait --namespace kube-system --for=condition=Ready pod/storage-provisioner --timeout=120s
A saída esperada inclui:
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ...
standard (default) k8s.io/minikube-hostpath Delete Immediate ...
pod/storage-provisioner condition met
Crie um namespace chamado ckad-prep-volumes:
kubectl create namespace ckad-prep-volumes
Defina este namespace como o namespace do contexto atual:
kubectl config set-context --current --namespace=ckad-prep-volumes
Confirme o namespace atual:
kubectl config view --minify --output 'jsonpath={..namespace}'; echo
Saída esperada:
ckad-prep-volumes
Utilizar emptyDir para Dados Temporários Locais do Pod
Nesta etapa, você criará um Pod que utiliza um volume emptyDir.
Um volume emptyDir começa vazio quando o Pod é criado. Os containers no mesmo Pod podem utilizá-lo como espaço de trabalho compartilhado, cache ou diretório de trabalho temporário. Ele não foi projetado para preservar dados após a remoção do Pod.
Crie o arquivo emptydir-pod.yaml:
cat > emptydir-pod.yaml <<'EOF'
apiVersion: v1
kind: Pod
metadata:
name: scratch-worker
labels:
app: scratch-worker
spec:
terminationGracePeriodSeconds: 0
volumes:
- name: scratch-space
emptyDir: {}
containers:
- name: worker
image: busybox:1.36
command:
- /bin/sh
- -c
- 'echo scratch-ready > /scratch/status.txt; sleep 3600'
volumeMounts:
- name: scratch-space
mountPath: /scratch
EOF
Aplique o manifesto:
kubectl apply -f emptydir-pod.yaml
Saída esperada:
pod/scratch-worker created
Aguarde até que o Pod esteja pronto (Ready):
kubectl wait --for=condition=Ready pod/scratch-worker --timeout=120s
Saída esperada:
pod/scratch-worker condition met
Leia o arquivo do volume emptyDir montado:
kubectl exec scratch-worker -c worker -- cat /scratch/status.txt
Saída esperada:
scratch-ready
Inspecione o tipo de volume do Pod. A expressão jsonpath imprime o nome do volume e confirma que se trata de um emptyDir.
kubectl get pod scratch-worker -o 'jsonpath={.spec.volumes[0].name}{" emptyDir\n"}'
Saída esperada:
scratch-space emptyDir
Gravar Dados em um PersistentVolumeClaim
Nesta etapa, você criará um PersistentVolumeClaim (PVC) e o montará em um Pod de escrita.
Um PersistentVolumeClaim, ou PVC, é uma solicitação de armazenamento feita por uma aplicação. Neste laboratório, a StorageClass standard fornece armazenamento dinamicamente para a solicitação. Seu Pod monta a solicitação em /data e grava um arquivo lá.
Crie o arquivo notes-pvc.yaml:
cat > notes-pvc.yaml <<'EOF'
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: notes-pvc
spec:
accessModes:
- ReadWriteOnce
storageClassName: standard
resources:
requests:
storage: 1Mi
EOF
Aplique o PVC:
kubectl apply -f notes-pvc.yaml
Saída esperada:
persistentvolumeclaim/notes-pvc created
Aguarde até que o PVC esteja no estado Bound:
kubectl wait --for=jsonpath='{.status.phase}'=Bound pvc/notes-pvc --timeout=120s
Saída esperada:
persistentvolumeclaim/notes-pvc condition met
Crie um Pod de escrita que monta o PVC:
cat > pvc-writer-pod.yaml <<'EOF'
apiVersion: v1
kind: Pod
metadata:
name: pvc-writer
labels:
app: pvc-writer
spec:
terminationGracePeriodSeconds: 0
volumes:
- name: notes-storage
persistentVolumeClaim:
claimName: notes-pvc
containers:
- name: writer
image: busybox:1.36
command:
- /bin/sh
- -c
- 'echo persistent-note > /data/note.txt; sleep 3600'
volumeMounts:
- name: notes-storage
mountPath: /data
EOF
Aplique o Pod de escrita e aguarde até que ele esteja pronto (Ready):
kubectl apply -f pvc-writer-pod.yaml
kubectl wait --for=condition=Ready pod/pvc-writer --timeout=120s
Saída esperada:
pod/pvc-writer created
pod/pvc-writer condition met
Leia o arquivo da montagem do PVC:
kubectl exec pvc-writer -c writer -- cat /data/note.txt
Saída esperada:
persistent-note
Reutilizar o PVC em um Novo Pod
Nesta etapa, você excluirá o Pod de escrita, criará um novo Pod de leitura que monta o mesmo PVC e confirmará que o arquivo ainda está lá.
Esta é a diferença prática entre dados temporários locais do Pod e armazenamento persistente. O Pod de escrita pode ser removido, mas o PVC permanece. Um novo Pod pode montar a mesma solicitação e ler os dados.
Exclua o Pod de escrita:
kubectl delete pod pvc-writer
Saída esperada:
pod "pvc-writer" deleted
Crie um Pod de leitura que monta o mesmo PVC:
cat > pvc-reader-pod.yaml <<'EOF'
apiVersion: v1
kind: Pod
metadata:
name: pvc-reader
labels:
app: pvc-reader
spec:
terminationGracePeriodSeconds: 0
volumes:
- name: notes-storage
persistentVolumeClaim:
claimName: notes-pvc
containers:
- name: reader
image: busybox:1.36
command:
- /bin/sh
- -c
- 'cat /data/note.txt; sleep 3600'
volumeMounts:
- name: notes-storage
mountPath: /data
EOF
Aplique o Pod de leitura e aguarde até que ele esteja pronto (Ready):
kubectl apply -f pvc-reader-pod.yaml
kubectl wait --for=condition=Ready pod/pvc-reader --timeout=120s
Saída esperada:
pod/pvc-reader created
pod/pvc-reader condition met
Leia o arquivo do novo Pod:
kubectl exec pvc-reader -c reader -- cat /data/note.txt
Saída esperada:
persistent-note
Inspecione o PVC. Ele ainda deve estar Bound, mesmo que o Pod de escrita original tenha sido removido.
kubectl get pvc notes-pvc
A saída esperada inclui:
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE
notes-pvc Bound ... 1Mi RWO standard <unset> ...
Resumo
Você utilizou um volume emptyDir para dados temporários locais do Pod, criou um PVC para armazenamento persistente, gravou dados através de um Pod, excluiu esse Pod e leu os mesmos dados a partir de um novo Pod que montou a mesma solicitação. Agora você sabe quando utilizar armazenamento efêmero para dados temporários do Pod e quando solicitar armazenamento persistente para dados que devem sobreviver à substituição do Pod.


