transmissão ao vivo · o gp do kubernetes básico, etapa por etapa

Kubernetes narrado
direto do paddock.

Boa tarde, Brasil! Boa tarde, paddock! Oito etapas, da largada (por que esse esporte existe) à reta final do autoscaling, onde o cluster passa a pilotar sozinho. Em jogo: sair daqui sabendo montar, operar, curar e escalar um cluster de verdade. O farol vai apagar — e quem assume o volante da narrativa é o piloto. Com vocês.

Cada conceito de Kubernetes lido como um piloto lê a telemetria: o problema que cada peça resolve, a analogia de F1 tecnicamente honesta, o YAML comentado linha a linha, os comandos com a saída esperada e um mão na massa por etapa. No final, os sites gratuitos pra praticar em clusters reais no navegador.

O quadro de-para — cole isto no volante

A mesma analogia vale do início ao fim do guia. Não tente decorar esta tabela agora — ela é o mapa do circuito, não a prova: siga direto para a Etapa 01 e volte aqui sempre que uma analogia aparecer no texto.

KubernetesFórmula 1
ContainerO carro + kit da equipe: isolado na sua garagem, compartilhando a infraestrutura do circuito
Imagem de containerA especificação de montagem do carro — replicável em qualquer circuito do calendário
Máquina virtual (VM)Levar a fábrica inteira da equipe para cada GP
Kubernetes (orquestrador)A operação completa de mureta + garagem
Estado desejadoO target passado no rádio: você declara o alvo, o sistema mantém
ClusterA equipe montada no fim de semana de GP
Control plane (master node)A mureta (pit wall)
Worker nodeA garagem/box onde os carros são montados e operados
API ServerO engenheiro de corrida — todo rádio passa por ele, sem exceção
kubectlO botão de rádio do piloto
kubeconfigO paddock pass + a frequência de rádio da equipe
etcdO sistema central de dados da equipe (setup sheets + estado de tudo)
kubeletO chefe de mecânicos de cada garagem
kube-proxyO sinaleiro do pit lane, direcionando cada carro ao box certo
MinikubeO simulador da fábrica
PodO carro (chassi montado e rodando)
IP do PodA posição do carro na pista — muda o tempo todo
LabelsAs etiquetas de rastreamento FIA nas peças e no carro (servem para selecionar)
AnnotationsAs anotações do engenheiro no caderno de debrief (servem para humanos)
Manifesto YAMLA folha de especificação do carro, versionada
Imperativo vs. declarativoOrdem direta no rádio ("box, box") vs. plano de corrida escrito antes do GP
ServiceO pit box: posição fixa no pit lane, atende qualquer carro com a etiqueta da equipe
ClusterIPCanal interno de rádio — só a equipe ouve
NodePortPortão de serviço numerado do autódromo
LoadBalancerA entrada oficial do autódromo, com bilheteria
ConfigMapA folha de set-up — separada do chassi
SecretOs mapas de motor confidenciais
ReplicaSetA regra do chefe de equipe: "N carros prontos, sempre" (e a virada de madrugada dos mecânicos)
DeploymentO programa de desenvolvimento: pacotes de upgrade, spec por spec
Rolling updateIntroduzir o upgrade em um carro de cada vez
RollbackVoltar para a spec anterior (o assoalho antigo que funcionava)
emptyDirO quadro branco da garagem — apagado quando o fim de semana acaba
hostPathGuardar dados no caixote de frete daquele circuito
PVCA requisição de armazenamento do engenheiro de dados
PVO storage físico da fábrica que atende a requisição
StorageClassO catálogo de tipos de storage (trackside rápido vs. datacenter da fábrica)
ProbesAs checagens de telemetria + radio check
Liveness probeTelemetria mudou → reset completo do carro
Readiness probeO semáforo do box: segura o carro fora da pista, sem desmontar nada
Startup probeO procedimento de fire-up da PU: nada é cobrado antes do motor aquecer
HPAA mureta de estratégia alinhando mais carros conforme a carga (uma F1 sem o limite de 2 carros)
metrics-serverOs sensores de telemetria — sem eles a mureta não enxerga nada
resources.requestsA alocação declarada de energia/combustível — a base de qualquer percentual

Onde as analogias quebram (piloto que esconde limitação do carro quebra no muro):

  • ReplicaSet (Etapa 05): na F1, reposição de carro só entre sessões, e o regulamento limita a 2 carros por equipe. O ReplicaSet repõe em segundos, a qualquer momento, em qualquer quantidade. A "virada de madrugada dos mecânicos" vale para o mecanismo (remontar da especificação), não para o tempo nem para o limite.
  • HPA (Etapa 08): escalar réplicas não tem paralelo direto no grid de 2 carros — a analogia declarada é uma "endurance sem limite de inscrições". O comportamento da mureta (reagir à telemetria, respeitar piso e teto) se mantém fiel.
  • Service (Etapa 04): o pit box real atende um carro por vez; o Service balanceia tráfego contínuo entre N réplicas simultâneas. A parte fiel é o endereço fixo + a seleção por etiqueta.
  • Pod multi-container (Etapa 03): o carro com PU + MGU-K ilustra "unidades distintas compartilhando sistemas", mas containers de um Pod são processos independentes que podem ser trocados individualmente na especificação.
SEU PROGRESSO0 de 8 etapas

Etapa 01 motivação + setup

Por que o Kubernetes existe

APAGARAM-SE AS LUZES! É largada no GP do Kubernetes! Primeira curva, primeira freada, e a pergunta que abre todo campeonato: por que esse esporte existe? A resposta desta etapa sustenta as outras sete. Segura comigo.

Pense na demanda de um fim de semana de GP: o site da equipe, o timing, o streaming — tudo dorme durante a semana e explode no domingo da corrida. E tem o carro que voa no simulador e não anda na pista: o clássico "na minha máquina funciona". Todo projeto esbarra nesses dois problemas — e o Kubernetes automatiza a solução dos dois.

Como funciona

A peça comum das duas soluções é o container. Uma máquina virtual é como levar a fábrica inteira para cada GP — prensa de fibra de carbono, túnel de vento, escritório, tudo embarcado no avião. Um container é o carro com o kit da equipe: cada equipe tem sua garagem isolada, seus segredos, suas peças — mas a estrutura do circuito (o prédio dos boxes, a energia, o pit lane, ou seja, o kernel do sistema operacional) é compartilhada entre as dez equipes. A Cadillac, estreando neste ano, não construiu um autódromo para correr — chegou com seus caixotes e plugou na infraestrutura existente.

