Browser Use: EC2에서 Firecracker microVM을 실행하여 고성능 클라우드 브라우저 구현

Browser Use는 브라우저 시간당 비용을 $0.06에서 $0.02로 낮추고 VM 콜드 스타트 시간을 400ms 미만으로 단축하기 위해 클라우드 브라우저 인프라를 재구축했습니다. 이 시스템은 모든 브라우저 세션에 개별 Firecracker microVM을 할당하여 높은 격리성을 제공하며, 비용과 확장 속도를 최적화하기 위해 이러한 VM을 일반적인 Amazon EC2 인스턴스 내에 중첩(nested)하여 실행합니다.

Unikernels에서 Firecracker로의 전환

Browser Use는 확장성 제한 문제로 인해 Unikraft unikernels에서 벗어났습니다. Unikernels는 빠른 부팅 시간과 낮은 유휴 비용을 제공했지만, 강력한 내장형 자동 확장(autoscaling) 기능이 부족하여 트래픽 급증 시 수동 엔지니어링 개입이 필요했으며, 이전에는 부하 테스트 중 45분간의 운영 중단 사태를 초래하기도 했습니다.

Firecracker는 각 브라우저를 호스트와 다른 세션으로부터 격리하면서도, 컨트롤 플레인이 VM 생성 및 모니터링을 더 효과적으로 관리할 수 있도록 하는 경량 가상화 레이어를 제공하기 위해 채택되었습니다.

자동 확장을 위한 커스텀 컨트롤 플레인

Unikernels에서 발생했던 확장성 문제를 해결하기 위해 Browser Use는 커스텀 컨트롤 플레인을 개발했습니다. 이 컨트롤 플레인은 브라우저 플릿(fleet)을 실시간으로 다음과 같이 관리합니다:

  • Host Selection: 사용자를 가용 용량이 있는 EC2 호스트에 할당합니다.
  • Dynamic Scaling: 트래픽이 증가하면 새로운 머신을 자동으로 시작하고, 제거 대상으로 표시된 호스트에 새로운 세션이 전송되는 것을 중단합니다.
  • Real-time Monitoring: 현재 시작 중인 브라우저를 추적하고 새로운 세션이 전송되지 않아야 할 호스트를 식별함으로써 표준 AWS CloudWatch 메트릭보다 빠르게 작동합니다.

EC2에서의 중첩 가상화 최적화

Firecracker는 일반적으로 베어메탈(.metal) 인스턴스에서 실행되지만, Browser Use는 일반 EC2 인스턴스를 사용합니다. 이 방식은 호스트 부팅 시간을 단축(약 30초)하고 비용을 낮출 수 있지만, 중첩 가상화(VM 내부의 VM)라는 과제를 안겨줍니다.

두 개의 하이퍼바이저 레이어를 통과하는 페이지 폴트(page fault)로 인한 지연 시간을 완기화하기 위해, 팀은 다음과 같은 메모리 및 CPU 최적화 작업을 수행했습니다:

메모리 최적화 및 페이지 폴트 감소

초기 콜드 스타트 시간은 9.8초였으며, 페이지 폴트가 VM exit의 72%를 차지했습니다. 팀은 다음과 같은 방법을 통해 이를 3.1초로 단축했습니다:

  • Increasing Page Size: 4KB 페이지를 2MB 페이지로 전환하여 페이지당 페이지 폴트 횟수를 512배 감소시켰습니다.
  • Implementing userfaultfd: Chromium이 가장 먼저 접근할 가능성이 높은 메모리 페이지를 사전 로드하기 위해 Linux userfaultfd API를 위한 커스텀 핸들러를 구현했습니다.
  • Removing Legacy Checks: 존재하지 않는 PS/2 키보드에 대한 500ms 체크 과정을 제거했습니다.
  • Optimizing Ready-Signals: HTTP 폴링을 vsock 통신 채널로 교체하여, 호스트가 브라우저가 준비되었음을 1밀리초 미만으로 감지할 수 있게 했습니다.

CPU 스케줄링 및 버스트 관리

Chromium의 시작은 CPU 집약적이지만, 운영 단계에서는 비교적 조용합니다. Browser Use는 이를 2단계 CPU 전략을 통해 관리합니다:

  • Launch Phase: 가상 CPU(vCPU)는 unpinned 상태로 유지하여 Linux가 시작 버스트를 모든 가용 호스트 코어에 분산할 수 있도록 합니다.
  • Operational Phase: 브라우저가 준비되면 vCPU를 안정적인 코어에 고정(pinned)하여 간호섭을 방지하고 호스트당 더 밀집하게 브라우저를 배치할 수 있게 합니다.
  • Hyperthread Management: 물리적 코어에서의 경합을 방지하기 위해, 각 브라우저에 물리적 코어의 형제 스레드(sibling threads)를 모두 할당합니다.
  • Real-time Priority: vCPU에 실시간 우선순위를 부여하여 즉각적인 실행을 보장함으로써, 1,000-브라우저 부하 테스트 중 세션 손실을 방지했습니다.

Headless Chromium Fork를 통한 스텔스 기능 구현

GPU나 디스플레이 서버의 오버헤드 없이 봇 감지를 피하기 위해, Browser Use는 커스텀 Chromium fork를 결합한 완전한 headless 방식의 접근법을을 사용합니다.

  • Low-level Patching: navigator.webdriver와 같은 자동화 플래그를 숨기기 위해 JavaScript injection을 사용하는 대신, 팀은 이러한 플래그가 노출되지 않도록 Chromium 소스 레벨에서 패치했습니다.

  • Lvl-level Fingerprinting: 시스템은 실제 사용자 환경을 모방하기 위해 macOS, Windows, Linux를 아량한 수만 명의 실제 핑거프린트(fingerprints)를 활용합니다.

내부 벤치마크에 따르면, 이 방식은 일반적인 headless Chromium(2%)보다 훨씬 높은 81%의 확률로 차단됨을 방지합니다.

성능 결과 및 향후 로드맵

10,000-세션 부하 테스트에서 시스템은 p50 브라우저 생성 지연 시간 825ms, p99 1.35s를 달성성하였으며, 100% 신뢰성을 보기였습니다. VM 콜드 스타트 자체는 400ms 미만입니다.

다음 병목 구간: Chromium Startup

가장 큰 지연 시간은 VM이 재개된 후 Chromium을 실행하는 데 필요한 545ms(p50)입니다. 팀은 현재 Chromium이 이미 시작된 에 VM 스냅샷을 찍는 작업을 진행 중입니다. 이를 통해 새로운 세션이 실행 중인 브라우저와 함께 깨어나도록 하여, Chromium 실행 시간을 전체적인 핵심 경로(critical path)에서 완전히 제거할 수 있을지를 기대하고 있습니다.

Sources