Pular para conteúdo

10. Kubernetes

Objetivo

Rodar o BoxOffice num cluster Kubernetes de verdade no seu laptop. Criar um cluster kind com três nós, instalar um Ingress controller (Traefik) e o metrics-server, fazer o deploy de db, redis e catalog com o Kustomize — probes, requests e limits de recursos, graceful shutdown — e deixar um Horizontal Pod Autoscaler escalar o catalog sob uma rampa do k6. Medir quão rápido a capacidade acompanha a carga, quantas requisições um rolling update perde e quanto tempo a autocura leva.

No lab 3 você escalou o catalog editando o docker-compose.yaml e reiniciando; no lab 9 você viu um serviço cair e teve que reiniciá-lo à mão. Às 10:00 do dia da venda ninguém deveria estar editando YAML ou reiniciando contêineres. O Kubernetes transforma as duas coisas em laços de controle: você declara o estado desejado — "pelo menos duas réplicas prontas, mais quando a CPU passar de 60%" — e os controllers mantêm a realidade ali, a cada poucos segundos, para sempre. Este lab é o lado prático da aula de cloud-native e constrói o capítulo 11 da história do curso: ele implementa as decisões da aula sobre probes, requests e limits, autoscaling e perder um nó.

Slides

Clique nos slides e use ← → para navegar; F abre em tela cheia e P abre a visão do apresentador, com as notas. Abrir os slides em uma nova aba

Antes de começar

Tempo cerca de 4 horas
Ferramentas kubectl (kubectl version --client), kind 0.33+ (kind version) ou minikube, Helm 4 (helm version, instalado no passo 1), Docker, k6
Recursos do Docker pelo menos 4 CPUs e 8 GB; a stack do Compose precisa estar parada (o cluster usa a porta 80)
Portas 80 na sua máquina (o Ingress)

Todo comando roda na raiz do seu repositório boxoffice, no estado em que o lab 9 o deixou:

Start state (end of lab 9)
boxoffice/
├── docker-compose.yaml     # the full Compose stack of labs 1-9
├── infra/  load/  scripts/
└── services/               # auth, catalog, gateway, inventory, notification, order, payment

Recupere o atraso

Pulou ou quebrou o lab 9? Baixe boxoffice-after-lab-9.zip, descompacte, cd boxoffice e continue daqui. Este lab só precisa da imagem do catalog, construída a partir de services/catalog com docker compose build catalog-1.

Todo arquivo deste lab aparece completo nestas páginas e é publicado em https://insper.github.io/platform/2027.1/hands-on/10/code/<caminho>.

Arquitetura

flowchart LR
    k6[k6] -->|"localhost:80"| traefik["Traefik (Ingress)"]
    subgraph cluster [cluster kind: 1 control plane + 2 workers]
        traefik -->|/catalog| svc[Service catalog]
        svc --> c1[pod catalog]
        svc --> c2[pod catalog]
        svc -.-> cN["pod catalog ... (HPA: 2..8)"]
        c1 --> redis[(redis)]
        c1 --> db[("db-0 (StatefulSet + PVC)")]
        ms[metrics-server] -.->|CPU| hpa[HPA]
        hpa -.->|réplicas| svc
    end

Componentes do BoxOffice envolvidos

Componente da paleta Neste lab
Ingress Traefik, com um Ingress (ou uma HTTPRoute da Gateway API) para /catalog
Load Balancer o Service catalog distribuindo as requisições entre os pods prontos
App Server o Deployment catalog, escalado por um HPA
Health Check probes de startup, liveness e readiness
SQL Database / Cache StatefulSet db com um volume persistente, redis

O que você vai medir

Pergunta Métrica Ferramenta
Quão rápido a capacidade acompanha uma rampa de carga? tempo até o primeiro scale-up, tempo até a capacidade total, p95 durante a rampa k6, watch-hpa.sh
Réplicas fixas vs autoscaling? p95, p99, erros no mesmo pico k6
Um rolling update perde requisições? requisições com falha com e sem readiness + preStop k6
Quanto tempo leva a autocura? pod apagado / nó parado → pronto de novo kubectl get -w

Pré-requisitos

  • Labs 1 a 5 concluídos (a imagem do catalog com o seu cache); o load/catalog-otel.js do lab 8 é reaproveitado no passo 5.
  • kubectl, kind (ou minikube) do lab 0, mais o Helm (passo 1).
  • Leia a página de Kubernetes da aula de cloud-native e autoscaling na aula de computação.

Passos

  1. Um cluster local — kind com três nós, Traefik, metrics-server, imagens carregadas no cluster.
  2. Deploy do BoxOffice — base e overlay do Kustomize; StatefulSet, Deployment, probes, recursos, graceful shutdown; autocura.
  3. Autoscaling — um HPA autoscaling/v2 com comportamento de scale-up e scale-down, sob uma rampa do k6.
  4. Ingress — o caminho de uma requisição para dentro do cluster; Ingress e Gateway API.
  5. Meça — fixo vs autoscaling, rollouts com e sem probes, tempos de recuperação.