Em termos técnicos: a VM carrega um sistema operacional completo (gigabytes, minutos para subir); o container compartilha o kernel do SO hospedeiro e leva só os arquivos, binários e bibliotecas que o app precisa (megabytes, segundos). Uma imagem de container é um ambiente inteiro, replicável em qualquer lugar — a especificação de montagem que garante que o carro embarcado para Suzuka é idêntico ao que rodou em Melbourne. Adeus "na minha máquina funciona".

Só que containers resolvem o problema do ambiente e criam outro: com dezenas ou centenas deles, alguém precisa criá-los, destruí-los, vigiar a saúde e recriar o que falhar. Fazer isso na mão não escala — é como pedir para uma pessoa só operar os dois carros, a telemetria e o pit stop. O Kubernetes (K8s) é o orquestrador que assume essas tarefas: a operação completa de mureta + garagem.

A filosofia dele é a do engenheiro de corrida ditando target: ele não manda instrução a cada curva — declara "target +0.3 por volta, modo de energia 6" e todo o sistema trabalha sozinho para manter. No K8s você declara o estado desejado ("quero 3 cópias disso rodando") e ele mantém a realidade de acordo — inclusive de madrugada, quando um container morre. A mureta nunca dorme.

Os conceitos-chave desta etapa

Container ≠ VM

VM = hardware virtual + SO completo (a fábrica embarcada). Container = só o necessário do app, compartilhando o kernel do hospedeiro (o carro na garagem do circuito). Muito mais leve.

Escala horizontal

Mais cópias da aplicação dividindo a carga (é o que o K8s automatiza). Vertical = mais CPU/RAM na mesma máquina — alinhar mais carros vs. motor maior num carro só.

Cluster e Pod

O K8s organiza máquinas (nós) em clusters. Os containers rodam agrupados em Pods — a menor unidade gerenciada. Cluster = a equipe no fim de semana; Pod = o carro.

kubectl

A ferramenta de linha de comando que conversa com a API REST do cluster. É o seu botão de rádio (detalhes na Etapa 02).

Minikube

Um cluster K8s de 1 nó rodando na sua máquina. O simulador da fábrica: feito para estudo, sem risco de bater o carro de verdade — é o laboratório deste guia.

Estado desejado

A filosofia do K8s: você declara o que quer, ele faz acontecer e mantém. Caiu? Ele recria sozinho. O target no rádio.

Montando o laboratório (passo a passo)

# 1. Instale o Docker Desktop (docker.com) — no Linux, use o Docker
# Engine (docs.docker.com/engine/install) — e confirme:
$ docker -v
Docker version 27.x
# 2. Instale o kubectl (kubernetes.io/docs/tasks/tools) e confirme:
$ kubectl version --output=yaml
# 3. Instale o Minikube (minikube.sigs.k8s.io/docs/start) e suba o cluster:
$ minikube start
😄 minikube v1.33 on Windows 11
✨ Using the docker driver
🏄 Done! kubectl is now configured to use "minikube"
# 4. Confirme que o cluster está de pé:
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
minikube Ready control-plane 1m v1.30.x
# 5. Cluster vazio = sucesso:
$ kubectl get pods
No resources found in default namespace.

💡 A primeira execução do minikube start baixa a imagem do cluster e demora alguns minutos. É normal — é o fire-up do simulador, e simulador frio nunca liga instantâneo.

Comandos essenciais desta etapa

$minikube start # sobe o cluster local de 1 nó
$minikube stop # para o cluster sem apagar nada
$kubectl get nodes # lista os nós e o status
$kubectl get pods # lista os pods do namespace atual

Mão na massa

O menor exercício possível: prove que seu laboratório está vivo — o equivalente ao installation lap.

  1. Rode minikube start e aguarde o "Done!".
  2. Rode kubectl get nodes — observe: o nó minikube com STATUS Ready. Se aparecer NotReady, aguarde 1 minuto e repita.
  3. Rode kubectl get pods — observe: "No resources found". Cluster vazio e pronto é exatamente o ponto de partida da próxima etapa — garagem limpa antes do carro chegar.
  4. Bônus: rode minikube stop e depois kubectl get nodes — veja a mensagem de erro de conexão. Suba de novo com minikube start. Agora você sabe o que "cluster fora do ar" parece no terminal — é o rádio mudo, e rádio mudo em corrida é a pior sensação que existe.

Dica: Se o minikube start falhar, a causa mais comum é o Docker Desktop não estar aberto (no Linux, o serviço parado: sudo systemctl start docker). Suba o Docker primeiro e tente de novo. (Todo simulador tem um disjuntor que alguém esqueceu de ligar.)

Anota aí: Container é um ambiente leve e replicável — o carro que anda igual em qualquer circuito; Kubernetes é o engenheiro de corrida do estado desejado — você declara o target, ele garante.

Setor 1 no verde! Laboratório de pé, simulador ligado, cluster respondendo — largada limpíssima. Agora vem a parte que todo estreante subestima: aprender a falar no rádio. Etapa 02 na sequência — não sai daí.

Etapa 02 o botão de rádio

kubectl e a API: como você comanda o cluster

Segunda etapa e o traçado aperta: de que adianta ter o carro na garagem se você não sabe apertar o botão do rádio? A F1 vive desse canal — foi nele que Kimi Räikkönen imortalizou o "deixa comigo, eu sei o que estou fazendo" em Abu Dhabi 2012, e venceu. Hoje é você quem aprende a dar as ordens.

Seu cluster está de pé, mas é uma caixa fechada. Como mandar ordens? Como investigar quando algo der errado, sem acesso "físico" ao container? Na pista o piloto tem o mesmo problema: a 300 km/h, não dá pra descer e abrir o capô — tudo que ele sabe do carro chega pelo rádio e pela telemetria.

Como funciona

Tudo no Kubernetes passa pela API REST do nó master. O kubectl é o cliente dessa API: cada comando que você digita vira uma requisição HTTP (GET, POST, PUT, DELETE) contra o cluster. Na F1, o piloto não fala com o mecânico do pneu dianteiro esquerdo nem com a fábrica — fala com uma pessoa: o engenheiro de corrida. Toda mensagem passa por esse canal único, que valida, registra e repassa para quem executa. O kubectl é o seu botão de rádio; o API Server é o engenheiro de corrida: nada acontece no cluster sem passar por ele.

O caminho de um comando: você digita kubectl get pods → o kubectl lê o arquivo kubeconfig (endereço do API Server, credenciais e contexto do cluster atual — o Minikube configura isso sozinho; pense nele como o paddock pass com a frequência de rádio da equipe já sintonizada) → e dispara um GET /api/v1/pods contra o API Server. A resposta volta formatada no seu terminal.

