대규모 AI 에이전트를 위한 샌드박스 운영 방법

@LegitSeanSmith
영어2주 전 · 2026년 7월 03일
319K
79
11
4
73

TL;DR

Adapt의 CTO Sean Smith가 gVisor에서 Firecracker microVM으로 인프라를 전환한 과정을 상세히 설명합니다. 이를 통해 AI 에이전트 코드 실행을 위한 수천 개의 격리된 1초 미만 샌드박스 환경을 구현했습니다.

우리는 초기부터 LLM에 임의의 코드를 실행할 수 있는 권한을 부여하는 과감한 결정을 내렸습니다. 이 글은 우리가 왜 그런 결정을 내렸는지, 그리고 사람들이 에이전트와 대화를 시작하고 끝낼 때마다 수천 개의 샌드박스를 즉시 생성하고 종료하면서 이를 운영하기 위해 무엇이 필요한지에 대해 다룹니다.

사용자가 Adapt 에이전트와 나누는 모든 대화는 각자의 전용 컴퓨터에서 지원됩니다. 공유 서버의 제한된 컨테이너가 아니라, 모델이 소프트웨어 설치, 프로그램 작성 및 실행, 웹 브라우징, API 호출 등 원하는 모든 작업을 수행할 수 있는 격리된 VM(가상 머신)에서 실행됩니다. 우리는 이를 샌드박스라고 부르며, 이는 Adapt가 구축된 핵심 요소 중 하나입니다.

완벽한 제어

LLM은 코딩의 천재이며, 제 업무는 주로 그들이 작업할 수 있는 완벽한 개발 환경을 구축하는 것이었습니다.

AI를 외부 세계와 연결하는 일반적인 방법은 GitHub용 커넥터, HubSpot용 커넥터, Stripe용 커넥터와 같이 통합 기능을 직접 구축하거나, 각 서비스가 MCP 서버를 출시할 때까지 기다리는 것입니다. 하지만 이런 방식은 확장성이 떨어지며, 저는 매일같이 통합 코드를 작성하는 일에 큰 흥미가 없습니다.

그래서 우리는 그 작업을 직접 하는 대신 모델이 수행하도록 했습니다. API를 제공하는 모든 서비스는 Adapt에서 액세스할 수 있습니다. 모델이 해당 API와 통신하는 스크립트나 프로그램을 작성하는 데 필요한 모든 것을 제공하기 때문입니다. 우리가 Adapt를 "수평적 지능(horizontal intelligence)"이라고 부르는 이유가 바로 여기에 있습니다. Adapt는 고정된 도구 목록에 얽매이지 않고, 필요할 때 즉석에서 필요한 도구를 직접 구축할 수 있습니다.

이 과정의 핵심은 LLM에 샌드박스에 대한 완전한 액세스 권한을 부여하는 것입니다. 파일 시스템에 대한 액세스가 제한된 정적인 언어 및 CLI 도구 세트를 모델에 제공하는 대신, 우리는 모든 것에 대한 완전한 액세스 권한을 제공합니다. 모델은 루트(root) 권한으로 실행됩니다. 또한 우리의 샌드박스는 Node나 Python과 같은 일반적인 런타임을 포함하고 있지만, 특정 서비스의 API를 위한 최고의 SDK가 Go로 작성되어 있다면 어떻게 할까요? 모델은 그냥 직접 설치하고 실행하면 됩니다.

Sean Smith - inline image

LLM이 Go 프로그램을 작성해야 하나요? 그냥 Go를 설치하고 실행하세요.

그렇다면 모델이 원하는 것은 무엇이든 설치하고 사람이 검증하지 않은 코드를 실행하도록 허용한다면, 보안은 어떻게 확보할까요? 다행히도 신뢰할 수 없는 코드를 실행해야 했던 것은 우리가 처음이 아닙니다. 이를 위해 gVisorFirecracker라는 두 가지 매우 인기 있는 보안 런타임이 존재합니다. 우리는 그동안의 여정을 통해 이 두 가지 모두에 매우 익숙해졌습니다.

gVisor에서 Firecracker로

LLM을 위한 보안 샌드박스에 대한 우리의 첫 시도는 "쉬운" 접근 방식이었습니다. GKE(Google Kubernetes Engine) 위에서 GKE Sandbox를 사용하여 gVisor로 각 샌드박스를 실행하는 것이었죠. 우리는 이미 다른 모든 서비스를 GKE에서 운영하고 있었기 때문에 이는 자연스러운 단계였습니다.

