↓Pular para o conteúdo principal
  1. blog/
ARTIGO TÉCNICO

Fila de retry pra falta de capacidade na OCI: distinguindo rc=3 de erro fatal

Resize automático de instância OCI que sabe diferenciar 'sem capacidade agora' de 'erro de verdade' — retry interno com backoff, e uma fila externa via at/atd pra reagendar sem duplicar o disparo nem lotar a janela operacional.

·2 minutos

O problema #

Resize de shape na OCI às vezes falha por falta temporária de capacidade no availability domain — não é erro de configuração, é a nuvem sem recurso livre naquele instante. Tratar isso como qualquer outro erro (alertar e esperar humano agir) desperdiça uma falha que se resolve sozinha minutos ou horas depois.


Distinguir “sem capacidade” de “quebrou de verdade” #

O script de resize usa um código de saída específico — rc=3 — só pra esse caso, reconhecido a partir da mensagem de erro da própria API OCI:

1
2
3
4
5
6
7
if echo "${RESIZE_RAW}" | grep -qiE \
  'Out of host capacity|OutOfCapacity|timed out|ServiceUnavailable|InternalError'; then
  # ... retry interno até RETRY_MAX, depois:
  echo "RESIZE_EXIT_REASON=NO_CAPACITY"
  echo "RESIZE_RETRY_ELIGIBLE=true"
  exit 3
fi

Qualquer outro erro da API — permissão, shape inválido, quota — sai com código diferente e não entra na fila de retry automático. Misturar os dois esconderia erro real atrás de “vai resolver sozinho”.


Retry interno primeiro, fila externa depois #

Duas camadas, não uma só:

  1. Retry interno (dentro do próprio script de resize): até 3 tentativas, 60s de espera entre elas — cobre uma indisponibilidade de segundos.
  2. Fila externa (at/atd), acionada só se as 3 tentativas internas falharem: reagenda uma nova tentativa completa 20 minutos depois, dentro de uma janela operacional até 04:00 BRT. Se passar da janela, remarca pro dia seguinte às 00:00 — a mesma lógica se repete até conseguir.

Por que at/atd em vez do Schedule nativo do orquestrador #

Decisão pouco óbvia: o agendador nativo do Ansible Semaphore (usado aqui pra disparar o resize) não persistia corretamente as variáveis de ambiente em algumas versões — um template agendado por ele subia sem server_name/ocpus/memory_gb, inútil. at/atd contorna isso porque o job local já guarda o payload final completo, pronto pra disparar a API do orquestrador com os parâmetros certos — não depende de nenhum estado persistido do outro lado.


Fila serializada, não corrida #

Quando várias instâncias vencem o retry no mesmo minuto, o script não dispara tudo de uma vez:

  • Espaçamento entre slots — cada novo agendamento calcula o próximo horário livre na fila, evitando que dois resizes caiam exatamente juntos
  • flock no disparo da API — serializa a chamada final pro orquestrador, reduzindo corrida de checkout/cache quando múltiplos jobs vencem ao mesmo tempo
  • Notificação por WhatsApp — cada agendamento e cada resultado final (sucesso ou esgotamento de tentativas) gera aviso, sem exigir que alguém fique olhando fila de at manualmente

Tecnologias #

Bash · OCI CLI · at/atd · flock · Ansible Semaphore

TEM UM CENÁRIO PARECIDO?

Me chama.

Manda o contexto, os sintomas e o que já foi testado. Bora organizar as evidências antes de sair mexendo.

Falar com Castro →
Sem enrolação. Com evidência.