A API é dividida em grupos: o "core" tem os recursos fundamentais (pods, services, replicasets); outros grupos cuidam de segurança, armazenamento, autoscaling — como os departamentos da equipe: chassi, aero, PU, estratégia. Como é REST puro, dá para chamar de qualquer linguagem — Python, Go, Java, C# — o que abre portas para automação.

Existem dois jeitos de trabalhar: o imperativo (kubectl run nginx --image=nginx — a ordem direta, o "box, box, box" no rádio: rápido, decisivo, bom para testes) e o declarativo (escrever um YAML e rodar kubectl apply -f arquivo.yaml — o plano de corrida escrito no sábado à noite: documentado, revisado, versionado). Em projetos reais o declarativo domina, porque o arquivo é versionável no Git — nenhuma equipe séria improvisa a estratégia inteira no rádio.

Os verbos que resolvem 90% do dia

get

Consultar: lista recursos e o status de cada um. kubectl get pods, get svc, get nodes... É a olhada no painel de timing.

create / run / apply

Criar: run cria um pod imperativo; apply -f aplica um YAML (declarativo).

delete

Remover: kubectl delete pod nginx. Cuidado — pode afetar quem depende do recurso.

describe

Detalhar: configuração + a seção Events. Primeira parada quando algo trava — o histórico de telemetria da sessão, evento por evento.

logs

Ver o que o container está imprimindo. Seu melhor amigo no debug: é ouvir o rádio do carro direto.

exec

Abrir um shell dentro do container: kubectl exec -it <pod> -- /bin/sh. O mecânico plugando o laptop no carro.

Exemplo estruturado: ciclo de vida de um Pod

# Cria um pod chamado "nginx" a partir da imagem nginx:1.14.2 do Docker Hub
$ kubectl run nginx --image=nginx:1.14.2 --port=80
pod/nginx created
# Acompanhe até o status ficar Running (o primeiro estado é ContainerCreating)
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx 1/1 Running 0 30s
# Detalhes + eventos (veja a linha "Pulling image" na seção Events)
$ kubectl describe pod nginx
# O que o container está imprimindo
$ kubectl logs nginx
# Limpeza
$ kubectl delete pod nginx
pod "nginx" deleted

💡 Se o status ficar em ImagePullBackOff, o cluster não conseguiu baixar a imagem — confira o nome/tag e sua internet. É o caixote de peças que não chegou no circuito: sem a spec certa, o carro não monta.

Comandos essenciais desta etapa

$kubectl run nginx --image=nginx:1.14.2 --port=80 # cria um pod imperativo
$kubectl describe pod <nome> # detalhes + Events (troubleshooting)
$kubectl logs <nome> # saída do container
$kubectl exec -it <nome> -- /bin/sh # shell dentro do container
$kubectl delete pod <nome> # remove o pod

Mão na massa

Execute o ciclo completo e force o primeiro erro da sua vida no K8s — todo piloto precisa da primeira rodada para calibrar o limite:

  1. Rode a sequência do exemplo acima (run → get → describe → logs → delete). Observe no describe a seção Events: as linhas Pulling image, Created container, Started container contam a história do pod em ordem — igual ao replay da telemetria, quadro a quadro.
  2. Agora crie um pod quebrado de propósito: kubectl run quebrado --image=nginx:versao-que-nao-existe.
  3. Rode kubectl get pods — observe o status ImagePullBackOff (ou ErrImagePull).
  4. Rode kubectl describe pod quebrado — observe nos Events a mensagem explicando que a imagem não foi encontrada. Você acabou de praticar o fluxo de debug de verdade.
  5. Limpe: kubectl delete pod quebrado.

Dica: Grave este fluxo: get pods (qual o status?) → describe pod (o que dizem os Events?) → logs (o que o app diz?). Essa sequência resolve a maioria dos problemas. É o protocolo pós-problema do piloto: painel de timing → histórico de telemetria → rádio do carro.

Anota aí: Tudo no K8s é uma chamada à API REST; o kubectl é o seu botão de rádio e o API Server é o engenheiro de corrida — e quando algo trava, o caminho é sempre get → describe → logs.

Rádio calibrado e — repararam? — o primeiro erro forçado e diagnosticado sem pânico. Esse setor separa quem aperta botão de quem conversa com a equipe. E atenção, porque agora vem o miolo técnico do circuito: a anatomia do cluster e a folha de especificação. Não pisca.

Etapa 03 arquitetura + labels

A anatomia do cluster — e a menor unidade dele: o Pod

Entramos no complexo de curvas mais técnico do traçado — aqui não adianta coragem, é precisão. E a história do esporte não perdoa spec fora do lugar: em 1999 a Ferrari quase perdeu uma vitória na Malásia por milímetros nas barge boards. Especificação não é burocracia, é resultado. Hoje você escreve a sua primeira folha de especificação.

Na Etapa 02 você criou um pod com um comando imperativo. Funciona, mas tem dois furos: você não sabe o que exatamente foi criado nem onde — e se amanhã precisar recriar aquele pod idêntico, vai depender da memória. Nenhuma equipe monta um carro de memória: existe folha de especificação para tudo, do ângulo da asa ao torque de cada parafuso.

Como funciona

Um cluster é um grupo de máquinas (nodes) trabalhando juntas, com papéis bem definidos — é a equipe montada no fim de semana de GP. O Pod é a menor unidade que o Kubernetes gerencia — no nosso mapa, o Pod é o carro: um "envelope" com um ou mais containers que dividem rede e armazenamento.

Quatro fatos sobre Pods: (1) um Pod representa um processo em execução e pode ter mais de um container dividindo o mesmo IP e volumes — como PU e MGU-K no mesmo carro; (2) Pods são efêmeros — nascem e morrem o tempo todo; o carro que correu em Silverstone hoje será desmontado até o último parafuso antes de Spa, o que permanece é a especificação (guarde esta frase: ela é a raiz das Etapas 04, 05 e 06); (3) cada Pod ganha um IP interno do cluster — a posição do carro na pista: existe, é real, mas muda o tempo todo; (4) Pods são descritos em YAML — a folha de especificação do carro.

Para organizar dezenas de Pods existem os rótulos e as anotações. Na F1, cada componente do carro — PU, turbo, MGU-K, câmbio — carrega uma etiqueta de rastreamento lacrada pela FIA: é por ela que o sistema sabe qual motor está em qual carro; a etiqueta serve para IDENTIFICAR E SELECIONAR. Já o caderno de debrief do engenheiro ("piloto reportou vibração na curva 7") é informação para humanos — ninguém filtra componentes por anotação de caderno. Labels são a etiqueta FIA (é por label que um Service acha seus Pods — você verá na Etapa 04); annotations são o caderno de debrief (autor, documentação, auditoria — NÃO participam de seleção). Essa diferença é o que cai em prova.

