Troubleshooting de problemas comuns

Os 12 problemas mais frequentes em clusters HeroCtl, com sintoma, diagnóstico e correção passo a passo.

Troubleshooting·10 min·

Este guia cobre os doze problemas que aparecem com mais frequência em clusters HeroCtl. Cada item traz sintoma, diagnóstico e correção. Use como referência rápida em incidente.

1. Cluster não inicia: "cannot bind to port 8080"

Sintoma: o serviço sobe e morre logo em seguida. O log diz que a porta 8080 está em uso.

Diagnóstico:

sudo lsof -i :8080
# ou
sudo ss -tlnp | grep 8080

A saída mostra qual processo está segurando a porta.

Correção:

Se for processo legítimo (outro app), mude a porta do HeroCtl:

# /etc/heroctl/server.yaml
api:
  port: 8090

Se for processo zumbi (HeroCtl antigo que não morreu direito):

sudo kill -9 <PID>
sudo systemctl start heroctl-server

2. Nó não consegue entrar no cluster

Sintoma: comando de join trava ou retorna connection refused / invalid token.

Diagnóstico:

Três suspeitos comuns:

# 1. Token expirou?
heroctl cluster join-token list

# 2. Firewall bloqueando?
nc -zv <ip-do-coordenador> 4646
nc -zv <ip-do-coordenador> 4647
nc -zv <ip-do-coordenador> 4648

# 3. Relógios fora de sincronia?
timedatectl status

Correção:

  • Token expirado: gere outro com heroctl cluster join-token create --ttl 1h.
  • Firewall: libere as portas 4646, 4647 e 4648 entre os nós. Veja firewall.
  • Relógio: instale e ative NTP.
sudo apt install chrony
sudo systemctl enable --now chrony

Diferença maior que 30 segundos entre nós quebra a coordenação.

3. Cluster perdeu coordenação

Sintoma: API responde com 503 e mensagens sobre falta de coordenador. Mudanças não são aceitas.

Diagnóstico:

heroctl cluster status

Você verá quantos nós estão saudáveis. Se menos da metade respondem, o cluster trava em modo somente-leitura por segurança.

Correção:

A solução normal é trazer os nós caídos de volta:

ssh nó-caído sudo systemctl start heroctl-server

Se eles não voltam (disco morto, máquina perdida), use bootstrap forçado a partir do snapshot mais recente:

heroctl snapshot restore /backups/ultimo.tar.gz --force-bootstrap

Atenção: bootstrap forçado descarta tudo que aconteceu depois do snapshot. Veja backup e restore.

4. Job fica em "pending"

Sintoma: heroctl jobs status meu-job mostra pending por minutos. Nada inicia.

Diagnóstico:

heroctl jobs explain meu-job

A saída detalha por que o agendador não consegue colocar o job. Causa típica: nenhum nó tem CPU/RAM disponível para os recursos pedidos.

Correção:

Duas opções:

  • Adicione mais nós ao cluster.
  • Reduza os recursos exigidos pelo job:
resources:
  cpu_mhz: 500      # antes era 2000
  memory_mb: 256    # antes era 1024

5. Health check falhando

Sintoma: o job sobe mas é marcado como não saudável. Reinicia em loop.

Diagnóstico:

heroctl logs <alloc-id> | tail -50

Frequentemente o app está demorando mais para subir que o healthy_deadline permite.

Correção:

Aumente o prazo:

health_check:
  path: /health
  port: 8080
  interval: 10s
  timeout: 3s
  healthy_deadline: 120s    # era 30s

Se o app está realmente lento para subir (carrega cache enorme, conecta em vários serviços), trabalhe o tempo de boot. Lazy loading geralmente resolve.

6. Certificado TLS não é emitido

Sintoma: site responde com certificado autoassinado ou erro de TLS. Logs do ingress mencionam falha em emissão automática.

Diagnóstico:

# DNS aponta pro IP correto?
dig +short meudominio.com

# Porta 80 acessível externamente?
curl -I http://meudominio.com/.well-known/acme-challenge/test

A emissão automática de certificado precisa de duas coisas: DNS público apontando para um nó do cluster e a porta 80 aberta para o mundo.

