Pular para o conteúdo
NyverraNyverra
Artigos
⌘K
InícioArtigosSite institucional
🇧🇷

Nyverra

Canal editorial

Artigos sobre tecnologia, operações e parceiros — infraestrutura, monitoramento e ambientes críticos.

Explorar

  • Início
  • Artigos
  • Categorias
  • Tags
  • Autores
  • Sobre
  • Contato
  • RSS
  • Site institucional

© 2026 Nyverra. Todos os direitos reservados.

blog.nyverra.com

  1. Início
  2. Kubernetes
  3. Curso Kubernetes 26 — Capacidade e carga: HPA, k6 e rate limit
Kubernetes
#K8S#SRE#Curso Kubernetes#Kubernetes

Curso Kubernetes 26 — Capacidade e carga: HPA, k6 e rate limit

Wedson LopesWedson Lopes
30 de outubro de 20265 min de leitura

Capacidade não é "quantos usuários cabem". É em que ponto o sistema deixa de cumprir o SLO — e qual componente quebra primeiro.

Na maioria dos clusters que eu vi, não é a CPU. É o banco, a conexão, o disco ou o NAT.

Selo do curso: testado em Kubernetes 1.35 com k6 e HPA em homolog.

O que medir

Métrica Por quê
p50/p95/p99 média esconde a cauda
taxa de erro 200 com erro de negócio não conta
throughput req/s sustentado
saturação CPU, memória, conexões, disco
tempo de fila onde o request espera

Média de latência é a métrica mais inútil de capacidade. p95 com 83 ms e 0% de erro é um resultado; média de 40 ms com p99 de 4 s é um problema.

Baseline antes do teste

kubectl top nodes
kubectl -n portal top pods
kubectl -n portal get hpa
kubectl -n portal get pdb
kubectl -n portal get pods -o wide

Registre: réplicas, requests/limits, conexões do Postgres, uso de memória dos nós. Sem baseline, o teste vira anedota.

k6: ramp, não tiro único

import http from 'k6/http';
import { check, sleep } from 'k6';

export const options = {
  stages: [
    { duration: '2m', target: 10 },
    { duration: '5m', target: 50 },
    { duration: '3m', target: 100 },
    { duration: '2m', target: 0 },
  ],
  thresholds: {
    http_req_failed: ['rate<0.01'],
    http_req_duration: ['p(95)<500'],
  },
};

export default function () {
  const res = http.get(`${__ENV.BASE_URL}/api/fornecedores`, {
    headers: { Authorization: `Bearer ${__ENV.TOKEN}` },
  });
  check(res, { 'status 200': (r) => r.status === 200 });
  sleep(1);
}
k6 run -e BASE_URL=https://homolog.example.com -e TOKEN=... k6.js

Ramp encontra o joelho da curva: o ponto em que latência sobe e throughput para de crescer.

O que aconteceu no nosso teste

Com 50 VUs contra o ingress:

Métrica Resultado
Erros 0%
p95 83,9 ms
p99 dentro do aceitável

O teste seguinte, mais agressivo, derrubou o Postgres: o primário reiniciou e o failover levou o banco para outra instância. O app estava saudável; o banco não.

Conclusão prática: escalar o app sem dimensionar o banco transfere o problema. 10 pods de backend com pool de 10 conexões = 100 conexões, e o Postgres tem limite.

HPA: o que ele vê e o que ele ignora

metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70
  • HPA usa requests como denominador. Sem requests, não escala.
  • CPU não vê fila de banco, latência ou conexões.
  • Para filas, use métricas custom (KEDA) — tamanho de fila do RabbitMQ, por exemplo.
  • maxReplicas precisa caber no cluster. HPA pedindo 8 pods com 4 nós cheios = Pending.
kubectl -n portal describe hpa portal-backend

A saída mostra unable to fetch metrics ou missing request for cpu quando falta requests.

Headroom de nó