Quem faz o quê dentro do cluster

Master node

A mureta (pit wall): gerencia o cluster e decide onde executar os Pods.

Worker node

As garagens: executam os Pods e demais recursos. É onde o carro é montado e roda.

etcd

O sistema central de dados da equipe: banco distribuído com a configuração e o estado do cluster — as setup sheets de tudo.

kubelet

O chefe de mecânicos de cada garagem: agente em cada node que gerencia os Pods locais.

kube-proxy

O sinaleiro do pit lane: encaminha o tráfego de rede para os Pods certos.

API Server

O engenheiro de corrida — tudo que o kubectl faz passa por aqui (Etapa 02).

O primeiro YAML — decore este esqueleto

apiVersion: v1 # versão da API do K8s p/ este objeto
kind: Pod # o TIPO de objeto criado
metadata: # dados SOBRE o objeto
name: meu-pod
labels: # rótulos: chave-valor p/ SELECIONAR
app: myapp
ambiente: estudo
annotations: # anotações: metadados livres (docs)
autor: "Davi Gomes"
spec: # a ESPECIFICAÇÃO: o que roda dentro
containers:
- name: meu-container
image: nginx:1.14.2
ports:
- containerPort: 80

💡 Todo objeto K8s segue esse esqueleto: apiVersion + kind + metadata + spec. Muda o kind e o conteúdo do spec — o resto é sempre igual. É como o regulamento técnico: quem entende a estrutura de um artigo lê todos os outros.

Comandos essenciais desta etapa

$kubectl apply -f arquivo.yaml # cria/atualiza pelo YAML
$kubectl get pods --show-labels # lista exibindo rótulos
$kubectl get pods -l app=myapp # filtra por rótulo
$kubectl delete -f arquivo.yaml # remove o que o arquivo criou

Mão na massa

  1. Salve o YAML acima como meu-pod.yaml e aplique com kubectl apply -f meu-pod.yaml.
  2. Rode kubectl get pods --show-labels — observe os dois labels na última coluna.
  3. Rode kubectl get pods -l app=myapp e depois kubectl get pods -l app=outra-coisa — observe: o primeiro encontra o pod, o segundo retorna vazio. Etiqueta certa, carro encontrado; etiqueta errada, garagem vazia.
  4. Adicione um label em tempo real: kubectl label pod meu-pod time=devops e confirme com --show-labels.
  5. NÃO delete o pod — ele será o alvo do Service na próxima etapa. (Se deletou, é só aplicar o YAML de novo — essa é a graça do declarativo: a folha de especificação remonta o carro idêntico.)

Dica: Labels = seleção operacional (o K8s usa). Annotations = documentação (humanos usam). Autor de um Pod? Annotation. Agrupar Pods de uma app? Label. Etiqueta FIA vs. caderno de debrief.

Anota aí: Todo objeto K8s é apiVersion + kind + metadata + spec — a folha de especificação do carro; e labels são a etiqueta FIA pela qual tudo no cluster encontra tudo.

Que setor limpo, senhoras e senhores! Esqueleto de YAML no bolso, etiquetas dominadas — e repara que o guia armou a jogada: esse label app: myapp que ficou vivo na pista é a ultrapassagem preparada da próxima etapa. Vamos para o pit box!

Etapa 04 rede + configuração

Services: endereço fixo pra Pods que mudam

Volta 4 e o problema clássico do pit lane aparece: como achar um carro que muda de posição o tempo todo? Quem acompanha F1 sabe que endereço e procedimento no box não são detalhe — Christijan Albers que o diga, saindo do box em 2007 com a mangueira de combustível ainda pendurada. Endereço fixo e configuração fora do chassi: é disso que esta etapa vive.

Lembra do fato nº 2 da Etapa 03? Pods são efêmeros: cada Pod novo nasce com um IP diferente. Tentar falar com eles pelo IP é como achar um carro pela posição na pista — na volta 12 ele está em P4, na volta 30 em P7. E tem o segundo problema: configuração dentro da imagem obriga a rebuildar a cada mudança — um chassi novo toda vez que a mureta pede meio grau a mais de asa.

Como funciona

Problema 1 → Service. O Service é o pit box da equipe: a posição do box no pit lane é fixa a temporada inteira — todo mundo sabe onde fica o box da Ferrari. Qual carro entra nele a cada volta muda (o de Leclerc, o de Hamilton, um chassi montado ontem) — e quem precisa do box não se importa: o endereço é o mesmo, e o box atende qualquer carro que carregue a etiqueta da equipe.

O fluxo: uma requisição chega no Service (IP e nome fixos) → o Service seleciona os Pods pelo label selector (o mecanismo da Etapa 03 — a etiqueta FIA de novo) → e distribui o tráfego de forma balanceada entre as réplicas saudáveis. O nome do Service vira um hostname interno do cluster: se o Service chama "auth-service", qualquer Pod acessa http://auth-service — mesmo que os Pods por trás troquem de IP mil vezes.

Problema 2 → ConfigMap. O ConfigMap é a folha de set-up separada do chassi: asa, pressões, mapas — nada disso é soldado no carro; está numa folha que os mecânicos aplicam antes do carro sair da garagem. Você guarda os valores num objeto central e injeta de 3 formas: variáveis de ambiente (a mais comum, via envFrom), arquivos montados (ótimo para configs longas) ou argumentos de linha de comando. Mudou a config? Atualiza o ConfigMap — a imagem continua a mesma. Meio grau de asa não exige chassi novo.

Os 3 tipos de Service

ClusterIP (padrão)

IP interno, só dentro do cluster. O canal interno de rádio: só a equipe ouve. Use para comunicação entre serviços (ex.: API ↔ banco).

NodePort

Porta fixa (30000–32767) aberta no nó. O portão de serviço numerado do autódromo — o jeito de expor algo no Minikube.

LoadBalancer

Balanceador externo com IP público. A entrada oficial do autódromo, com bilheteria — o tipo de produção na nuvem (AWS, GCP, Azure).

Os YAMLs — repare no selector

# app.yaml — salve o Service neste arquivo
apiVersion: v1
kind: Service
metadata:
name: meu-service # vira o hostname interno
spec:
type: NodePort # troque p/ ClusterIP (interno) ou LoadBalancer (nuvem)
selector: # ← O ELO: procura Pods com este label
app: myapp
ports:
- protocol: TCP
port: 80 # porta em que o Service escuta
targetPort: 80 # porta do container que recebe
nodePort: 30080 # porta exposta no nó (só NodePort)

💡 O selector do Service casa com o label do Pod (app: myapp) — exatamente o meu-pod que você criou na Etapa 03. É assim que ele sabe pra quem mandar o tráfego: o box lê a etiqueta do carro que está chegando.