Experimente no playground

Experimente: rode o scale-out com o perfil stress e um número fixo de réplicas até o p99 explodir; depois aumente o número de réplicas e rode de novo. Anote a vazão por réplica — o mesmo número em que o alvo do seu HPA se baseia implicitamente. Ligue um health check e mate uma réplica: por quanto tempo o load balancer continua mandando tráfego para ela?

O simulador completo está no playground.

Meça

O passo Meça tem os comandos e a tabela de resultados para guardar em results/lab10.md, com o log do watch-hpa.sh em results/lab10-hpa.csv.

Solução de problemas

Sintoma Causa provável Correção
kind create cluster falha com port is already allocated o edge do Compose (ou outro servidor) usa a porta 80 docker compose down; lsof -i :80
pods em ImagePullBackOff / ErrImagePull a imagem não foi carregada nos nós, ou a tag é latest kind load docker-image boxoffice/catalog:dev --name boxoffice; mantenha imagePullPolicy: IfNotPresent
catalog em CrashLoopBackOff nos primeiros minutos o PostgreSQL ainda não estava pronto (normal), ou credenciais erradas espere; kubectl -n boxoffice logs deploy/catalog --previous
catalog morto com failed startup probe a primeira inicialização (migrations) mais lenta que o orçamento de startup num laptop ocupado aumente o failureThreshold da startupProbe; dê mais CPU ao Docker
kubectl get hpa mostra cpu: <unknown>/60% o metrics-server não está pronto, ou não recebeu o patch com --kubelet-insecure-tls kubectl -n kube-system get pods; repita o patch; espere um minuto
pods ficam em Pending CPU/memória insuficientes para os recursos pedidos kubectl -n boxoffice describe pod <name>; diminua PEAK/maxReplicas ou dê mais recursos ao Docker
curl localhost/catalog/... devolve 404 o Ingress não existe ou tem o ingressClassName errado kubectl -n boxoffice get ingress; kubectl -n traefik get pods
o kubectl fala com o cluster errado outro contexto está ativo kubectl config use-context kind-boxoffice

Boas práticas neste lab

  • Uma probe por pergunta: startup dimensionada para a inicialização mais lenta (5 min, com migrations), liveness local à JVM, readiness para o tráfego — k8s/base/catalog.yaml; por quê: Kubernetes — probes.
  • Requests definidos de propósito, porque são a base da porcentagem do HPA (60% de 250m) — catalog.yaml e catalog-hpa.yaml; por quê: requests e limits.
  • Nenhuma requisição perdida num rollout: maxUnavailable: 0, uma pausa de 5 s no preStop e graceful shutdown — catalog.yaml; por quê: graceful shutdown.
  • Escale para cima rápido, para baixo devagar: dobrar ou +2 pods a cada 15 s, um pod a cada 30 s depois de uma janela de 2 minutos — catalog-hpa.yaml; por quê: autoscaling.
  • Uma base, overlays finos: o que muda por ambiente fica em k8s/overlays/, então o lab 11 reaproveita o k8s/base/ sem mudanças; por quê: GitOps.

Limpeza

kind delete cluster --name boxoffice     # frees all the memory of the three nodes
docker compose up -d                     # back to the Compose stack, if you need it

O lab 11 precisa de um cluster de novo: você pode mantê-lo (docker stop boxoffice-control-plane boxoffice-worker boxoffice-worker2 e docker start … depois) ou recriá-lo com os comandos do passo 1.

Estado final

End state (what this lab added)
boxoffice/
├── k8s/
│   ├── kind.yaml
│   ├── base/               # kustomization, namespace, config, db, redis, catalog, catalog-hpa,
│   │                       # ingress (+ catalog-route.yaml, the Gateway API alternative)
│   └── overlays/local/kustomization.yaml
├── load/catalog-hpa.js
├── scripts/watch-hpa.sh
└── results/lab10.md, lab10-hpa.csv

Faça commit e tag: git add -A && git commit -m "lab 10: kubernetes" && git tag lab10.

Checklist

  • k8s/kind.yaml, k8s/base/ e k8s/overlays/local/ no seu repositório; kubectl apply -k k8s/overlays/local faz o deploy de tudo no namespace boxoffice
  • curl localhost/catalog/events/1 responde pelo Traefik
  • o catalog tem probes de startup, liveness e readiness, requests e limits, graceful shutdown e uma pausa no preStop
  • o HPA escalou o catalog para cima durante a rampa do k6 e de volta para baixo depois; o log em CSV está no commit
  • o experimento de rolling update mostra o efeito de readiness + preStop nas requisições com falha
  • tabela de resultados preenchida e explicada; git tag lab10

Começar: Um cluster local