No capítulo anterior o cluster ficou Ready. Agora vamos colocar algo dentro dele.
A tentação é criar um pod direto. Resista. Pod é efêmero: se ele morrer, ninguém recria. O nível certo para uma aplicação é o Deployment, que cria um ReplicaSet, que cria os pods.
Deployment -> ReplicaSet -> Pod(s)
O caminho do kubectl apply
Quando você roda:
kubectl apply -f app.yaml
Acontece isto:
kubectllê o YAML e envia para o API server.- O API server valida e grava no etcd.
- O controller manager vê o Deployment e cria um ReplicaSet.
- O ReplicaSet vê que faltam pods e cria os objetos Pod.
- O scheduler escolhe um nó para cada pod.
- O kubelet do nó baixa a imagem e inicia o container.
- O CNI atribui IP ao pod.
- O kube-proxy atualiza as regras de Service.
Se algo falhar em qualquer etapa, o estado aparece em kubectl get e kubectl describe. Aprender a ler esses dois comandos vale mais do que decorar YAML.
Um Deployment completo
Crie app.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
labels:
app: web
spec:
replicas: 3
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: web
image: nginx:1.27
ports:
- containerPort: 80
resources:
requests:
cpu: 50m
memory: 64Mi
limits:
cpu: 200m
memory: 128Mi
readinessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 2
periodSeconds: 5
livenessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 10
periodSeconds: 10
Aplique:
kubectl apply -f app.yaml
kubectl get deploy,rs,pods -o wide
Você deve ver 3 pods Running e Ready.
Por que labels e selector?
O Deployment não procura pods pelo nome. Ele seleciona por label. O selector.matchLabels precisa casar com template.metadata.labels. Se não casar, o Deployment não encontra os pods e o cluster reclama. É um dos erros mais comuns de YAML.
O Service
Pods nascem e morrem com IPs diferentes. O Service dá um nome e um IP estável:
apiVersion: v1
kind: Service
metadata:
name: web
spec:
selector:
app: web
ports:
- port: 80
targetPort: 80
type: ClusterIP
kubectl apply -f service.yaml
kubectl get svc web
Teste de dentro do cluster:
kubectl run curl --image=curlimages/curl:8.10.1 --rm -it --restart=Never -- \
curl -s http://web
ClusterIP só é acessível dentro do cluster. Para acesso externo, usamos NodePort, LoadBalancer ou Ingress — o capítulo 09 cobre isso.
Para testar localmente sem expor nada:
kubectl port-forward svc/web 8080:80
# em outro terminal
curl -I http://localhost:8080
Rollout e rollback
Atualize a imagem:
kubectl set image deployment/web web=nginx:1.28
kubectl rollout status deployment/web
kubectl rollout history deployment/web
Se a nova versão quebrar:
kubectl rollout undo deployment/web
kubectl rollout status deployment/web
O Kubernetes mantém ReplicaSets antigos para rollback. Isso é o revisionHistoryLimit.
Escala
kubectl scale deployment/web --replicas=5
kubectl get pods -l app=web
Em produção, quem escala sozinho é o HPA (Horizontal Pod Autoscaler), que veremos na temporada 3. Escala manual é ótima para entender; HPA é para operar.
Probes: o que separa “rodando” de “pronto”
- readinessProbe: o pod pode receber tráfego?
- livenessProbe: o container está vivo? Se falhar, o kubelet reinicia.
- startupProbe: para aplicações lentas; segura liveness até o app iniciar.
Uma aplicação Java com Spring Boot pode levar 90–120 segundos para subir. Se a liveness tem initialDelaySeconds: 10, o kubelet mata o container antes de ele terminar — e você entra em CrashLoopBackOff sem nenhum erro de aplicação. Já vi isso acontecer em um deploy real; o log mostrava o app iniciando normalmente e sendo morto.
Regra prática:
- readiness: generosa no começo, curta depois.
- liveness: só depois que o app comprovadamente inicia.
- startup: ideal para apps lentas.
Diagnóstico: os três estados que você vai ver
Pending
O pod foi criado, mas não foi agendado.
kubectl describe pod <pod> | tail -30
Causas: recursos insuficientes, nodeSelector/affinity impossível, taint sem toleration, PVC não vinculado.
ImagePullBackOff / ErrImagePull
O nó não conseguiu baixar a imagem.
kubectl describe pod <pod> | grep -A5 Events
Causas: imagem/tag inexistente, registry privado sem imagePullSecret, rate limit do Docker Hub, ou imagem removida do registry.
Caso real: uma imagem que existia apenas em cache em dois nós falhou quando o pod foi reagendado para um terceiro. O cluster estava “funcionando” até o dia em que o nó mudou. Imagem precisa estar disponível no registry (ou em todos os nós), não só em cache.
CrashLoopBackOff
O container inicia e morre repetidamente.
kubectl logs <pod>
kubectl logs <pod> --previous
kubectl describe pod <pod> | tail -20
Causas: configuração ausente, variável de ambiente errada, dependência indisponível, permissão, OOMKilled (veja Last State: OOMKilled).
Limpando
kubectl delete -f service.yaml
kubectl delete -f app.yaml
Checklist
- [ ] Entendi Deployment → ReplicaSet → Pod.
- [ ] Sei que
selectorelabelsprecisam casar. - [ ] Criei um Deployment com 3 réplicas e um Service.
- [ ] Testei com
port-forwarde/oucurlinterno. - [ ] Fiz rollout e rollback.
- [ ] Configurei readiness e liveness com tempos realistas.
- [ ] Sei diagnosticar
Pending,ImagePullBackOffeCrashLoopBackOff.
Glossário
- ReplicaSet: garante N pods de uma versão.
- Service: nome/IP estável para um conjunto de pods.
- ClusterIP: IP interno do Service.
- NodePort: porta exposta em cada nó.
- readinessProbe: define se o pod entra no balanceamento.
- livenessProbe: define se o container deve ser reiniciado.
- OOMKilled: container morto por excesso de memória.
Próximo
Agora que você sabe criar e diagnosticar um deploy, vamos usar o kubeadm para montar o cluster de verdade, com control plane e workers separados.
Próximo: Curso Kubernetes 04 — kubeadm por dentro: certificados, static pods e o join
Continuar a ler
Leia também
KubernetesKubernetes de Verdade — do zero ao cluster em produção
Uma trilha prática para entender, montar e operar um cluster Kubernetes — do primeiro pod ao failover do Postgres.
4 min de leitura
KubernetesCurso Kubernetes 28 — DR e capstone: provar que o cluster volta
RPO, RTO e drills reais: cenários de desastre, runbook, restore medido e o capstone que fecha o curso com um cluster que se recupera.
5 min de leitura
KubernetesCurso Kubernetes 27 — SLO/SLI, on-call e postmortem blameless
O que prometer, como medir e o que fazer quando o erro estoura: SLI, SLO, error budget, alertas que acordam alguém e postmortem sem caça às bruxas.
4 min de leitura
Comentários
Ainda sem comentários
Seja o primeiro a compartilhar sua opinião sobre este artigo.

Deixe um comentário