Comandos essenciais desta etapa

$kubectl get svc # lista os Services
$minikube service <nome> --url # URL de acesso a um NodePort
$kubectl get configmap # lista os ConfigMaps
$kubectl exec <pod> -- env # confere variáveis injetadas

Mão na massa

  1. Com o meu-pod da Etapa 03 rodando (label app: myapp), salve o YAML do Service como app.yaml e aplique.
  2. Rode minikube service meu-service --url e abra a URL no navegador — observe a página de boas-vindas do nginx. Você acessou um Pod efêmero por um endereço estável — encontrou o carro pelo box, não pela posição na pista.
  3. Teste o elo: delete o pod (kubectl delete pod meu-pod) e recarregue o navegador — observe o erro (box vazio, nenhum carro com a etiqueta da equipe). Recrie com kubectl apply -f meu-pod.yaml e recarregue — voltou, sem tocar no Service. O box nem se mexeu.
  4. Aplique o ConfigMap + pod (kubectl apply -f configmap-pod.yaml) e rode kubectl exec pod-config -- env — observe MENSAGEM e MODO na lista de variáveis. A folha de set-up foi aplicada no carro.

Dica: Regra de ouro: exponha o mínimo. Banco de dados = ClusterIP (canal interno — estratégia de corrida não vaza no rádio aberto). Só a porta de entrada do sistema vira NodePort/LoadBalancer. Pra senhas e chaves, o irmão seguro do ConfigMap é o Secret — os mapas de motor que nem todo mecânico da própria equipe conhece.

Anota aí: Service é o pit box: endereço fixo para carros (Pods) que mudam, achando-os pela etiqueta (label); ConfigMap é a folha de set-up — configuração fora do chassi (imagem).

Setor no roxo! Pod acessado por endereço estável, configuração fora do chassi — e você ainda provou o elo deletando o carro e vendo o box impassível no mesmo lugar. Mas atenção, porque agora vem a curva que decide corrida: o que acontece quando o carro PARA na pista?

Etapa 05 auto-cura + escala

Auto-cura e escala: ReplicaSets e Deployments

É AQUI que separa os pontuadores do resto do grid! Hoje mesmo, volta 46, o carro da Red Bull calou e o Verstappen assistiu ao fim da prova do muro — zero ponto. Em produção, o seu Pod único morrendo às 3h da manhã é exatamente essa cena. Auto-cura e caminho de volta — a etapa mais importante do guia começa AGORA.

Até aqui você criou Pods na mão — ótimo pra aprender, mas pense em Silverstone hoje: o Verstappen parou na volta 46 e acabou — não há substituto no meio da corrida. Em produção, seu único Pod morrendo de madrugada é isso: site fora do ar até alguém acordar. E quando lançar a 2.0, como trocar a versão sem derrubar o serviço? E se ela vier com um bug catastrófico, como voltar rápido?

Como funciona

ReplicaSet — o chefe de equipe do número. Você declara "replicas: 3" e ele monitora os Pods pelo label selector (a etiqueta FIA, de novo!). Caiu um? Ele detecta que a contagem baixou e cria outro em segundos, sem você pedir. É a regra inegociável do chefe de equipe — "N carros prontos, sempre": o piloto destrói o chassi no sábado, os mecânicos viram a madrugada e no domingo tem um carro inteiro no grid, remontado da especificação. É a auto-cura do Kubernetes — o "estado desejado" da Etapa 01 mantido de verdade.

Aqui a analogia quebra — e vale registrar: na F1, a reposição só acontece entre sessões, e o regulamento limita cada equipe a 2 carros. O ReplicaSet não tem parc fermé nem regulamento: repõe o Pod em segundos, a qualquer hora, em qualquer quantidade. Pense no K8s como uma endurance sem limite de inscrições — e a "madrugada dos mecânicos" dura trinta segundos.

Deployment — o gestor de specs. Ele embrulha o ReplicaSet e adiciona o programa de desenvolvimento: Rolling Update (ao trocar a imagem, sobe réplicas novas e desliga as antigas gradualmente — o serviço nunca fica fora do ar, como o upgrade que entra em um carro enquanto o outro segue com a spec antiga), Rollback (kubectl rollout undo volta pra anterior em segundos — o assoalho novo não anda, o carro volta com a spec anterior; a Ferrari chegou em Barcelona este ano com pacote novo e o Hamilton venceu, mas se o pacote piorasse o carro, voltavam pra spec de Mônaco sem drama) e escala manual (kubectl scale --replicas=5: cinco carros no grid).

Os YAMLs de ReplicaSet e Deployment são quase idênticos, mas no dia a dia usamos quase sempre o Deployment, pelo controle de versão — ninguém gerencia só o número de carros; gerencia-se o número E a spec de cada um. O Deployment cria e gerencia o ReplicaSet por baixo dos panos.

O que cada um garante

ReplicaSet

N réplicas rodando SEMPRE. Caiu uma, nasce outra em segundos — a madrugada dos mecânicos comprimida. Seleção por label selector.

Rolling Update

Troca de versão gradual: sobe as novas, desliga as antigas. Zero downtime — upgrade introduzido em um carro por vez.

Rollback

A versão nova quebrou? kubectl rollout undo volta pra anterior em segundos — de volta pra spec que funcionava.

O Deployment completo + ciclo de vida

apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-fiap
spec:
replicas: 3 # quero 3 cópias, sempre
selector:
matchLabels:
app: nginx-app # gerencio os Pods com este label...
template: # ...e este é o "molde" de cada Pod
metadata:
labels:
app: nginx-app # tem que casar com o selector ↑
spec:
containers:
- name: nginx
image: nginx:1.14.2 # trocar esta versão dispara o rolling update
ports:
- containerPort: 80

💡 Repare: o template é literalmente o esqueleto de Pod da Etapa 03, embutido no Deployment. Nada aqui é novo — é composição: a folha de especificação do carro, anexada à ordem do chefe de equipe ("três carros desta spec, sempre").

Comandos essenciais desta etapa

$kubectl scale deployment <nome> --replicas=5 # escala manual
$kubectl set image deployment/<nome> ctn=img:tag # dispara rolling update
$kubectl rollout status deployment/<nome> # acompanha a troca
$kubectl rollout history deployment/<nome> # lista revisões
$kubectl rollout undo deployment/<nome> # rollback!

Mão na massa

