Escalando para 1 Milhão de Sandboxes Simultâneos em Segundos

@modal
INGLÊShá 1 dia · 16 de jul. de 2026
128K
415
41
14
515

TL;DR

A Modal explica sua transição de uma arquitetura centralizada para um modelo descentralizado focado em workers, que permite o lançamento de 1 milhão de sandboxes em segundos.

Este post foi escrito por Colin Weld e Connor Adams. Leia aqui ou em nosso blog.

Na Modal, construímos sandboxes, entre outras coisas. Agentes rodam em sandboxes, e os agentes estão dominando o software. Hoje, a Modal executa milhões de sandboxes por dia, suporta até cinquenta mil sandboxes simultâneas por cliente e oferece suporte a uma variedade de casos de uso em escala, desde aprendizado por reforço até agentes em segundo plano.

Cada vez mais, nossos usuários exigem mais e mais sandboxes, criadas em taxas cada vez mais altas. O aprendizado por reforço pode exigir a execução de milhões de sandboxes simultaneamente e a criação de picos de centenas de milhares de sandboxes no início das implantações. Da mesma forma, os agentes exigem cada vez mais escala massiva e altas taxas de criação simultânea para lidar com picos de tráfego.

Nossa plataforma de sandbox existente é muito boa, mas não foi projetada para essas escalas; nem qualquer outra solução existente. Somos obcecados por escala e desempenho, e queremos que nossa infraestrutura acelere o crescimento dos agentes, não adicione atrito. Então, voltamos à estaca zero.

Nos últimos meses, reconstruímos nossa plataforma principal de sandbox do zero, tanto para escala quanto para confiabilidade. Em nosso novo sistema, os usuários podem executar milhões de sandboxes simultaneamente e criar dezenas de milhares de sandboxes por segundo. Removemos todos os gargalos centrais do nosso plano de controle para que não haja limites práticos de escalabilidade, e otimizamos cada parte do agendamento e inicialização de contêineres, simplificando o caminho de agendamento para uma camada de balanceadores de carga que criam contêineres diretamente em nossa frota de workers.

Como demonstração do que nossa plataforma é capaz, executamos um milhão de sandboxes simultaneamente, criando todo o 1 milhão em menos de um minuto.

Modal - inline image

Evidência de que podemos executar muitas sandboxes.

Por que a maioria das soluções não escala

Executar 1 milhão de sandboxes leva ao limite qualquer plataforma de contêineres, tanto pelo grande número de contêineres, mas também porque executar tantas sandboxes requer dezenas de milhares de nós de computação. Haverá muitas operações que são O(contêineres), O(nós) ou ambas, o que fará com que as plataformas de contêineres tradicionais atinjam limites de escalabilidade.

Para o Kubernetes, por exemplo:

  • o algoritmo de agendamento é O(n x p) para n nós e p pods no pior caso, e o agendamento é serializado por padrão.
  • cada pod causa várias gravações no etcd (o armazenamento durável central do Kubernetes) ao longo de sua vida útil, o que pode criar problemas sérios sob altas taxas de criação de pods ou alta rotatividade de pods, e o etcd não é nativamente fragmentável dentro de um keyspace.
  • cada nó deve gravar no etcd pelo menos uma vez por intervalo de heartbeat para sinalizar atividade, então a carga base de gravação no etcd é O(nós), completamente independente da criação de pods.
Modal - inline image

Aproximação do fluxo de agendamento do Kubernetes. Novos pods são gravados no etcd (um armazenamento durável fortemente consistente) pelo servidor de API. O agendador do Kubernetes monitora novos pods não atribuídos e os atribui a nós por meio de uma chamada ao servidor de API, que novamente grava no etcd; após essa gravação ser concluída, um nó pode iniciar o pod.

O Kubernetes pode ser escalado, mas requer um trabalho sério. Para executar um grande número de nós, o etcd geralmente precisa ser reescrito ou substituído. Suportar alta taxa de transferência de agendamento requer a construção de um sistema complexo de scatter-gather para paralelizar o algoritmo de agendamento, mantendo ao mesmo tempo uma única fonte da verdade para o estado do pod. Fragmentação e paralelização não são fáceis por padrão, porque o Kubernetes depende de consistência forte como espinha dorsal de seu design.

A arquitetura de sandbox original da Modal tem problemas semelhantes. Assim como o Kubernetes, dependemos de consistência forte em todo o nosso backend, portanto, criar e agendar sandboxes requer coordenação global e gravações O(sandboxes) no Postgres, que não podemos fragmentar trivialmente.

Modal - inline image

Arquitetura original do plano de controle de sandbox da Modal. Quando as sandboxes são criadas, elas são colocadas em uma fila e gravadas no Postgres. O agendamento é otimista e executado em paralelo, com coordenação central necessária para evitar conflitos. Atribuir uma sandbox a um worker (nó de computação) requer uma gravação adicional no Postgres.

