Kubernetes requests vs limits: como isso afeta scheduling e throttling

Tabela de Conteúdo

Se seu pod está sendo morto por OOM ou a aplicação fica lenta sem motivo aparente, o problema costuma ser requests/limits.

A ideia é simples:

  • requests = reserva que o scheduler usa pra decidir onde alocar
  • limits = teto que o container não pode passar (CPU pode ser throttled, memória pode ser OOMKilled)

Classes de QoS (o que o K8s usa internamente)

Guaranteed (requests == limits)

  • Garantia de recursos
  • Não sofre throttling de CPU (dentro do limite)
  • Se estourar memória, OOMKill

Burstable (requests < limits)

  • Pode ser “preemptado” por pods Guaranteed
  • CPU pode ser throttled se o nó estiver lotado
  • Memória: OOM se passar do limit

BestEffort (sem requests/limits)

  • Primeiro a ser “preemptado” se o nó precisar de recursos
  • CPU pode ser quase zero se o nó estiver sob pressão
  • OOMKill se o nó precisar de memória

Debug rápido (o que eu uso no dia a dia)

kubectl top pod -A
kubectl describe pod -n <ns> <pod>
kubectl describe node <node>
kubectl get events -n <ns> --sort-by=.lastTimestamp | tail -n 30

Procure por:

  • Killing container with id ... (OOM)
  • Throttling (CPU)
  • Insufficient cpu/memory (preemption)

Exemplo YAML (Burstable)

apiVersion: apps/v1
kind: Deployment
metadata:
  name: api
spec:
  replicas: 2
  selector:
    matchLabels:
      app: api
  template:
    metadata:
      labels:
        app: api
    spec:
      containers:
        - name: api
          image: nginx:1.27
          resources:
            requests:
              memory: "128Mi"
              cpu: "100m"
            limits:
              memory: "256Mi"
              cpu: "500m"

Como ler esse YAML

  • requests.memory: reserva 128 MiB (o scheduler usa isso pra alocar)
  • limits.memory: teto de 256 MiB (se passar, OOMKill)
  • requests.cpu: reserva 0.1 vCPU (100 millicores)
  • limits.cpu: teto de 0.5 vCPU (se passar, throttling)

Dica que salva

  • Se você setar limits, SEMPRE sete requests também (senão pode virar BestEffort sem querer)
  • Para apps críticos, considere Guaranteed (requests == limits)
  • Para apps “batch” ou de baixa prioridade, Burstable costuma ser suficiente

Se você quiser entender melhor como rollout e probes interagem com recursos, dá uma olhada neste post: Kubernetes probes: liveness, readiness e startup (sem mistério).

Simples assim! :)