O momento que as arquibancadas esperavam: o pit stop do guia. Mas aqui, diferente da troca de pneus, pressa é inimiga — o valor do exercício está em OBSERVAR cada estado mudando no terminal. Calma e olhos abertos.

  1. Aplique o deployment.yaml e confirme os 3 pods Running — três carros na pista, mesma spec.
  2. Delete um pod na mão (copie um nome real do kubectl get pods) e rode kubectl get pods de novo, rápido — observe o substituto em ContainerCreating. Você tentou violar o estado desejado e o cluster corrigiu.
  3. Rode o rolling update para nginx:1.16.1 e acompanhe com kubectl rollout status — observe a mensagem de sucesso. Upgrade introduzido carro a carro, ninguém saiu da pista.
  4. Quebre de propósito com a imagem nginx:nao-existe — observe no kubectl get pods os pods antigos Running segurando o serviço e os novos em ImagePullBackOff.
  5. Execute kubectl rollout undo deployment/nginx-fiap e confirme com kubectl rollout history — observe as revisões listadas. Você fez um rollback de produção em um comando — voltou pra spec da classificação sem perder a corrida.

Dica: Faça o teste da auto-cura pelo menos uma vez: matar um pod e ver o substituto nascer — a madrugada dos mecânicos comprimida em segundos. É o momento em que o Kubernetes "clica" na cabeça.

Anota aí: Ninguém cria Pod avulso em produção — carro sem equipe não termina corrida: o Deployment garante N réplicas (auto-cura), troca specs sem tirar ninguém da pista (rolling update) e volta pra spec anterior em um comando (rollback).

E o público de pé nas arquibancadas! Você MATOU um Pod e o cluster o remontou antes do replay terminar. Setor decisivo completado no verde. Agora, a pergunta que assombra qualquer equipe de ponta: e os DADOS?

Etapa 06 persistência de dados

Volumes: dados que sobrevivem ao Pod

Entramos no setor de alta velocidade — e no assunto que não aparece nos highlights, mas ganha campeonatos: dados. A Williams dominou os anos 90 porque transformava telemetria em desenvolvimento antes de todo mundo. Carro se desmonta; histórico, jamais. Etapa 06 valendo.

Pods são efêmeros — e a Etapa 05 deixou isso radical, com pods morrendo e nascendo em rolling updates. Ótimo pro app, catastrófico pra dados: o carro que correu hoje será desmontado até o monocoque, mas os gigabytes de telemetria já estão na fábrica antes do piloto tirar o capacete. Se o Pod do PostgreSQL for recriado num update, todos os pedidos da Black Friday somem junto — dados de verdade não podem viver no filesystem de um container.

Como funciona

O Kubernetes resolve isso com uma cadeia de 4 conceitos: Volume, PersistentVolume (PV), PersistentVolumeClaim (PVC) e StorageClass (SC). Memorize pela operação de dados da equipe: o PVC é a REQUISIÇÃO do engenheiro de dados ("preciso de 1Gi, leitura e escrita por um nó"); o PV é o STORAGE físico da fábrica que atende a requisição (NFS, EBS da AWS, hostPath...); a StorageClass é o CATÁLOGO de tipos de storage (o servidor trackside rápido? o datacenter da fábrica?).

O Pod só referencia o PVC — o carro não sabe (nem precisa saber) em qual rack da fábrica a telemetria dele está guardada. Essa separação é o que permite o mesmo YAML rodar no Minikube e na AWS — o mesmo procedimento de dados funciona em Interlagos e em Suzuka. No Minikube, a StorageClass "standard" já provisiona PVs automaticamente: você faz a requisição (PVC) e o storage (PV) aparece.

Modos de acesso do PVC (quem pode montar o volume): ReadWriteOnce (leitura e escrita por UM nó — o caso típico de banco de dados; só a garagem da equipe escreve nos próprios dados), ReadOnlyMany (só leitura, vários nós — assets estáticos; como o feed de timing da FIA: todas as equipes leem, ninguém altera) e ReadWriteMany (leitura e escrita por vários nós — precisa de NFS ou similar).

A cadeia de armazenamento

emptyDir

Vive e morre com o Pod. O quadro branco da garagem: anotações da sessão, apagadas quando o fim de semana acaba. Pra dado temporário e compartilhamento entre containers do Pod.

hostPath

Monta diretório do NÓ no container. O caixote de frete daquele circuito: dev ok; produção, cuidado (amarra o Pod ao nó).

PVC → PV

A requisição (Claim) casa com o storage (Volume). Dados sobrevivem à morte do Pod — a telemetria na fábrica.

StorageClass

O catálogo: provisiona PVs automaticamente por perfil. No Minikube, a classe "standard" já faz isso.

Prove a persistência: escreva, destrua, leia de volta

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: meu-pvc
spec:
accessModes:
- ReadWriteOnce # um nó lê e escreve (típico de banco)
resources:
requests:
storage: 1Gi # quanto disco eu quero
# no Minikube, a StorageClass "standard" provisiona o PV sozinha

Comandos essenciais desta etapa

$kubectl get pvc # pedidos de volume (Bound = ok)
$kubectl get pv # discos persistentes do cluster
$kubectl delete pvc <nome> # remove o pedido (e libera o disco)

Mão na massa

  1. Aplique o PVC e rode kubectl get pvc — observe o STATUS Bound: sua requisição foi atendida por um PV criado automaticamente (confirme com kubectl get pv).
  2. Execute a sequência completa do exemplo: escrever o arquivo → deletar o pod → recriar o pod → ler o arquivo. Observe o "sobrevivi!" voltar. Esse é o contrato do PVC — o carro morre, a telemetria fica.
  3. Experimento extra (o contraste que ensina): repita o teste trocando o volume por emptyDir — ao recriar o Pod, o arquivo terá sumido. Essa é a diferença entre o quadro branco da garagem e o servidor da fábrica, sentida na prática.

Dica: Dado importante SEMPRE em PVC. Se os dados sumiram após um restart, aposto que estavam em emptyDir ou no filesystem do container — alguém anotou a estratégia da corrida no quadro branco e a faxina passou.

Anota aí: PVC é a requisição, PV é o storage, StorageClass é o catálogo — e dado que importa mora sempre atrás de um PVC: o carro é desmontado, a telemetria nunca.

"SOBREVIVI!" — e o arquivo voltou! O carro foi desmontado até o monocoque e a telemetria estava lá, intacta, na fábrica. Setor no verde. Mas segura na cadeira, porque agora vem a pegadinha mais traiçoeira do circuito: o carro que anda... mas não anda.

Etapa 07 saúde do app

Probes: como o cluster sabe que seu app está vivo

Atenção que esta curva é CEGA! Hoje, em Silverstone, o mundo inteiro viu: Antonelli largou na pole, cravou 1:31.777 — a volta mais rápida da prova — e cruzou a linha em DÉCIMO SEXTO. Cinquenta e duas voltas na pista, e nada saudável. E os mais antigos lembram de Senna em Interlagos, 1991: o carro andava, mas só restava a sexta marcha. É exatamente esse buraco que as probes fecham.