gVisor는 컨테이너와 호스트 커널 사이에 위치합니다. 프로그램이 신뢰할 수 없는 코드가 직접 건드려서는 안 되는 실제 Linux 커널에 시스템 호출을 보내도록 하는 대신, gVisor는 사용자 공간 커널에서 해당 호출을 가로채 직접 처리합니다. 이를 통해 일반 컨테이너의 편리함을 대부분 누리면서도 공격 표면을 훨씬 줄일 수 있습니다. GKE Sandbox는 이 모든 것을 패키지로 제공합니다. Pod(컨테이너)를 배포하면 별도의 인프라 구성 없이도 gVisor 하에서 투명하게 실행됩니다.

초기에는 이 방식이 매우 잘 작동했습니다. 우리는 "기본" 샌드박스를 Docker 이미지로 정의하고 GKE가 필요한 만큼 샌드박스를 확장하도록 했습니다. 샌드박스에 포함된 소프트웨어 업데이트는 간단한 Dockerfile 수정과 매니페스트의 버전 업데이트만으로 충분했습니다.

Sean Smith - inline image

GKE Sandbox 하에서 실행되는 수백 개의 샌드박스 Pod.

하지만 gVisor를 쉽게 사용할 수 있게 해주었던 바로 그 추상화가 우리가 계속해서 부딪히는 문제였습니다. gVisor는 사용자 공간에서 Linux 시스템 호출 인터페이스를 재구현하기 때문에 모든 것이 실제 커널에서와 똑같이 작동하지는 않으며, 우리 모델이 만들어내는 워크로드는 예측 불가능함 그 자체입니다. 안전을 위해 가로채기를 수행하는 과정에서 시스템 호출 및 I/O 작업이 많은 경우 성능 저하가 발생합니다. 또한 전체 수명 주기를 GKE에 의존하게 되면서 부팅 시간, 패킹 밀도, 네트워킹, 머신 재활용 방식 등 우리가 가장 제어하고 싶었던 부분들에 대한 통제권이 가장 낮아졌습니다. 위에서 언급한 'OutOfcpu' Pod는 다른 사람의 스케줄러를 한계 이상으로 밀어붙일 때 나타나는 현상입니다.

이것이 바로 우리가 Firecracker로 눈을 돌리게 된 계기입니다.

Firecracker microVM은 하드웨어 가상화를 통해 실행되며 자체 게스트 커널을 가진 실제 가상 머신이지만, 단 몇 메가바이트의 오버헤드만으로 순식간에 부팅되도록 최적화되어 있습니다. 이는 AWS가 수많은 Lambda 및 Fargate 워크로드를 공유 하드웨어에 담기 위해 구축한 것과 동일한 기술입니다. 이 기술은 공유 커널보다 강력한 격리 경계를 제공하고, 즉각적으로 느껴질 만큼 빠르게 부팅되며, 단일 호스트에 많은 수를 담을 수 있을 만큼 작습니다.

단점은 Firecracker는 VM만 제공할 뿐 그 외의 것은 거의 제공하지 않는다는 점입니다. 스케줄링, 네트워킹, 수명 주기 오케스트레이션을 수행하는 GKE 같은 계층이 없습니다. 그래서 우리는 직접 구축했고, 이를 'orc'라고 부릅니다.

rootfs는 그저 이미지일 뿐

컨테이너에서 벗어나면서도 포기하고 싶지 않았던 것 중 하나는 샌드박스를 일반 Dockerfile로 정의하는 것이었습니다. 컨테이너는 이를 간단하게 만들어 주지만, VM은 전통적으로 microVM이 OCI 이미지가 아닌 루트 파일 시스템을 부팅하기 때문에 그렇지 못합니다.

그래서 orc는 이 둘을 연결합니다. VM 생성을 요청받으면 일반 Docker/OCI 이미지를 가져와 즉석에서 VM의 루트 파일 시스템을 생성하고, 동일한 이미지를 나중에 다시 부팅할 때 빠르게 사용할 수 있도록 결과를 캐싱합니다. 우리의 기본 샌드박스는 여전히 Dockerfile이며, orc는 요청 시 이를 부팅 가능한 rootfs로 변환합니다.

