Escalando a 1 millón de sandboxes concurrentes en segundos

@modal
INGLÉShace 1 día · 16 jul 2026
128K
415
41
14
515

TL;DR

Modal explica su transición de una arquitectura centralizada a un modelo descentralizado centrado en el trabajador, que permite lanzar 1 millón de sandboxes en segundos.

Esta publicación fue escrita por Colin Weld y Connor Adams. Léela aquí o en nuestro blog.

En Modal, construimos sandboxes, entre otras cosas. Los agentes se ejecutan en sandboxes, y los agentes se están comiendo el software. Hoy, Modal ejecuta millones de sandboxes por día, soporta hasta cincuenta mil sandboxes concurrentes por cliente y respalda una variedad de casos de uso a escala, desde aprendizaje por refuerzo hasta agentes en segundo plano.

Cada vez más, nuestros usuarios requieren más y más sandboxes, creados a tasas cada vez más altas. El aprendizaje por refuerzo puede requerir ejecutar millones de sandboxes de forma concurrente y crear ráfagas de cientos de miles de sandboxes al inicio de los despliegues. De manera similar, los agentes requieren cada vez más una escala masiva y altas tasas de creación concurrente para manejar picos de tráfico.

Nuestra plataforma de sandboxes existente es muy buena, pero no fue diseñada para estas escalas; tampoco lo es ninguna otra solución existente. Estamos obsesionados con la escala y el rendimiento, y queremos que nuestra infraestructura acelere el crecimiento de los agentes, no que añada fricción. Así que volvimos a la mesa de dibujo.

En los últimos meses, hemos reconstruido nuestra plataforma central de sandboxes desde cero, tanto para escala como para fiabilidad. En nuestro nuevo sistema, los usuarios pueden ejecutar millones de sandboxes de forma concurrente y crear decenas de miles de sandboxes por segundo. Hemos eliminado todos los cuellos de botella centrales de nuestro plano de control, por lo que no hay límites prácticos de escalado, y hemos optimizado cada parte de la planificación y el inicio de contenedores, simplificando la ruta de planificación a una capa de balanceadores de carga que crean contenedores directamente en nuestra flota de workers.

Como demostración de lo que nuestra plataforma es capaz, hemos ejecutado un millón de sandboxes de forma concurrente, creando el millón completo en menos de un minuto.

Modal - inline image

Evidencia de que podemos ejecutar muchos sandboxes.

Por qué la mayoría de las soluciones no escalan

Ejecutar 1 millón de sandboxes lleva al límite a cualquier plataforma de contenedores, tanto por la gran cantidad de contenedores como porque ejecutar tantos sandboxes requiere decenas de miles de nodos de cómputo. Habrá muchas operaciones que son O(contenedores), O(nodos) o ambas, lo que hará que las plataformas tradicionales de contenedores alcancen límites de escalado.

Para Kubernetes, por ejemplo:

  • el algoritmo de planificación es O(n x p) para n nodos y p pods en el peor de los casos, y la planificación está serializada por defecto.
  • cada pod causa múltiples escrituras en etcd (el almacén duradero central de Kubernetes) durante su ciclo de vida, lo que puede crear problemas graves bajo altas tasas de creación de pods o alta rotación de pods, y etcd no se puede fragmentar de forma nativa dentro de un espacio de claves.
  • cada nodo debe escribir en etcd al menos una vez por intervalo de latido para indicar que está vivo, por lo que la carga de escritura base de etcd es O(nodos) completamente independiente de la creación de pods.
Modal - inline image

Aproximación del flujo de planificación de Kubernetes. Los nuevos pods se escriben en etcd (un almacén duradero fuertemente consistente) a través del servidor API. El planificador de Kubernetes observa nuevos pods no asignados y los asigna a nodos mediante una llamada al servidor API, que nuevamente escribe en etcd; después de que esta escritura se completa, un nodo puede iniciar el pod.

Kubernetes se puede escalar, pero requiere trabajo serio. Para ejecutar grandes cantidades de nodos, etcd generalmente debe ser reescrito o reemplazado. Soportar un alto rendimiento de planificación requiere construir un sistema complejo de dispersión-recopilación para paralelizar el algoritmo de planificación mientras se mantiene una única fuente de verdad para el estado de los pods. La fragmentación y la paralelización no son fáciles por defecto, porque Kubernetes se basa en la consistencia fuerte como columna vertebral de su diseño.

La arquitectura original de sandboxes de Modal tiene problemas similares. Al igual que Kubernetes, confiamos en la consistencia fuerte en todo nuestro backend, por lo que crear y planificar sandboxes requiere coordinación global y escrituras O(sandboxes) en Postgres, que no podemos fragmentar trivialmente.

Modal - inline image

Arquitectura original del plano de control de sandboxes de Modal. Cuando se crean sandboxes, se colocan en una cola y se escriben en Postgres. La planificación es optimista y se ejecuta en paralelo, con coordinación central necesaria para evitar conflictos. Asignar un sandbox a un worker (nodo de cómputo) requiere una escritura adicional en Postgres.