Correção:

  • DNS errado: corrija o registro A no seu provedor.
  • Porta 80 fechada: libere no firewall do servidor e no firewall do provedor (security group, etc).
  • Domínio com proxy de CDN ativo: desative o proxy temporariamente para a emissão; reative depois.

7. App lento sob carga

Sintoma: latência sobe quando o tráfego aumenta. Usuários reclamam.

Diagnóstico:

heroctl metrics --job meu-app --since 30m

Olhe CPU, memória e número de instâncias. Verifique também se há um deploy em curso — deploys gradativos retiram capacidade temporariamente.

Correção:

Se está faltando capacidade, escale:

heroctl jobs scale meu-app --count 6   # de 3 para 6

Se está deploy em curso, espere ele terminar antes de avaliar. Se o app está com vazamento de memória ou loop apertado, perfile o código — não tem como o orquestrador resolver problema interno do app.

8. Logs não aparecem

Sintoma: heroctl logs retorna vazio mesmo com app rodando e gerando saída.

Diagnóstico:

docker inspect <container-id> | grep LogConfig

Se aparece "Type": "none" ou um driver não suportado, o problema está aí.

Correção:

Configure o driver de log padrão na máquina:

// /etc/docker/daemon.json
{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m",
    "max-file": "3"
  }
}

Reinicie o serviço:

sudo systemctl restart docker

9. Conexão com Postgres dando timeout

Sintoma: o app loga connection timeout ou too many clients quando conecta no banco.

Diagnóstico:

No Postgres:

SELECT count(*) FROM pg_stat_activity;
SHOW max_connections;

Se count(*) está perto de max_connections, o pool está saturado.

Correção:

Coloque um pgbouncer entre app e banco:

# job pgbouncer
config:
  max_client_conn: 1000
  default_pool_size: 25

E aponte os apps para o pgbouncer em vez do banco direto. Você pode atender milhares de conexões de cliente com poucas conexões reais ao banco.

10. Cluster aparenta ter dois coordenadores

Sintoma: comportamentos estranhos — escrita em um nó não aparece no outro. Métricas inconsistentes entre painéis.

Diagnóstico:

heroctl cluster peers

Se a lista de pares varia dependendo do nó que você consulta, houve uma divisão de rede e duas metades acharam que eram a metade boa.

Correção:

Identifique a metade minoritária (a com menos nós) e reinicie esses nós:

sudo systemctl restart heroctl-server

Eles re-sincronizam com a metade majoritária e a inconsistência some. Em seguida verifique se algum dado divergiu durante o intervalo:

heroctl jobs status --all | grep -i diverge

11. Disco cheio

Sintoma: o nó começa a se comportar mal. API lenta. Agente reinicia containers sem motivo aparente. df -h mostra 100%.

Diagnóstico:

sudo du -sh /var/lib/heroctl/* | sort -h
sudo du -sh /var/log/* | sort -h

Os culpados de sempre são logs antigos e snapshots não limpos.

Correção:

Configure rotação:

# /etc/heroctl/server.yaml
logs:
  retention_days: 7
  max_size_per_alloc_mb: 500

snapshots:
  retention_count: 10

E uma faxina manual imediata:

sudo journalctl --vacuum-time=3d
heroctl snapshot prune --keep 10

12. Container morto por falta de memória

Sintoma: heroctl logs termina com OOMKilled. O container reinicia em loop.

Diagnóstico:

heroctl alloc status <id> | grep -A5 "memory"

Compare uso real com o limite definido.

Correção:

Aumente o limite no spec do job:

resources:
  memory_mb: 1024    # era 512

Suba a nova versão:

heroctl jobs submit meu-app.json

Se o uso de memória cresce com o tempo (vazamento), aumentar o limite só adia o problema. Investigue o app.

Quando nada disso ajuda

Reúna as seguintes informações antes de abrir um chamado:

  • heroctl cluster status (saída completa)
  • heroctl version em todos os nós
  • O request_id retornado pelo erro da API
  • Recorte do log com timestamp do incidente

Mande para suporte@heroctl.com com essas informações no corpo da mensagem. Quanto mais contexto, mais rápida a resposta.

Próximos passos

#troubleshooting#diagnostico#operacao#incidentes