Capacidade real = soma dos allocatable menos o que já está reservado, com margem para:

  • um nó perdido (N+1);
  • surge de rollout (maxSurge);
  • DaemonSets.
kubectl describe node <node> | sed -n '/Allocated resources/,/Events/p'

Se cada nó está a 85%, você não tem HA: tem um cluster esperando o próximo drain.

Rate limit e proteção

Teste de carga também revela ausência de proteção:

  • Rate limit no ingress (nginx limit_req) ou no app.
  • Timeout de conexão e de leitura.
  • Circuit breaker para dependência lenta.
  • Connection pool com limite e timeout curto.

Sem isso, um pico vira fila infinita, e a fila vira timeout em cascata.

Teste seguro

Antes de rodar carga:

  1. Ambiente isolado (homolog), nunca prod sem janela.
  2. Backup recente do banco.
  3. Alerta de plantão avisado.
  4. Critério de parada definido (ex.: erro > 5% por 1 min).
  5. Observabilidade ligada: Prometheus, Grafana, logs.
  6. Plano de rollback.

E depois:

kubectl -n portal get pods
kubectl -n portal logs deploy/portal-backend --tail=100
kubectl -n portal get events --sort-by=.lastTimestamp | tail -20

Laboratório

  1. Rode um teste curto (10 VUs, 2 min) e valide o ambiente.
  2. Suba o ramp e acompanhe kubectl get hpa -w e o Grafana.
  3. Identifique o primeiro componente saturado.
  4. Reduza maxReplicas e repita: veja o erro aparecer.
  5. Ajuste o pool de conexões do app e repita.
  6. Documente: throughput máximo, p95 no limite e gargalo.

Erros comuns

Sintoma Causa
p95 explode com carga baixa pool de conexão pequeno
HPA não escala sem requests ou metrics-server fora
Pods Pending no pico maxReplicas acima da capacidade
Banco reinicia sob carga conexões/memória do Postgres
429 inesperado rate limit do ingress
Teste “passou” e prod caiu ambiente de teste com mais recursos
Números irreproduzíveis sem baseline nem script versionado

Checklist

  • [ ] Baseline registrado antes do teste.
  • [ ] Script k6 versionado no repositório.
  • [ ] Thresholds de erro e p95 definidos.
  • [ ] HPA com requests e maxReplicas que cabe no cluster.
  • [ ] Pool de conexões dimensionado com o banco.
  • [ ] Headroom de N+1 validado.
  • [ ] Rate limit e timeouts configurados.
  • [ ] Critério de parada e rollback acordados.
  • [ ] Resultado documentado com data e commit.

Glossário

  • VU: usuário virtual do k6.
  • ramp: aumento gradual de carga.
  • joelho: ponto onde latência cresce sem ganho de throughput.
  • headroom: folga de capacidade.
  • pool: conjunto de conexões reutilizáveis.
  • KEDA: autoscaling por eventos/filas.

Próximo

Você mediu capacidade e sabe onde quebra. Falta combinar isso com o que o negócio espera: SLO, SLI, on-call e postmortem sem culpa.

Próximo: Curso Kubernetes 27 — SLO/SLI, on-call e postmortem blameless

Compartilhar

Continuar a ler

Leia também

  • Kubernetes de Verdade — do zero ao cluster em produção
    Kubernetes

    Kubernetes 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.

    30 de outubro de 20264 min de leitura
  • Curso Kubernetes 28 — DR e capstone: provar que o cluster volta
    Kubernetes

    Curso 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.

    30 de outubro de 20265 min de leitura
  • Curso Kubernetes 27 — SLO/SLI, on-call e postmortem blameless
    Kubernetes

    Curso 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.

    30 de outubro de 20264 min de leitura

Comentários

Ainda sem comentários

Seja o primeiro a compartilhar sua opinião sobre este artigo.

Deixe um comentário

Newsletter

Receba novos artigos

Inscreva-se para receber publicações do blog Nyverra no seu e-mail. Enviaremos um link de confirmação.

​