Como não construímos sobre o Kubernetes, conseguimos escalar muitas partes deste sistema. Por exemplo, o agendamento é paralelizado por padrão, o que nos permite alcançar taxas de criação de sandbox em pico muito altas. Mas, à medida que escalávamos para números cada vez maiores de nós e sandboxes, encontrávamos continuamente novos gargalos decorrentes de operações que eram O(sandboxes) ou O(nós), mas que não eram fáceis de escalar.

Por exemplo, executamos um workflow durável para cada sandbox que termina, então altas taxas de rotatividade de sandbox criariam enormes acúmulos de eventos. Constantemente esbarravamos em RPCs chamados a uma taxa de O(sandboxes) que causavam problemas de carga inesperados em todo o sistema. E o grande número de nós necessários para executar um grande número de sandboxes causava múltiplos problemas downstream no gerenciamento de nós e no auto-escalonamento. Por fim, mesmo que pudéssemos contornar isso, deixar uma instância do Postgres não fragmentada no caminho crítico de toda criação e agendamento de sandboxes havia se mostrado uma má ideia.

Desbloqueando escala infinita

Rapidamente percebemos que alcançar a escala que desejávamos exigia repensar nossa arquitetura do zero. Queremos executar milhões de sandboxes e criar dezenas de milhares de sandboxes por segundo, o que requer propriedades de escalabilidade muito melhores do que qualquer coisa existente. Em vez de tentar evoluir o que tínhamos, acreditamos que o caminho mais rápido e limpo era começar do zero.

Para otimizar para escala, decidimos que tudo que gera carga O(sandboxes) ou O(nós) deve ser horizontalmente escalável por padrão, o caminho de criação de sandbox deve ser o mais simples possível, e todo o resto deve ser secundário. A solução a que chegamos é notavelmente diferente dos sistemas existentes. Abandonamos completamente qualquer tipo de coordenação central e trocamos consistência global por escalabilidade e desempenho em todos os lugares no caminho crítico para executar e criar sandboxes. Aqui está como funciona:

  • Em vez de um único agendador serializado, executamos uma frota de servidores de agendamento que lidam com solicitações de criação de sandbox simultaneamente. Para lidar com uma solicitação de criação, um servidor de agendamento executa um algoritmo de agendamento rápido contra dados armazenados em cache na memória. O resultado é que o agendamento escala horizontalmente e se parece mais com balanceamento de carga do que com agendamento tradicional de contêineres.
  • Em vez de um armazenamento de dados central e durável atuando como a fonte da verdade para o estado da sandbox e do worker, que é como a maioria das plataformas de contêineres funciona, cada worker em nosso novo sistema é sua própria fonte da verdade. Os workers publicam seu estado periodicamente em um stream do Redis. Os servidores de agendamento consomem esse estado de forma assíncrona e o usam para tomar decisões de agendamento. Uma vez que um servidor de agendamento decide em qual worker criar uma sandbox, ele contata o worker diretamente via RPC para solicitar que uma sandbox seja criada. Os workers aceitam a solicitação de agendamento se tiverem recursos livres, caso contrário, a rejeitam.
  • Não temos armazenamentos de dados no caminho crítico de criação de sandbox, o que melhora a escalabilidade e a confiabilidade. Embora precisemos gravar metadados e resultados de sandbox em armazenamento durável, fazemos isso em grande parte de forma assíncrona.
  • Além das criações de sandbox, não temos RPCs que sejam O(sandboxes). Os workers agrupam mensagens de controle para múltiplas sandboxes em RPCs únicos, no espírito das ideias de design orientado a dados.
Modal - inline image

Nosso design final, a primeira vez que o esboçamos no quadro branco.

Modal - inline image

Caminho de criação de sandbox na arquitetura de sandbox v2 da Modal. As solicitações de criação de sandbox são tratadas por servidores de agendamento escalados horizontalmente, que então selecionam um worker com um algoritmo rápido de balanceamento de carga em memória e contatam o worker (nó de computação) diretamente para criar uma sandbox. Os objetos de sandbox são armazenados no Redis, mas não no caminho crítico.

O resultado é que o caminho de criação de sandbox requer apenas dois saltos de rede e uma operação de CPU barata. Não há gargalos centrais ou custos de coordenação, nenhum ponto único de falha e, consequentemente, nenhum teto prático para a escala agregada de sandbox ou taxa de transferência de criação de sandbox. Podemos adicionar mais agendadores ou workers conforme necessário. O gargalo mais iminente é que todos os workers publicam estado em um único stream do Redis, mas os testes de carga sugeriram que isso permanece viável até bem mais de 100.000 workers; e não dependemos de ordenação no stream de qualquer maneira, então seria fácil apenas adicionar mais streams. Por design, evitamos os problemas que impedem as soluções existentes de escalar.