Debido a que no construimos sobre Kubernetes, hemos podido escalar muchas partes de este sistema. Por ejemplo, la planificación está paralelizada por defecto, lo que nos permite lograr tasas de creación de sandboxes en ráfaga muy altas. Pero a medida que escalamos a números cada vez mayores de nodos y sandboxes, nos encontramos continuamente con nuevos cuellos de botella derivados de operaciones que eran O(sandboxes) o O(nodos) pero no eran fáciles de escalar.

Por ejemplo, ejecutamos un workflow duradero para cada sandbox que finaliza, por lo que las altas tasas de rotación de sandboxes creaban enormes acumulaciones de eventos. Nos topábamos repetidamente con RPCs llamados a una tasa de O(sandboxes) que causaban problemas de carga inesperados en todo nuestro sistema. Y la gran cantidad de nodos necesarios para ejecutar grandes cantidades de sandboxes causaba múltiples problemas secundarios en la gestión de nodos y el autoescalado. Por último, aunque podíamos sortearlo, dejar una instancia de Postgres sin fragmentar en la ruta crítica de toda la creación y planificación de sandboxes había demostrado ser una mala idea.

Desbloqueando la escala infinita

Rápidamente nos dimos cuenta de que alcanzar la escala que deseábamos requería replantear nuestra arquitectura desde cero. Queremos ejecutar millones de sandboxes y crear decenas de miles de sandboxes por segundo, lo que requiere propiedades de escalado mucho mejores que cualquier cosa existente. En lugar de intentar evolucionar lo que teníamos, creímos que el camino más rápido y limpio era empezar de nuevo.

Para optimizar la escala, decidimos que todo lo que genera carga O(sandboxes) u O(nodos) debe ser horizontalmente escalable por defecto, la ruta de creación de sandboxes debe ser lo más simple posible, y todo lo demás debe ser secundario. La solución a la que llegamos es notablemente diferente de los sistemas existentes. Prescindimos por completo de cualquier tipo de coordinación central e intercambiamos consistencia global por escalabilidad y rendimiento en todas partes de la ruta crítica para ejecutar y crear sandboxes. Así es como funciona:

  • En lugar de un único planificador serializado, ejecutamos una flota de servidores de planificación que manejan las solicitudes de creación de sandboxes de forma concurrente. Para manejar una solicitud de creación, un servidor de planificación ejecuta un algoritmo de planificación rápido contra datos almacenados en caché en memoria. El resultado es que la planificación escala horizontalmente y se parece más a un balanceo de carga que a la planificación tradicional de contenedores.
  • En lugar de un almacén de datos central y duradero que actúe como fuente de verdad para el estado de los sandboxes y workers, que es como funcionan la mayoría de las plataformas de contenedores, cada worker en nuestro nuevo sistema es su propia fuente de verdad. Los workers publican su estado periódicamente en un stream de Redis. Los servidores de planificación consumen este estado de forma asíncrona y lo utilizan para tomar decisiones de planificación. Una vez que un servidor de planificación decide en qué worker crear un sandbox, se comunica directamente con el worker mediante RPC para solicitar que se cree un sandbox. Los workers aceptan la solicitud de planificación si tienen recursos libres, o la rechazan en caso contrario.
  • No tenemos almacenes de datos en la ruta crítica de la creación de sandboxes en absoluto, lo que mejora la escalabilidad y la fiabilidad. Aunque necesitamos escribir metadatos y resultados de sandboxes en almacenamiento duradero, lo hacemos mayormente de forma asíncrona.
  • Aparte de las creaciones de sandboxes, no tenemos RPCs que sean O(sandboxes). Los workers agrupan mensajes de control para múltiples sandboxes en RPCs individuales, siguiendo el espíritu de las ideas del diseño orientado a datos.
Modal - inline image

Nuestro diseño final, la primera vez que lo dibujamos en la pizarra.

Modal - inline image

Ruta de creación de sandboxes en la arquitectura v2 de Modal. Las solicitudes de creación de sandboxes son manejadas por servidores de planificación escalados horizontalmente, que luego seleccionan un worker con un algoritmo rápido de balanceo de carga en memoria y se comunican directamente con el worker (nodo de cómputo) para crear un sandbox. Los objetos de sandbox se almacenan en Redis, pero no en la ruta crítica.

El resultado es que la ruta de creación de sandboxes requiere solo dos saltos de red y una operación de CPU barata. No hay cuellos de botella centrales ni costos de coordinación, no hay puntos únicos de fallo y, en consecuencia, no hay un límite práctico para la escala agregada de sandboxes ni el rendimiento de creación de sandboxes. Podemos agregar más planificadores o workers según sea necesario. El cuello de botella más inminente es que todos los workers publican estado en un único stream de Redis, pero las pruebas de carga han sugerido que esto sigue siendo viable hasta bien pasados los 100,000 workers; y no dependemos del orden en el stream de todos modos, por lo que sería fácil agregar más streams. Por diseño, evitamos los problemas que impiden que las soluciones existentes escalen.

