← Todas las recetasReceta · 8 de septiembre de 2026

Montar un modelo residente en dos máquinas: lo que ningún runbook te dice

Del clúster que funciona solo después de un reinicio al cartucho que rota sin borrar pesos. Los detalles de operación que convierten un experimento en algo que puedes dejar encendido.

Portada de la receta: Montar un modelo residente en dos máquinas: lo que ningún runbook te dice
Dificultadavanzada
Tiempouna tarde para montarlo, minutos para arrancarlo después
Ingredientes2× máquinas con GPU y memoria unificada · vLLM o SGLang · systemd de usuario · SSH sin contraseña · RDMA

La receta anterior explicaba si compensa repartir un modelo entre dos máquinas. Esta va de lo que casi nadie escribe en los titulares: cómo se opera para que siga funcionando un martes por la mañana sin que nadie esté delante.

Todo esto viene de tenerlo montado y roto varias veces. Los comandos son de nuestro laboratorio interno; aquí van traducidos a lo que necesitas saber, con los nombres y las rutas fuera.

Primero decide qué arquitectura de operación quieres

Hay dos formas de usar dos máquinas y no se pueden tener las dos a la vez.

Cluster (tensor parallel): las dos máquinas calculan cada token. Sirve un modelo que no cabe en una. Cuando arranca esto, la otra máquina no está libre: está dentro.

Residentes independientes: cada máquina sirve su propio modelo. Doble throughput total, el doble de espacio para experimentar, y una puede caerse sin tumbar la otra. Pero cada modelo sigue limitado a la memoria de su máquina.

Nosotros usamos las dos, y el momento de cambiar de una a otra es el peligroso. Antes de levantar un cluster hay que detener ambos residentes, con un drenaje que vacíe los perfiles activos. Hecho a mano son dos servicios que hay que detener en dos máquinas distintas, y si te olvidas de una, el arranque del cluster se queda sin memoria y falla de forma opaca.

Convierte el arranque en una unidad, no en un comando

docker run no es un despliegue. Es un recordatorio de que alguien tuvo que escribir algo.

Lo que hace que sobreviva a un reinicio:

  • Una unidad de systemd de usuario por despliegue, no un script suelto en tu historial.
  • linger habilitado para tu usuario si usas unidades de usuario. Sin esto, el servicio no existe hasta que haces login, y un servidor que espera login no es un servidor.
  • Un ExecStop que pare los dos nodos y deje el almacenamiento compartido disponible para el siguiente arranque. Si parar es manual, vas a dejar contenedores huérfanos.

Y un detalle que nos ha ahorrado cargas de veinte minutos: la unidad debe adoptar el servidor existente si ya está sano. Tras un reinicio, si los dos contenedores y el health ya existen, no tiene sentido volver a leer 150 GiB de pesos. Comprueba antes de cargar.

Worker primero, siempre

El lanzador tiene que arrancar el nodo worker antes que el head, porque el head espera un rendezvous que el worker tiene que presentar.

No arranques el worker a mano. Lo hace el head por SSH. Si lo levantas tú, te cargas el orden de negociación y te queda un sistema que parece levantado y no lo está.

Esto aplica también a la parada: no borres contenedores a mano mientras haya una rotación activa. El orquestador está en medio de una transacción y tú acabas de borrarle una pata.

Cómo saber si realmente está repartido

Esto es lo más útil de la lista, porque un cluster mal configurado arranca y responde. No da error. Simplemente no está haciendo lo que crees.

Inspecciona el comando real del contenedor de cada nodo y comprueba:

En el head En el worker
--nnodes 2 --nnodes 2
--node-rank 0 --node-rank 1
--master-addr <IP del head> la misma

Si los dos tienen --node-rank 0, tienes dos servidores distintos que se creen el jefe.

Y sobre RDMA: el identificador de ruta (GID) que funciona no es el mismo en los dos extremos. En nuestro caso son valores deliberadamente distintos por nodo. Homogeneizarlos “para que queden iguales” es el tipo de cambio que parece limpieza y rompe la comunicación sin avisar. Además pueden cambiar tras un reinicio (P-092). Si los tocas, repite la prueba de NCCL.

Antes de actualizar nada, haz un backup fechado

No del modelo. De la integración: las rutas del gateway, el catálogo de perfiles, la configuración del controlador, el script de arranque y el .env.

Después, en este orden:

  1. Verifica los pesos sin tocar el servicio activo (check-weights o lo que tu receta ofrezca).
  2. Valida la nueva versión en una ventana de rotación, sin descarga y con el almacenamiento compartido que ya tienes: --no-download te ahorra volver a bajar nada y te deja probar la config.
  3. Repite el banco de pruebas: salud, chat, llamada a herramienta, visión, razonamiento, contexto largo, concurrencia.
  4. Solo ahora cambias el commit fijado en el servicio y el catálogo.

Si la versión nueva no arranca, restauras el backup y vuelves al perfil anterior. Los pesos del checkpoint no se borran en el rollback: si los borras, un rollback de dos minutos se convierte en una descarga de dos horas.

Cuando falle, no subas el porcentaje de memoria

Este es el instinto equivocado más caro que existe. El health falla, piensas “le falta memoria”, subes el porcentaje de GPU… y en una máquina de memoria unificada puedes bloquear el arranque por reservar de más, o dejar sin aire al sistema.

Antes de tocar un número, mira:

  • memoria libre ahora, no la que creías
  • temperatura y estado de la GPU
  • los logs de ambos nodos, no solo del head
  • el estado del orquestador

Si los contenedores no existen, vuelve a lanzar la unidad: hará la carga completa. Si la versión nueva simplemente no arranca, no insistas con parámetros — restaura y vuelve atrás. Un fallo documentado vale más que un éxito forzado a base de variable.

Y durante una incidencia: nada de docker system prune. Es la forma más rápida de borrar el artefacto que estabas a punto de diagnosticar.

Comprueba que rota, no solo que arranca

Un despliegue que funciona cuando lo arrancas a mano y no funciona después de un reinicio no está desplegado, está montado.

Las tres pruebas que valen:

  1. Reinicia la máquina y comprueba que el servicio está solo, sin que nadie entre.
  2. Pide el perfil que ya está activo y verifica que el resultado es “no hago nada” en lugar de recargar pesos. Si no existe ese camino, cada toque en el panel es una carga de veinte minutos.
  3. Detén y vuelve a arrancar y cronometra. El primer arranque o un reinicio completo tarda varios minutos por nodo leyendo pesos y calentando kernels; el timeout operativo que usamos es de 30 minutos. Si tu comprobación de salud falla a los cinco, tienes un monitor que mata despliegues sanos.

Lo que te llevas

Ninguna de estas cosas es espectacular. Una unidad de systemd, linger, un orden de arranque, un backup antes de tocar, y no subir el porcentaje de memoria cuando algo va mal.

Son la diferencia entre un clúster que funciona el día que lo montas y uno que sigue sirviendo cuando te vas de vacaciones.

Contexto: probado en dos ASUS Ascent GX10 (GB10, 128 GB unificados por nodo) con tensor parallel 2 sobre red RDMA directa. Las cifras de rendimiento están en Benchmarks y el detalle de cada toma en el registro de medidas. Los comandos internos no se publican: lo que aquí sale es el método, no nuestra infraestructura.