1ms 이하로 VM을 띄운다고? Firecracker와 CoW를 활용한 극단적인 샌드박싱 (Zeroboot 리뷰)
최근 AI 에이전트 생태계를 보면 다들 비슷한 문제로 골머리를 앓고 있습니다. LLM이 생성한 파이썬 코드를 어디서 안전하게 실행할 것인가? 보안을 생각하면 VM이나 컨테이너 기반의 샌드박스가 필수적인데, 문제는 ‘초기화 지연시간(Cold Start Latency)‘입니다.
E2B나 Daytona 같은 기존 솔루션들은 훌륭하지만 여전히 100ms 이상의 부팅 시간이 필요합니다. 일반적인 웹 백엔드라면 100ms는 감내할 수 있는 수준이겠지만, AI 에이전트가 수십 개의 코드를 투기적(Speculative)으로 병렬 실행하며 결과를 비교해야 하는 상황이라면 이야기가 달라집니다.
이런 와중에 해커뉴스에 흥미로운 프로젝트가 하나 올라왔습니다. Firecracker와 CoW(Copy-on-Write) 메모리 포크를 이용해 VM 샌드박스 생성 시간을 1ms 이하로 줄였다고 주장하는 Zeroboot입니다.
아키텍처 Deep Dive: VM 단위의 fork()
기본적인 아이디어는 굉장히 단순하면서도 우아합니다. 리눅스 프로세스의 fork() 시스템 콜이 작동하는 방식을 그대로 VM 단위로 끌어올린 것입니다.
Zeroboot의 동작 방식은 다음과 같습니다.
- Template (One-time): Firecracker로 초기 VM을 부팅하고 런타임(예: Python)을 메모리에 로드한 뒤, CPU 상태와 메모리를 스냅샷으로 뜹니다.
- Fork (~0.8ms): 새로운 KVM VM을 생성하고, 앞서 만든 스냅샷 메모리를
mmap(MAP_PRIVATE)을 통해 CoW 방식으로 매핑합니다. - Isolation: 각 포크는 하드웨어 수준에서 메모리가 격리된 독립적인 KVM VM으로 동작합니다.
# Zeroboot API 호출 예시
curl -X POST https://api.zeroboot.dev/v1/exec \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer zb_demo_hn2026' \
-d '{"code":"import numpy as np; print(np.random.rand(3))"}'
벤치마크 결과를 보면 p50 Latency가 0.79ms입니다. 기존 솔루션들이 150ms 언저리인 것을 감안하면 엄청난 성능 향상입니다.
메모리 효율성도 인상적입니다. 베이스 오버헤드는 265KB에 불과합니다. 실제 Numpy 같은 무거운 워크로드를 돌리면 27MB 정도가 필요하지만, CoW의 특성상 읽기 전용 페이지는 호스트 메모리를 공유합니다. 테스트 결과에 따르면 100개의 VM이 Numpy를 실행할 때 2.4GB의 메모리를 공유하고, VM당 프라이빗 메모리는 1.75MB 수준에 그쳤다고 합니다.
시니어 엔지니어의 시선: 이것은 은총알인가?
솔직히 말해서 저는 이런 류의 ‘극단적인 최적화’를 볼 때마다 약간의 방어기제가 작동합니다. 이 패턴, 우리 예전에도 본 적 있지 않나요? 안드로이드의 Zygote 프로세스 모델이나, 2000년대 초반 FastCGI가 프로세스 풀을 미리 띄워두고 요청을 처리하던 방식과 본질적으로 같습니다.
단일 노드에서의 밀도(Density)와 속도는 확실히 매력적입니다. 50달러짜리 단일 서버에서 1000개의 샌드박스를 동시에 띄울 수 있다는 건 엄청난 가성비죠. 하지만 프로덕션 레벨로 넘어가면 몇 가지 심각한 고민거리가 생깁니다.
첫 번째는 크로스 노드 클로닝(Cross-node Cloning) 문제입니다. 단일 장비 안에서는 CoW로 메모리를 공유하면 그만이지만, 분산 환경에서는 스냅샷과 메모리 상태를 다른 노드로 마이그레이션해야 합니다. 작성자도 userfaultfd를 이용한 원격 페이지 패치를 고려 중이라고 언급했는데, 네트워크를 타는 순간 서브 밀리초라는 장점은 퇴색될 수밖에 없습니다.
해커뉴스를 달군 보안 이슈: 엔트로피와 ASLR
기술적으로 가장 흥미로웠던 논의는 해커뉴스 스레드에서 벌어진 ‘엔트로피(Entropy)’ 문제였습니다. VM을 메모리 상태까지 완벽하게 복제해버리면 무슨 일이 발생할까요?
- PRNG State Cloning: 복제된 모든 VM이 정확히 동일한 난수 생성기(PRNG) 상태를 가지게 됩니다. 즉, 두 개의 샌드박스에서 난수를 뽑으면 똑같은 값이 나옵니다. 암호화 키를 생성하거나 무작위 포트 번호를 할당할 때 치명적인 보안 취약점이 됩니다.
- ASLR 우회: 메모리 레이아웃이 동일하게 복제되므로, 공격자가 한 샌드박스에서 메모리 주소를 알아내면 다른 샌드박스에도 동일한 공격 벡터를 사용할 수 있습니다.
물론 해결책은 있습니다. Firecracker가 지원하는 ACPI vmgenid를 통해 리눅스 커널의 난수 풀을 리시딩(Reseeding)할 수 있습니다. 하지만 Numpy 같은 유저스페이스 애플리케이션의 PRNG는 커널이 알아서 초기화해주지 않으므로, 포크 직후에 명시적으로 리시딩을 해줘야 합니다. ASLR 문제 역시 스냅샷을 주기적으로 교체하고 이미지를 퍼블릭에 공개하지 않는 방식(Security by Obscurity에 가깝지만)으로 완화해야 합니다.
결론: 장난감인가, 미래인가?
Zeroboot은 현재 프로덕션 환경에 바로 투입하기엔 무리가 있는 프로토타입입니다. 보안 문제, 멀티 노드 확장성, 다양한 의존성 관리 등 풀어야 할 숙제가 산더미입니다.
하지만 이 프로젝트가 제시하는 방향성 에는 전적으로 동의합니다. AI 에이전트가 코드를 작성하고 실행하는 행위는 점차 인프라 프로비저닝이 아니라 단순한 ‘함수 호출(Function Call)’ 수준으로 가벼워져야 합니다. 1ms 이하의 지연시간이 보장된다면, 에이전트가 10가지 다른 방식으로 코드를 병렬 실행해보고 가장 결과가 좋은 것을 선택하는 식의 ‘투기적 실행(Speculative Execution)’ 아키텍처가 가능해집니다.
단일 노드에서 극단적인 성능이 필요한 AI 툴링을 만들고 있다면, 이 프로젝트의 코드를 뜯어보는 것만으로도 꽤 많은 영감을 얻을 수 있을 것입니다.
References:
- 원문 및 GitHub: https://github.com/adammiribyan/zeroboot
- Hacker News 토론: https://news.ycombinator.com/item?id=47412569