Construir esta solução não foi fácil! Todo o processo de desenvolvimento levou meses de trabalho, abrangendo a maioria dos sistemas principais em nosso backend. Passamos horas em quadros brancos. Quatro de nós nos mudamos para uma casa alugada em Miami Beach para construir um protótipo do novo sistema que queríamos, sem distrações. Passamos oito dias escrevendo código até não aguentarmos mais fisicamente, jogando xadrez rápido para nos recuperar, pulando no oceano e depois voltando direto para o código, lutando para deixar nosso novo sistema limpo e funcional.

Modal - inline image

Nosso melhor engenheiro relaxando em Miami Beach.

Depois que conseguimos fazer as peças principais funcionarem (e voltamos para Nova York), também precisamos reimplementar cada recurso de Sandbox e toda a observabilidade de Sandbox sobre nosso novo sistema. Este projeto também exigiu mudanças em nossa pilha principal de gerenciamento de workers, bem como em nosso runtime de contêineres. Por exemplo, um problema interessante que encontramos é que nossos novos agendadores de sandbox podiam enviar contêineres para os workers tão rapidamente que muitos contêineres iniciando ao mesmo tempo disputariam o bloqueio rtnl no kernel do Linux ao configurar as regras de rede do contêiner e levariam dezenas de segundos para iniciar, então tivemos que mudar nossa configuração de rede de contêiner para sandboxes apenas para que nossos workers não explodissem quando inundados com criações de sandbox.

Como nosso desempenho se compara

Fizemos um benchmark do nosso sistema iniciando 1 milhão de sandboxes o mais rápido possível. Em um nível alto, podemos criar um milhão de sandboxes em menos de um minuto, onde o principal gargalo é o próprio benchmark. O tempo de interatividade individual da sandbox permanece consistentemente baixo, e não vemos degradações reais com a escala.

Modal - inline image

Distribuição e eCDF das solicitações de criação de sandbox. Uma solicitação de criação de sandbox retorna quando nossos servidores de agendamento atribuíram com sucesso uma sandbox a um worker, e ela começou a ser iniciada.

Acreditamos que isso é esperado, dado nosso design. Não há coordenação no caminho de agendamento, portanto, o agendamento deve permanecer muito rápido, independente da concorrência e da escala. No que nos diz respeito, não temos limites sérios para o agendamento simultâneo de sandbox ou escala fora da capacidade disponível, e gerenciar a capacidade é algo que já fazemos bem.

Modal - inline image

Gráfico de dispersão de 10 mil tempos de início de sandbox do nosso teste de 1M de sandboxes, selecionados aleatoriamente do 1M de sandboxes.

Os tempos de início de sandbox em nosso novo sistema (a latência desde quando o cliente tenta criar uma sandbox pela primeira vez até quando a sandbox pode executar o código do usuário) são inferiores a meio segundo na mediana e permanecem sólidos em escala. Eles também são substancialmente mais rápidos do que nosso sistema antigo, em grande parte porque o agendamento é muito mais rápido — agora leva apenas dezenas de milissegundos. A cauda longa da latência é um pouco mais longa do que gostaríamos. Atribuímos grande parte dessa cauda à contenção do kernel e da rede (incluindo a contenção do bloqueio rtnl mencionada anteriormente) quando muitas sandboxes iniciam simultaneamente no mesmo worker, e estamos trabalhando para reduzi-la. Além disso, a cauda em escala é real. Esperamos que isso melhore à medida que otimizamos o caminho de inicialização do contêiner.

No geral, estamos muito felizes com esses números de desempenho. À medida que os agentes assumem o mundo, claramente podemos escalar com eles.

Veja você mesmo

Em breve, este novo sistema dará suporte a todo o agendamento de sandbox na Modal, mas já está disponível em Beta. Você pode optar por participar com uma simples mudança em seu código. Se você precisa executar muitas sandboxes, experimente e fale conosco!

Agradecimentos

Muitas pessoas contribuíram com sangue, suor e lágrimas para este projeto. Nosso POC em Miami foi construído por Colin Weld (eu), Daniel Shaar, Walter Tang e Gleb Posobin, e depois levado à produção por Walter, Colin, Connor Adams, Akshay Balwally, Tom Wildenhain, Scott Hao e Taylor Baldwin.

Salvar com um clique

Faça leitura profunda de artigos virais com IA no YouMind

Salve a fonte, faça perguntas específicas, resuma o argumento e transforme um artigo viral em notas reutilizáveis em um único espaço de trabalho com IA.

Explorar o YouMind
Para criadores

Transforme seu Markdown em um artigo 𝕏 impecável

Quando você publica seus próprios textos longos, formatar imagens, tabelas e blocos de código para o 𝕏 é uma dor de cabeça. O YouMind transforma um rascunho completo em Markdown em um artigo 𝕏 impecável e pronto para publicar.

Experimente Markdown para 𝕏

Mais padrões para decifrar

Artigos virais recentes

Explorar mais artigos virais