이를 통해 우리는 Dockerfile을 수정하고 새로운 샌드박스를 배포하는 기존의 워크플로우를 그대로 유지하면서도, 실제 VM 위에서 실행할 수 있게 되었습니다. 또한 이제 막 시작하려는 새로운 가능성의 문이 열렸습니다. 모든 OCI 이미지가 microVM이 될 수 있기 때문에 기본 이미지 외의 다른 이미지로도 샌드박스를 부팅할 수 있습니다. Postgres와 pgvector가 이미 포함된 VM을 원하시나요? orc에 해당 이미지를 지정하기만 하면 격리된 머신으로 즉시 얻을 수 있습니다. 샌드박스는 더 이상 고정된 단일 환경이 아니라 "작업에 필요한 모든 이미지를 VM으로 부팅하는 환경"이 됩니다.

대규모 실행

이 문제를 정말 어렵게 만드는 핵심은 모든 대화가 각자의 샌드박스를 가진다는 점입니다. 대화당 머신 하나가 할당됩니다. 어느 순간에도 수천 개의 샌드박스가 활성화되어 있으며, 그 수는 끊임없이 변합니다. 누군가 대화를 시작할 때마다 샌드박스가 나타나야 하고, 대화가 조용해지면 비용을 지불하지 않도록 샌드박스가 사라져야 합니다. 우리는 끊임없이 샌드박스를 생성하고 종료합니다.

두 가지 수치가 모든 것을 결정합니다. 샌드박스를 얼마나 빨리 준비할 수 있는지, 그리고 호스트 하나에 얼마나 많은 샌드박스를 담을 수 있는지입니다.

시작 지연 시간(Startup latency). Firecracker microVM은 수백 밀리초 만에 부팅됩니다. 이는 웜 풀(warm pool)을 유지할 필요가 없을 정도로 빠르며, 이것이 전환을 통해 얻은 가장 조용한 성과 중 하나입니다. GKE 환경에서는 시작 시간을 숨기기 위해 여분의 용량을 유지해야 했을 것입니다. orc를 사용하면 새로운 샌드박스가 눈치채기도 전에 준비되므로, 대화가 시작될 때 요청에 따라 생성하고 대화가 끝나면 종료합니다. 더 이상 관리하거나 비용을 지불할 유휴 풀(idle pool)은 없습니다.

밀도(Density). 각 microVM은 매우 작기 때문에 하나의 물리적 호스트에 많은 수를 담을 수 있습니다. 우리는 각 샌드박스의 CPU와 메모리 크기를 실제 필요한 만큼만 할당하여 과도한 프로비저닝을 방지하며, 이를 통해 수천 개의 샌드박스를 경제적으로 운영할 수 있습니다.

orc 자체는 의도적으로 작게 설계되었습니다. orc는 간단한 API를 사용하는 제어 평면입니다. 주어진 이미지에서 N개의 vCPU와 M메가바이트 메모리를 가진 VM을 생성하고, 명령어를 스트리밍하고, 내부 파일을 읽고 쓰고, 나중에 찾을 수 있도록 태그를 지정하고, 작업이 끝나면 삭제합니다. 각 게스트는 PID 1로 작은 init 프로세스를 실행하며 자체 격리된 네트워크를 가집니다. 이것이 전부입니다. 마법 같은 기교는 없으며, 이러한 기본 요소들이 지루할 정도로 단순하고 빠르기 때문에 전체 함대를 운영할 수 있는 것입니다.

이 모든 인프라 구축의 결실은 우리가 처음 시작했던 바로 그것입니다. 무엇이든 설치하고, 프로그램을 작성하고, API를 호출하고, 실제 컴퓨터에서 실행하여 결과를 돌려주는 모델 말입니다.

원클릭 저장

YouMind로 바이럴 글을 AI 심층 읽기

소스를 저장하고, 핵심 질문을 던지고, 주장을 요약해 바이럴 글을 다시 활용할 수 있는 노트로 바꾸세요. 하나의 AI 워크스페이스에서 모두 할 수 있습니다.

YouMind 둘러보기
크리에이터를 위해

당신의 Markdown을 깔끔한 𝕏 글로

직접 쓴 장문을 올릴 때 이미지, 표, 코드 블록을 𝕏에 맞게 정리하는 일은 번거롭습니다. YouMind는 전체 Markdown 초안을 깔끔하고 바로 게시할 수 있는 𝕏 글로 바꿔 줍니다.

Markdown → 𝕏 사용해 보기

분석할 패턴 더 보기

최근 바이럴 아티클

더 많은 바이럴 아티클 보기