Debugando rollout no Kubernetes

Tabela de Conteúdo

Se o seu rollout está lento ou apresentando problemas, geralmente está na configuração de maxSurge/maxUnavailable ou na quantidade de réplicas.

A ideia é simples:

  • maxSurge: quantos pods extras podem ser criados durante o rollout
  • maxUnavailable: quantos pods podem ficar indisponíveis durante o rollout

Checklist rápido que uso diariamente

1) Verificar status do rollout

$ kubectl rollout status deploy/<app> -n <ns>
$ kubectl rollout history deploy/<app> -n <ns>

2) Olhar events recentes

$ kubectl get events -n <ns> --sort-by=.lastTimestamp | tail -n 30

Procure por FailedScheduling, ReplicaSet, Available

3) Descrever o deployment

$ kubectl describe deploy/<app> -n <ns>

Veja as colunas Replicas, Available, Unavailable

4) Checar endpoints do Service

$ kubectl get endpoints -n <ns>
$ kubectl describe svc/<app> -n <ns>

5) Logs dos pods que estão falhando

$ kubectl logs -n <ns> <pod> -c <container> --tail=200

Trade-offs

maxSurge: 25% / maxUnavailable: 25% (padrão)

Impacto real

  • Cria pods extras, pode estourar recursos do nó (CPU/memória)
  • Com poucas replicas (1-2), o “25%” pode não ser suficiente para progresso
  • Risco de FailedScheduling se o nó estiver lotado

Quando usar

  • Ambientes com recursos sobrando
  • Apps que toleram sobrecarga momentânea

maxSurge: 0 / maxUnavailable: 1 (conservador)

Impacto real

  • Não cria pods extras, é seguro para nós com poucos recursos
  • Rollout mais lento (substitui um por um)
  • Se replicas: 1, você terá downtime durante a troca

Quando usar

  • Clusters pequenos ou spot instances
  • Apps stateful que não lidam bem com múltiplas instâncias temporárias

maxUnavailable: 0 (zero-downtime)

Impacto real

  • Pode dobrar o consumo de recursos durante rollout
  • Precisa de maxSurge > 0 para ter progresso
  • Se não houver recursos, rollout trava (nenhum pod novo sobe, nenhum antigo morre)

Quando usar

  • Produção crítico com SLA estrito
  • Clusters com recursos provisionados

Cenários avançados

1) PodDisruptionBudget (PDB) + rollout

Se você tem PDB com minAvailable: 2, mas usa maxUnavailable: 1, rollout pode travar:

$ kubectl get pdb -n <ns>
$ kubectl describe pdb <pdb> -n <ns>

2) Resource requests vs surge

Se cada pod pede 1Gi e você tem 3Gi livre, maxSurge: 1 funciona.Se pedir 2Gi, rollout falha por falta de recursos.

3) HPA interagindo com rollout

Se HPA escala durante rollout, você pode ter mais pods do que esperava → esgotamento de recursos.

Dica que salva

  • Se você só tem 1 replica, não existe zero-downtime
  • Para zero-downtime real: maxUnavailable: 0 + maxSurge >= 1 + recursos suficientes
  • Sempre teste rollout em staging com as mesmas requests/limits de produção

Exemplo YAML (zero-downtime com 2+ replicas)

apiVersion: apps/v1
kind: Deployment
metadata:
  name: api
spec:
  replicas: 3
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  selector:
    matchLabels:
      app: api
  template:
    metadata:
      labels:
        app: api
    spec:
      containers:
        - name: api
          image: nginx:1.27
          ports:
            - containerPort: 80

Como ler esse YAML

  • replicas: 3: baseline de 3 pods
  • maxSurge: 1: pode criar 1 pod extra (total 4)
  • maxUnavailable: 0: nenhum pod pode ficar indisponível
  • Resultado: rollout cria novos pods antes de matar os antigos

Quando usar cada estratégia

Produção crítico

  • maxUnavailable: 0 + maxSurge: 1 (ou 25%)
  • Pré-requisito: recursos provisionados para o dobro de pods
  • Cuidado: verifique PDBs para não travar rollout

Produção com recursos limitados

  • maxUnavailable: 1 + maxSurge: 1
  • Balance entre disponibilidade e uso de recursos
  • Funciona bem com 2-3 replicas

Dev/test ou ambientes efêmeros

  • maxUnavailable: 1 + maxSurge: 0
  • Mais rápido se você tem recursos escassos
  • Downtime aceitável para não produção

Spot instances ou nós pequenos

  • maxSurge: 0 + maxUnavailable: 1
  • Evita criar pods extras que podem não caber
  • Rollout mais lento, mas seguro

Comandos úteis do dia a dia

# Rollback rápido se algo deu errado
$ kubectl rollout undo deployment/<app> -n <ns>

# Verificar se rollout está em andamento
$ kubectl get rs -n <ns>

# Forçar rollout (ex: depois de mudar image)
$ kubectl rollout restart deployment/<app> -n <ns>

# Verificar histórico de rollouts
$ kubectl rollout history deployment/<app> -n <ns>

# Verificar PDBs que podem bloquear rollout
$ kubectl get pdb -n <ns>

# Checar recursos disponíveis vs pedidos
$ kubectl describe node <node> | grep -A 10 "Allocated resources"

Nota: Você pode usar deployment/<nome> ou deploy/<nome> — ambos funcionam da mesma forma.

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

Simples assim! :)