Levantar cluster de 3 nodos
Forma un cluster con 3 servidores en menos de 10 minutos. Tolera falla de 1 nodo sin indisponibilidad.
Un nodo aislado funciona, pero cualquier reboot tira la aplicación. Para tolerar fallas y hacer deploy sin ventana, necesitas 3 nodos formando un plano de control distribuido.
¿Por qué 3 nodos, y no 2 o 4?
La regla es simple: el consenso entre servidores necesita mayoría. Con 3 nodos, perder 1 aún mantiene 2 vivos, es decir, mayoría. Con 2, perder 1 deja 1 vivo, sin mayoría, y el cluster se traba por seguridad.
| Nodos | Tolera falla de | Indicado para |
|---|---|---|
| 1 | 0 | desarrollo, lab |
| 3 | 1 | producción pequeña/media |
| 5 | 2 | producción crítica |
| 4 o 6 | igual que 3 o 5 | nunca, es desperdicio |
Números pares suman costo sin sumar resiliencia. Siempre impar.
Nota: los workers (modo agente puro) no cuentan para esa matemática. Puedes tener 3 servidores + 50 workers y la regla sigue siendo "1 servidor puede caer".
Provisionar los 3 servidores
HeroCtl no exige máquinas iguales, pero los servidores deben tener mismo perfil de CPU y disco para evitar lentitud en quien queda atrás. Un ejemplo barato y funcional:
| Proveedor | Plan | Costo/mes | CPU | RAM | Disco |
|---|---|---|---|---|---|
| Hetzner | CPX21 | € 7,99 | 3 vCPU | 4 GB | 80 GB |
| DigitalOcean | s-2vcpu-4gb | US$ 24 | 2 vCPU | 4 GB | 80 GB |
| Vultr | vc2-2c-4gb | US$ 24 | 2 vCPU | 4 GB | 80 GB |
Provisiona 3 máquinas en el mismo datacenter, en red privada si el proveedor lo ofrece. La latencia entre nodos debe quedar bajo 10 ms.
Después sigue el paso de instalación en cada una. Cuando termines, tendrás 3 servidores con binario listo y nada más.
Inicializar el primer nodo
El primer nodo "abre" el cluster. Los otros se unirán a él. Ese comando solo corre en una máquina y nunca más.
# En el nodo 1, IP privada 10.0.0.1
sudo heroctl cluster init --advertise 10.0.0.1
Salida esperada:
cluster initialized
node-id: node-1
state: healthy
nodes: 1/1
A partir de aquí, el nodo 1 ya acepta jobs. Pero sin los otros dos, no hay tolerancia a falla.
Generar token de join
Para que otros nodos se unan, necesitas un token. Es firmado por el cluster y tiene validez configurable.
# En el nodo 1
heroctl cluster join-token --ttl 1h
# eyJhbGciOi...truncado...8X7Z
Atención: el token concede entrada al plano de control. Trátalo como contraseña. Usa TTL corto (1h alcanza para unir 3 nodos) y nunca lo pegues en logs o Slack público.
Conectar nodos 2 y 3
En cada uno de los otros dos nodos, ejecuta el comando de join. Sustituye <TOKEN> por el token generado y <IP> por la IP privada de esa máquina.
# En el nodo 2, IP privada 10.0.0.2
sudo heroctl cluster join \
--token eyJhbGciOi...8X7Z \
--advertise 10.0.0.2 \
--servers 10.0.0.1:8080
# En el nodo 3, IP privada 10.0.0.3
sudo heroctl cluster join \
--token eyJhbGciOi...8X7Z \
--advertise 10.0.0.3 \
--servers 10.0.0.1:8080
Cada comando demora de 5 a 15 segundos. El nodo descarga el estado actual, sincroniza y pasa a recibir actualizaciones en tiempo real.
Verificar salud
Tras estar los 3 conectados, cualquiera responde con la visión del cluster:
heroctl cluster status
Salida saludable:
cluster: 3 nodes
quorum: ok (2/3 required)
leader: node-1 (10.0.0.1)
peers:
- node-1 10.0.0.1 server ready applied=1247
- node-2 10.0.0.2 server ready applied=1247
- node-3 10.0.0.3 server ready applied=1247
last_update: 0.4s ago
Qué mirar:
- quorum: ok — mayoría viva, el cluster acepta escrituras.
- applied igual en los 3 nodos — todos vieron los mismos cambios. Diferencia pequeña (1–2) es normal entre el pulso actual.
- last_update bajo 5s — replicación fluyendo.
Si applied diverge mucho (cientos), hay problema de red o disco en un nodo. Mira Problemas comunes abajo.
Agregar workers
Los workers ejecutan solo contenedores. No votan, no deciden, no guardan estado. Agrega cuantos quieras sin afectar el consenso.
# En cada worker
sudo heroctl agent \
--token <TOKEN> \
--advertise 10.0.0.10 \
--servers 10.0.0.1:8080,10.0.0.2:8080,10.0.0.3:8080
Confirma con:
heroctl node list
# node-1 server ready 3.2 GB free 2 jobs
# node-2 server ready 3.4 GB free 1 job
# node-3 server ready 3.0 GB free 2 jobs
# node-10 worker ready 7.8 GB free 0 jobs
Nota: siempre pasa las 3 IPs en
--servers. Si apuntas solo al nodo 1 y se cae durante el join, el agente queda en retry.
Problemas comunes
Nodo no conecta
Síntoma: cluster join queda en "connecting..." por más de 30s.
Causa típica: firewall bloqueando puerto 8082 entre los nodos. Confirma con nc -zv <ip-do-nó-1> 8082. Si falla, libera el puerto en el firewall externo del proveedor.
Estado divergente entre nodos
Síntoma: applied muy diferente entre nodos (>100).
Causa posible: un nodo quedó offline y está reaplicando historial. Espera unos minutos. Si no converge, fuerza resync en el nodo atrasado:
sudo systemctl restart heroctl
heroctl node info <node-id>
Cluster sin mayoría
Síntoma: quorum: degraded o los comandos de escritura se traban.
Significa que 2 de 3 nodos están fuera. El cluster rechaza escrituras para evitar inconsistencia. Recupera los nodos antes de intentar cambiar nada. Si uno de los servidores está perdido en definitiva, reemplázalo con cluster leave + nuevo cluster join.
Aparecen dos "líderes"
No ocurre. Si el status de un nodo dice que es líder y otro también, hay problema de reloj. Sincroniza con chrony o ntpd en todos los nodos y reinicia.
Próximo paso: hacer deploy de la primera app.