O Antonelli esteve na pista, rodando, as 52 voltas — e mesmo assim algo claramente não estava saudável. No cluster é idêntico: seu app entra em deadlock às 3h da manhã, o processo continua de pé (pro Kubernetes está tudo Running), mas nenhuma requisição é respondida. A auto-cura da Etapa 05 só recria pods que MORREM; ela não enxerga pods vivos porém travados — o carro que anda, mas não anda.

Como funciona

As probes são verificações de saúde declaradas no manifesto do Pod. É a telemetria + o radio check: a equipe não confia no fato de o carro estar se movendo — ela verifica canais específicos em intervalos regulares: pressão de óleo, temperatura da PU, resposta do piloto no rádio. Não basta o carro estar na pista; ele precisa responder aos estímulos.

Como a probe verifica (3 mecanismos): httpGet (o kubelet faz um GET num endpoint tipo /health e espera 200 OK — o mais comum; é o radio check: "me dá um ok, piloto"), tcpSocket (testa se a porta aceita conexão — pra serviços que não falam HTTP; a portadora do rádio abre, mesmo sem conversa) e exec (executa um comando dentro do container; código de saída 0 = saudável — o mecânico plugando o laptop e rodando o diagnóstico).

Boas práticas da aula: use as três probes juntas em produção; use endpoints diferentes pra cada probe (canais de telemetria separados — pressão de óleo não se mede no sensor de freio); comece pelas configurações padrão e ajuste intervalos só quando o app pedir; monitore as falhas de probe (ex.: com Prometheus) — elas são o primeiro sinal de problema, como aquele tremor na telemetria duas voltas antes de a peça quebrar.

As 3 probes e o que acontece na falha

Liveness

"Está vivo?" Falhou → o Pod é REINICIADO. O "faça o ciclo completo — desliga e liga o carro". Pra apps que travam e só voltam com restart.

Readiness

"Pronto pra tráfego?" Falhou → SAI do balanceador, sem restart. O semáforo vermelho do box: segurado na garagem, ninguém o desmonta. Pra apps que carregam dados antes.

Startup

"Terminou de subir?" Enquanto roda, SEGURA as outras. O fire-up da PU: ninguém cobra tempo de volta com motor frio. Pra apps lentos no boot.

Pod com as 3 probes + sabotagem didática

apiVersion: v1
kind: Pod
metadata:
name: exemplo-probes
spec:
containers:
- name: app
image: exemplo:latest
ports:
- containerPort: 80
livenessProbe: # falhou → REINICIA o pod
httpGet:
path: /health
port: 80
periodSeconds: 10 # verifica a cada 10s
timeoutSeconds: 5
failureThreshold: 3 # 3 falhas seguidas → reinicia (3 é o padrão)
readinessProbe: # falhou → SAI do balanceador
httpGet:
path: /ready # boa prática: endpoint separado
port: 80
periodSeconds: 5
startupProbe: # segura as outras até o app subir
httpGet:
path: /startup
port: 80
initialDelaySeconds: 120 # app lento: espera 2min
periodSeconds: 30

💡 Este YAML é ilustrativo — a imagem exemplo:latest é fictícia. O experimento executável está na aba seguinte.

Comandos essenciais desta etapa

$kubectl get pods -w # assiste mudanças em tempo real
$kubectl describe pod <nome> # Events mostram as falhas de probe

Mão na massa

  1. Aplique o liveness-exec.yaml e rode kubectl get pods -w — observe a coluna RESTARTS subir sozinha a cada ~35-45s. Cada incremento é o kubelet mandando o "desliga e liga o carro" pra um Pod que parou de responder na telemetria.
  2. Em outro terminal, rode kubectl describe pod liveness-exec — observe nos Events o par Warning Unhealthy + Normal Killing. Aprenda a reconhecer essa dupla: em produção, ela é o diagnóstico de probe falhando.
  3. Limpe: kubectl delete pod liveness-exec.

Dica: Running NÃO significa saudável. O Antonelli rodou as 52 voltas de Silverstone com pole e volta mais rápida no bolso — e terminou em P16. Carro na pista não é carro competitivo; processo de pé não é app funcionando. É exatamente por isso que as probes existem.

Anota aí: Liveness falhou = desliga e liga o carro (reinicia); Readiness falhou = semáforo vermelho do box (sai do balanceador sem reiniciar); Startup = fire-up da PU (segura as duas até o app terminar de aquecer).

RESTARTS subindo sozinho na tela — você sabotou o sensor e viu a mureta mandar o reset, três leituras confirmadas, sem pânico. Poucos setores ensinam tanto com tão pouco YAML. E agora, a reta final do circuito: o cluster vai aprender a pilotar sozinho.

Etapa 08 escala automática

HPA: escala automática baseada em métricas

ÚLTIMA ETAPA, bandeirada à vista! E que fecho de prova: a mureta assumindo a estratégia em tempo real. Foi assim que Ross Brawn venceu a Hungria em 1998 — Schumacher voando e uma estratégia de três paradas recalculada com a corrida em andamento. Hoje, quem lê e reage é o HPA — e o ciclo do estado desejado, aberto lá na Etapa 01, se fecha diante dos seus olhos.

Volte ao problema da Etapa 01: a demanda explode no domingo da corrida. Você já sabe escalar na mão (kubectl scale, Etapa 05) — mas vai ficar de plantão no terminal ajustando réplicas a cada pico? Às 2h da manhã também? Nenhuma mureta funciona assim: a estratégia reage à corrida em tempo real, com base em telemetria. O ciclo precisa se fechar: o cluster deve medir a carga e escalar sozinho.

Como funciona

O Horizontal Pod Autoscaler (HPA) monitora métricas dos Pods (CPU, memória...) e ajusta o número de réplicas entre um mínimo e um máximo que você define. É a mureta de estratégia com poder de alinhar mais carros conforme a carga da corrida — lembrando o combinado da Etapa 05: aqui a F1 trava em 2 carros, então pense numa endurance sem limite de inscrições. O ritmo apertou além do alvo → alinha mais carros (até o teto); a corrida acalmou → recolhe gradualmente.

O funcionamento: o HPA compara a utilização dos Pods com o alvo configurado (ex.: manter a média de CPU em 70%). Passou → cria réplicas (até o máximo). Caiu → remove (até o mínimo), economizando recurso. O scale down é propositalmente lento (~5min de estabilidade) pra não ficar "pistonando" com variações rápidas — mesma razão pela qual a mureta não muda a estratégia a cada nuvem no radar: espera o padrão se confirmar, sem desmontar a operação no primeiro safety car.

