Troubleshooting de problemas comunes
Los 12 problemas más frecuentes en clusters HeroCtl, con síntoma, diagnóstico y corrección paso a paso.
Esta guía cubre los doce problemas que aparecen con más frecuencia en clusters HeroCtl. Cada ítem trae síntoma, diagnóstico y corrección. Úsala como referencia rápida en un incidente.
1. Cluster no inicia: "cannot bind to port 8080"
Síntoma: el servicio sube y muere enseguida. El log dice que el puerto 8080 está en uso.
Diagnóstico:
sudo lsof -i :8080
# ou
sudo ss -tlnp | grep 8080
La salida muestra qué proceso está reteniendo el puerto.
Corrección:
Si es un proceso legítimo (otra app), cambia el puerto de HeroCtl:
# /etc/heroctl/server.yaml
api:
port: 8090
Si es un proceso zombi (HeroCtl antiguo que no murió bien):
sudo kill -9 <PID>
sudo systemctl start heroctl-server
2. Nodo no consigue entrar al cluster
Síntoma: el comando de join se cuelga o retorna connection refused / invalid token.
Diagnóstico:
Tres sospechosos comunes:
# 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
Corrección:
- Token expirado: genera otro con
heroctl cluster join-token create --ttl 1h. - Firewall: libera los puertos 4646, 4647 y 4648 entre los nodos. Ver firewall.
- Reloj: instala y activa NTP.
sudo apt install chrony
sudo systemctl enable --now chrony
Diferencia mayor a 30 segundos entre nodos rompe la coordinación.
3. Cluster perdió coordinación
Síntoma: la API responde con 503 y mensajes sobre falta de coordinador. Los cambios no son aceptados.
Diagnóstico:
heroctl cluster status
Verás cuántos nodos están saludables. Si menos de la mitad responden, el cluster se traba en modo solo-lectura por seguridad.
Corrección:
La solución normal es traer los nodos caídos de vuelta:
ssh nó-caído sudo systemctl start heroctl-server
Si no vuelven (disco muerto, máquina perdida), usa bootstrap forzado a partir del snapshot más reciente:
heroctl snapshot restore /backups/ultimo.tar.gz --force-bootstrap
Atención: el bootstrap forzado descarta todo lo que sucedió después del snapshot. Ver backup y restauración.
4. Job se queda en "pending"
Síntoma: heroctl jobs status meu-job muestra pending por minutos. Nada inicia.
Diagnóstico:
heroctl jobs explain meu-job
La salida detalla por qué el agendador no consigue colocar el job. Causa típica: ningún nodo tiene CPU/RAM disponible para los recursos pedidos.
Corrección:
Dos opciones:
- Agrega más nodos al cluster.
- Reduce los recursos exigidos por el job:
resources:
cpu_mhz: 500 # antes era 2000
memory_mb: 256 # antes era 1024
5. Health check fallando
Síntoma: el job sube pero es marcado como no saludable. Reinicia en loop.
Diagnóstico:
heroctl logs <alloc-id> | tail -50
Frecuentemente la app está demorando más en subir de lo que el healthy_deadline permite.
Corrección:
Aumenta el plazo:
health_check:
path: /health
port: 8080
interval: 10s
timeout: 3s
healthy_deadline: 120s # era 30s
Si la app está realmente lenta para subir (carga caché enorme, conecta a varios servicios), trabaja el tiempo de boot. Lazy loading generalmente resuelve.
6. Certificado TLS no se emite
Síntoma: el sitio responde con certificado autofirmado o error de TLS. Los logs del ingress mencionan fallo en emisión 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
La emisión automática de certificado necesita dos cosas: DNS público apuntando a un nodo del cluster y el puerto 80 abierto al mundo.
Corrección:
- DNS errado: corrige el registro A en tu proveedor.
- Puerto 80 cerrado: libera en el firewall del servidor y en el firewall del proveedor (security group, etc).
- Dominio con proxy de CDN activo: desactiva el proxy temporalmente para la emisión; reactívalo después.
7. App lenta bajo carga
Síntoma: la latencia sube cuando el tráfico aumenta. Los usuarios reclaman.
Diagnóstico:
heroctl metrics --job meu-app --since 30m
Mira CPU, memoria y número de instancias. Verifica también si hay un deploy en curso — los deploys graduales retiran capacidad temporalmente.
Corrección:
Si falta capacidad, escala:
heroctl jobs scale meu-app --count 6 # de 3 para 6
Si hay deploy en curso, espera a que termine antes de evaluar. Si la app tiene fuga de memoria o loop apretado, perfila el código — el orquestador no puede resolver problema interno de la app.
8. Logs no aparecen
Síntoma: heroctl logs retorna vacío aun con la app corriendo y generando salida.
Diagnóstico:
docker inspect <container-id> | grep LogConfig
Si aparece "Type": "none" o un driver no soportado, el problema está ahí.
Corrección:
Configura el driver de log estándar en la máquina:
// /etc/docker/daemon.json
{
"log-driver": "json-file",
"log-opts": {
"max-size": "100m",
"max-file": "3"
}
}
Reinicia el servicio:
sudo systemctl restart docker
9. Conexión con Postgres dando timeout
Síntoma: la app loguea connection timeout o too many clients cuando conecta a la base.
Diagnóstico:
En Postgres:
SELECT count(*) FROM pg_stat_activity;
SHOW max_connections;
Si count(*) está cerca de max_connections, el pool está saturado.
Corrección:
Pon un pgbouncer entre app y base:
# job pgbouncer
config:
max_client_conn: 1000
default_pool_size: 25
Y apunta las apps al pgbouncer en vez de la base directa. Puedes atender miles de conexiones de cliente con pocas conexiones reales a la base.
10. Cluster aparenta tener dos coordinadores
Síntoma: comportamientos extraños — escritura en un nodo no aparece en el otro. Métricas inconsistentes entre paneles.
Diagnóstico:
heroctl cluster peers
Si la lista de pares varía dependiendo del nodo que consultas, hubo una división de red y dos mitades creyeron ser la mitad buena.
Corrección:
Identifica la mitad minoritaria (la de menos nodos) y reinicia esos nodos:
sudo systemctl restart heroctl-server
Re-sincronizan con la mitad mayoritaria y la inconsistencia desaparece. Luego verifica si algún dato divergió durante el intervalo:
heroctl jobs status --all | grep -i diverge
11. Disco lleno
Síntoma: el nodo empieza a comportarse mal. API lenta. El agente reinicia containers sin motivo aparente. df -h muestra 100%.
Diagnóstico:
sudo du -sh /var/lib/heroctl/* | sort -h
sudo du -sh /var/log/* | sort -h
Los culpables de siempre son logs antiguos y snapshots no limpiados.
Corrección:
Configura rotación:
# /etc/heroctl/server.yaml
logs:
retention_days: 7
max_size_per_alloc_mb: 500
snapshots:
retention_count: 10
Y una limpieza manual inmediata:
sudo journalctl --vacuum-time=3d
heroctl snapshot prune --keep 10
12. Container muerto por falta de memoria
Síntoma: heroctl logs termina con OOMKilled. El container reinicia en loop.
Diagnóstico:
heroctl alloc status <id> | grep -A5 "memory"
Compara uso real con el límite definido.
Corrección:
Aumenta el límite en el spec del job:
resources:
memory_mb: 1024 # era 512
Sube la nueva versión:
heroctl jobs submit meu-app.json
Si el uso de memoria crece con el tiempo (fuga), aumentar el límite solo aplaza el problema. Investiga la app.
Cuando nada de esto ayuda
Reúne la siguiente información antes de abrir un ticket:
heroctl cluster status(salida completa)heroctl versionen todos los nodos- El
request_idretornado por el error de la API - Recorte del log con timestamp del incidente
Manda a suporte@heroctl.com con esa información en el cuerpo del mensaje. Cuanto más contexto, más rápida la respuesta.
Próximos pasos
- Métricas y alertas — detectar problemas antes que el usuario.
- Backup y restauración — preparación para los escenarios más graves.
- Referencia de la API — cuando el CLI no sea suficiente.