¡Construir esta solución no fue fácil! Todo el proceso de desarrollo ha llevado meses de trabajo, abarcando la mayoría de los sistemas principales de nuestro backend. Pasamos horas frente a pizarras. Cuatro de nosotros nos trasladamos a una casa de alquiler en Miami Beach para construir un prototipo del nuevo sistema que queríamos, sin distracciones. Pasamos ocho días escribiendo código hasta que físicamente no podíamos más, jugando ajedrez rápido para recuperarnos, saltando al océano y luego volviendo directamente al código, luchando para que nuestro nuevo sistema quedara limpio y funcional.

Modal - inline image

Nuestro mejor ingeniero relajándose en Miami Beach.

Una vez que logramos que las piezas centrales funcionaran (y regresamos a Nueva York), también necesitamos reimplementar cada característica de Sandbox y toda la observabilidad de Sandbox sobre nuestro nuevo sistema. Este proyecto también requirió cambios en nuestra pila central de gestión de workers, así como en nuestro runtime de contenedores. Por ejemplo, un problema interesante que encontramos es que nuestros nuevos planificadores de sandboxes podían enviar contenedores a los workers tan rápido que muchos contenedores iniciándose al mismo tiempo competían por el bloqueo rtnl en el kernel de Linux al configurar las reglas de red de los contenedores, tardando decenas de segundos en iniciarse, así que tuvimos que cambiar nuestra configuración de red de contenedores para sandboxes solo para que nuestros workers no explotaran cuando se vieran inundados de creaciones de sandboxes.

Cómo se compara nuestro rendimiento

Evaluamos nuestro sistema iniciando 1 millón de sandboxes lo más rápido que pudimos. A alto nivel, podemos crear un millón de sandboxes en menos de un minuto, donde el principal cuello de botella es la propia prueba de rendimiento. El tiempo individual hasta la interactividad de los sandboxes se mantiene consistentemente bajo, y no vemos degradaciones reales con la escala.

Modal - inline image

Distribución y eCDF de las solicitudes de creación de sandboxes. Una solicitud de creación de sandbox devuelve un resultado cuando nuestros servidores de planificación han asignado correctamente un sandbox a un worker y este ha comenzado a iniciarse.

Creemos que esto es esperado, dado nuestro diseño. No hay coordinación en la ruta de planificación, por lo que la planificación debería permanecer muy rápida independientemente de la concurrencia y la escala. Por lo que a nosotros respecta, no tenemos límites serios para la planificación concurrente de sandboxes o la escala fuera de la capacidad disponible, y gestionar la capacidad es algo que ya hacemos bien.

Modal - inline image

Diagrama de dispersión de 10k tiempos de inicio de sandboxes de nuestra prueba de 1M de sandboxes, seleccionados aleatoriamente del millón.

Los tiempos de inicio de sandboxes en nuestro nuevo sistema (la latencia desde que el cliente intenta crear un sandbox por primera vez hasta que el sandbox puede ejecutar código de usuario) son inferiores a medio segundo en la mediana y se mantienen sólidos a escala. También son sustancialmente más rápidos que nuestro sistema anterior, en gran medida porque la planificación es mucho más rápida: ahora solo toma decenas de milisegundos. La cola larga de latencia es algo más larga de lo que nos gustaría. Atribuimos gran parte de esta cola a la contención del kernel y la red (incluida la contención del bloqueo rtnl mencionada anteriormente) cuando muchos sandboxes se inician simultáneamente en el mismo worker, y estamos trabajando para reducirla. Además, la cola a escala es real. Esperamos que esto mejore a medida que optimicemos la ruta de inicio de contenedores.

En general, estamos muy satisfechos con estos números de rendimiento. A medida que los agentes se apoderan del mundo, claramente podemos escalar con ellos.

Compruébalo tú mismo

Pronto este nuevo sistema respaldará toda la planificación de sandboxes en Modal, pero ya está disponible en Beta. Puedes optar por él con un simple cambio en tu código. Si necesitas ejecutar muchos sandboxes, pruébalo y ¡habla con nosotros!

Agradecimientos

Muchas personas contribuyeron con sangre, sudor y lágrimas a este proyecto. Nuestro POC de Miami fue construido por Colin Weld (yo), Daniel Shaar, Walter Tang y Gleb Posobin, y luego llevado a producción por Walter, Colin, Connor Adams, Akshay Balwally, Tom Wildenhain, Scott Hao y Taylor Baldwin.

Guardar con un clic

Lee artículos virales en profundidad con IA en YouMind

Guarda la fuente, haz preguntas concretas, resume el argumento y convierte un artículo viral en notas reutilizables en un único espacio de trabajo con IA.

Explora YouMind
Para creadores

Convierte tu Markdown en un artículo de 𝕏 impecable

Cuando publicas tus propios textos largos, dar formato en 𝕏 a imágenes, tablas y bloques de código es un fastidio. YouMind convierte un borrador completo en Markdown en un artículo de 𝕏 impecable y listo para publicar.

Prueba Markdown a 𝕏

Más patrones por descifrar

Artículos virales recientes

Explorar más artículos virales