Métricas suportadas: CPU (a mais comum), memória, métricas personalizadas do app (requisições/s, fila), métricas externas (ex.: Prometheus) e E/S de disco. A métrica certa depende do perfil do app — como escolher a estratégia pelo que o carro degrada: pneu em Barcelona, freio em Montreal.

Dois pré-requisitos que pegam todo mundo: (1) o cluster precisa do metrics-server pra ler CPU/memória — no Minikube: minikube addons enable metrics-server. Sem sensores no carro, a mureta não enxerga nada. (2) O container PRECISA declarar resources.requests.cpu, porque "70% de CPU" significa 70% DO QUE O POD PEDIU — como a alocação de energia do ERS por volta: "usei 70%" só faz sentido contra uma alocação declarada. Sem requests, o HPA mostra <unknown> e não escala.

O que o HPA entende

CPU / Memória

As métricas clássicas. % calculada sobre o resources.requests do container — o percentual da alocação declarada, nunca um número absoluto solto.

Métricas custom

Do seu app (req/s, fila) ou externas (Prometheus). Pra escalar pelo que importa — cada pista degrada uma coisa diferente.

min / max

Você sempre define o piso e o teto de réplicas. O HPA trabalha dentro da faixa, como a estratégia dentro do regulamento.

Deployment + HPA + Service + teste de carga

apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-hpa
spec:
replicas: 1 # começa com 1; o HPA assume daqui
selector:
matchLabels:
app: nginx-hpa
template:
metadata:
labels:
app: nginx-hpa
spec:
containers:
- name: nginx
image: nginx:1.14.2
resources: # SEM requests o HPA não calcula %
requests:
cpu: "100m" # 100 milicores = 0,1 CPU
limits:
cpu: "200m"

Comandos essenciais desta etapa

$minikube addons enable metrics-server # pré-requisito do HPA
$kubectl get hpa -w # assiste o HPA reagir à carga
$kubectl top pods # CPU/memória por pod
$kubectl autoscale deployment <n> --cpu-percent=70 --min=1 --max=10 # cria HPA imperativo

Mão na massa

Volta rápida final do fim de semana — todos os setores juntos numa tacada só:

  1. Ative o metrics-server e aplique os três YAMLs (Deployment, HPA, Service). Rode kubectl get hpa — observe os targets: se aparecer <unknown>, aguarde ~1min (sensor recém-instalado não dá dado antes da primeira volta).
  2. Suba o gerador de carga num terminal e kubectl get hpa -w em outro — observe o percentual de CPU disparar acima de 70% e a coluna REPLICAS subir. Se estacionar abaixo do alvo, use o plano B da aba de carga. Confirme com kubectl get pods: pods novos nasceram sem nenhum comando seu — a mureta alinhou carros sozinha, lendo a telemetria.
  3. Pare a carga (Ctrl+C) e continue assistindo — observe que as réplicas demoram ~5min pra encolher. Essa lentidão é proposital (ninguém desmonta a garagem no primeiro momento de calmaria).
  4. Use kubectl top pods durante o teste pra ver a métrica crua que alimenta o HPA — a telemetria antes da decisão de estratégia.

Dica: kubectl get hpa mostrando <unknown> nos targets? Ou o metrics-server não está ativo, ou o container não declarou resources.requests. São as duas causas, sempre — ou o sensor está desligado, ou ninguém declarou a alocação de referência.

Anota aí: HPA = estado desejado aplicado à escala: você define alvo, piso e teto — a mureta faz o resto. Mas sem metrics-server (sensores) e sem resources.requests (alocação declarada) ele não enxerga nada.

E o cluster ESCALOU SOZINHO, senhoras e senhores! Réplicas subindo na tela sem um comando sequer — o ciclo se fechou: você declara o alvo, a mureta faz a corrida. Última curva completada. Agora é volta de desaceleração, aceno pra arquibancada — e o pódio logo ali.

Etapa 09 labs online

Pratique de graça em clusters reais

Volta de desaceleração: o motor esfria, mas o campeonato continua — e todo piloto sabe que temporada se constrói no treino. Aqui está o calendário de testes.

Pense nisto como a escada de qualquer piloto: simulador público, kart, F4, e só então o carro de verdade. Estas plataformas dão terminal com Kubernetes real direto no navegador — comece pelas 100% gratuitas.

Killercoda

100% grátis

Cenários interativos de Kubernetes direto no navegador: você recebe um terminal com cluster real e um roteiro guiado. Sucessor do Katacoda.

Bom para: Praticar cada etapa deste guia sem instalar nada. Comece por aqui.

killercoda.com/kubernetes

Play with Kubernetes

100% grátis

Cluster Kubernetes real e temporário (sessões de 4 horas) no navegador, mantido pela Docker. Você monta o cluster na mão com kubeadm.

Bom para: Testar comandos kubectl livremente e entender a montagem de um cluster.

labs.play-with-k8s.com

Kube by Example

100% grátis

Tutoriais e exemplos curtos mantidos pela Red Hat: um conceito por página (Pods, Services, Deployments...), com exemplos direto ao ponto.

Bom para: Revisar um conceito específico rapidamente, como uma segunda explicação.

kubebyexample.com

Introduction to Kubernetes (LFS158)

100% grátis

Curso oficial gratuito da Linux Foundation (quem mantém o K8s), disponível também no edX. Base teórica sólida com certificado de participação.

Bom para: Consolidar a teoria com o material oficial depois de fechar este guia.

training.linuxfoundation.org

Kubernetes the Hard Way

100% grátis

O lendário roteiro do Kelsey Hightower: montar um cluster peça por peça, na unha, sem instaladores. É o "monte o carro parafuso por parafuso" — quem faz, nunca mais olha a garagem do mesmo jeito.

Bom para: Nível avançado — quando quiser entender o que o Minikube esconde de você.

github.com/kelseyhightower

KodeKloud

Free tier + pago

Labs guiados estilo desafio: "esse Pod não sobe, descubra por quê". Alguns labs são gratuitos; o catálogo completo (e os simulados CKA/CKAD) é pago.

Bom para: Troubleshooting realista, o mais próximo de uma entrevista técnica.

kodekloud.com

iximiuz Labs

Free tier + pago

Playgrounds de containers e Kubernetes no navegador com desafios práticos. Vários playgrounds e desafios liberados no plano gratuito.

Bom para: Experimentos mais profundos: rede, imagens, internals de containers.

labs.iximiuz.com

Roteiro sugerido: a cada etapa deste guia, abra o Killercoda e repita os comandos no cenário equivalente (Pods, Deployments, Volumes...). Fechou as 8 etapas? Vá pro KodeKloud encarar desafios de troubleshooting.