카테고리 없음

AWS Lambda MicroVM 등장: Firecracker 기반 격리 샌드박스를 서버리스로 굴리는 법

TeEm0 2026. 6. 24. 09:00

1. 도입: 왜 지금 이게 화제인가

요 몇 년 사이에 "남이 짠(혹은 AI가 짠) 코드를 내 인프라에서 안전하게 실행해줘야 하는" 서비스가 부쩍 늘었다. AI 코딩 어시스턴트, 온라인 IDE, 데이터 분석 노트북 플랫폼, 취약점 스캐너, 유저 스크립트를 받는 게임 서버까지. 공통점은 하나다. 각 사용자/세션마다 격리된 실행 환경을 따로 쥐어줘야 한다는 것.

여기서 실무자가 항상 부딪히는 삼각딜레마가 있다.

  • VM(EC2 등): 격리는 확실한데 부팅에 분 단위가 걸린다. 유저가 "Run" 누르고 1분 기다리게 할 수는 없다.
  • 컨테이너: 빠르게 뜨지만 커널을 공유한다. 신뢰할 수 없는 코드를 돌리려면 seccomp, gVisor, 네임스페이스 하드닝을 직접 다 발라야 한다. 이거 제대로 하려면 보안 전담 엔지니어 한 명이 통째로 붙는다.
  • 일반 Lambda 함수: 이벤트-요청/응답 모델에 최적화돼 있어서, 세션 동안 메모리·디스크 상태를 유지해야 하는 장시간 인터랙티브 워크로드엔 맞지 않는다.

그래서 지금까지는 다들 Firecracker 위에 자체 오케스트레이션을 직접 짜서 굴렸다. 스타트업이 이걸 직접 만들면 제품 만들 시간을 인프라 빌딩에 다 갈아넣게 된다. 이번에 나온 AWS Lambda MicroVMs가 정확히 이 틈을 메우는 물건이다. Lambda 함수가 이미 매달 15조 회 이상의 호출을 굴려온 그 Firecracker를 그대로 가져다, "이미지 만들고 → 띄우고 → 상태 유지하고 → 쉬면 멈추는" 라이프사이클을 API로 노출했다.

2. 핵심: 동작 원리를 예시로

image-then-launch 모델

일반 Lambda는 "코드 zip 올리면 끝"이지만, MicroVM은 두 단계다.

  1. MicroVM Image 생성: Dockerfile + 코드 zip을 S3에 올리면, Lambda가 Dockerfile을 빌드하고 애플리케이션을 실제로 한 번 띄운 다음, 그 시점의 메모리·디스크 상태를 Firecracker 스냅샷으로 떠둔다.
  2. MicroVM 실행(launch): 그 이미지에서 인스턴스를 띄울 때, 콜드 부팅을 하는 게 아니라 미리 초기화된 스냅샷에서 resume한다. 그래서 띄우는 순간 이미 앱이 떠 있는 상태로 시작한다.

비유하자면, 일반 컨테이너가 매번 "전원 켜고 OS 부팅하고 앱 띄우기"라면, MicroVM은 "노트북 덮개 닫았다가 다시 여는" 식이다. 절전(suspend)됐다가 깨어날 때 열어둔 탭이 그대로 살아있는 그 경험을 인프라 단에 적용했다고 보면 된다.

격리 원리: 커널을 공유하지 않는다

핵심은 여기다. 컨테이너는 호스트 커널 하나를 여러 컨테이너가 나눠 쓴다. 그래서 커널 취약점 하나 터지면 컨테이너 탈출(escape) 시나리오가 현실이 된다. 반면 MicroVM은 세션마다 독립된 게스트 커널과 가상화된 하드웨어를 가진다. 하이퍼바이저(KVM) 경계로 격리되기 때문에, A 유저가 던진 악성 코드가 B 유저 환경이나 호스트로 넘어가는 경로가 원천적으로 막힌다. 이게 "VM-level isolation"의 의미다.

실제 만들어보기

원문 예제 기준으로 Flask 앱을 MicroVM으로 만드는 흐름이다. 먼저 Dockerfile은 MicroVM 전용 베이스 이미지를 쓴다는 점이 포인트다.

# Dockerfile
FROM public.ecr.aws/lambda/microvms:al2023-minimal
RUN dnf install -y python3 python3-pip && dnf clean all
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY app.py .
EXPOSE 5000
CMD ["gunicorn", "--bind", "0.0.0.0:5000", "app:app"]

이미지 생성 명령. 코드 zip은 S3에 올려두고 URI로 참조한다.

aws lambda-microvms create-microvm-image \
  --code-artifact uri=s3://my-bucket/path/to/artifact.zip \
  --name flask-sandbox \
  --base-image-arn arn:aws:lambda:us-east-1:aws:microvm-image:al2023-1 \
  --build-role-arn arn:aws:iam::123456789012:role/MicroVMBuildRole

빌드 로그는 CloudWatch /aws/lambda/microvms/<image-name>로 실시간 스트리밍된다. 빌드가 끝나면 ARN과 버전이 콘솔에 뜬다. 빌드 완료 후 실행:

aws lambda-microvms run-microvm \
  --image-identifier arn:aws:lambda:us-east-1:123456789012:microvm-image:flask-sandbox \
  --execution-role-arn arn:aws:iam::123456789012:role/MicroVMExecutionRole \
  --idle-policy '{"maxIdleDurationSeconds":900,"suspendedDurationSeconds":300,"autoResumeEnabled":true}'

idle-policy는 "15분(900초) 동안 요청 없으면 자동 suspend, 그 뒤 5분(300초) suspend 상태 유지, 요청 들어오면 자동 resume"이라는 뜻이다. 별도 네트워킹 세팅 없이 Lambda가 고유 ID와 전용 엔드포인트 URL을 돌려준다. 응답은 대략 이런 형태로 보인다(필드명은 공식 문서 확인 필요):

{
    "microVmId": "mvm-0a1b2c3d4e5f67890",
    "endpointUrl": "https://mvm-0a1b2c3d4e5f67890.lambda-microvms.us-east-1.amazonaws.com",
    "state": "RUNNING"
}

트래픽을 보낼 땐 단명(short-lived) 인증 토큰을 만들어 X-aws-proxy-auth 헤더에 붙인 평범한 HTTPS 요청을 던진다.

curl https://mvm-0a1b2c3d4e5f67890.lambda-microvms.us-east-1.amazonaws.com/ \
  -H "X-aws-proxy-auth: <short-lived-token>"

# 응답
{"message":"Hello, World!"}

여기서 인상적인 건, idle 임계치를 넘겨 suspend된 뒤 다시 요청을 보내도 애플리케이션 상태가 그대로 살아서 resume된다는 점이다. 클라이언트 입장에선 멈췄던 적이 없는 것처럼 보인다. 설치한 패키지, 로딩한 모델, 작업 중이던 파일이 다 그 자리에 있다.

3. 실무 관점: 트레이드오프와 흔한 함정

스냅샷 모델이 만드는 함정 — 초기화 코드를 의심하라

가장 먼저 발 헛디딜 곳이 여기다. MicroVM은 "한 번 초기화한 상태"를 스냅샷으로 떠서 모든 인스턴스가 그걸 복제한다. 즉 이미지 빌드 시점에 단 한 번 실행된 코드의 결과물이 모든 세션에 그대로 복사된다.

이게 왜 문제냐. 초기화 단계에서 다음을 하는 코드는 위험하다.

  • 고유값 생성: 부팅 시 UUID, 랜덤 시드, 세션 키를 한 번 만들어 캐싱하는 코드 → 모든 MicroVM이 동일한 값을 갖게 된다. 난수 생성기 상태까지 복제되므로 보안적으로 치명적일 수 있다.
  • 네트워크 커넥션 선점: 초기화 때 DB 커넥션 풀이나 keep-alive 소켓을 열어두면, 스냅샷에 박제된 끊긴 커넥션을 resume 후 그대로 들고 있게 된다.
  • 초기화 시점 외부 데이터 로딩: 빌드 시점 환경에서 받아온 ephemeral 데이터가 그대로 굳는다.

원문도 이 부분을 명시한다 — "고유 콘텐츠 생성, 네트워크 연결 수립, ephemeral 데이터 로딩을 하는 앱은 서비스가 제공하는 hook과 연동해야 호환된다"고. 일반 Lambda의 SnapStart를 써본 사람이라면 익숙한 패턴이다. 네트워크 연결과 난수 시드 같은 건 스냅샷 이후, 즉 resume 시점에 다시 초기화하도록 코드를 짜야 한다. 이걸 모르고 그냥 컨테이너 코드 들고 오면 이런 식의 증상을 만난다:

# resume 후 박제된 죽은 DB 커넥션을 그대로 사용하다 터지는 전형적 에러
psycopg2.OperationalError: server closed the connection unexpectedly
	This probably means the server terminated abnormally
	before or while processing the request.

# 혹은 redis 클라이언트의 경우
redis.exceptions.ConnectionError: Error 104 while writing to socket. Connection reset by peer.

해결은 lazy connection(첫 요청 때 연결)이나 resume hook에서 풀 재생성. 일반 Lambda의 afterRestore 훅과 비슷한 메커니즘이 제공될 것으로 보이나, 정확한 API는 공식 Developer Guide 확인이 필요하다.

베이스 이미지 잘못 쓰면 빌드부터 막힌다

MicroVM은 일반 Lambda 베이스 이미지가 아니라 public.ecr.aws/lambda/microvms:... 계열을 써야 한다. 기존 Lambda 컨테이너 이미지(public.ecr.aws/lambda/python 등)를 그대로 가져오면 빌드/실행 단계에서 막힌다. 빌드 IAM 역할 권한이 부족하면 보통 이런 식으로 떨어진다:

An error occurred (AccessDeniedException) when calling the CreateMicrovmImage operation:
User: arn:aws:iam::123456789012:role/MicroVMBuildRole is not authorized to perform:
s3:GetObject on resource: arn:aws:s3:::my-bucket/path/to/artifact.zip

build-role과 execution-role을 헷갈려서 권한을 한쪽에만 몰아주는 실수가 잦다. 빌드 역할은 S3 아티팩트 읽기 + CloudWatch 로그 쓰기, 실행 역할은 런타임에 필요한 권한으로 나눠 생각하는 게 깔끔하다.

리소스·리전·아키텍처 제약

  • 아키텍처: ARM64만 지원한다. x86 전용 바이너리(특정 ML 라이브러리 등) 쓰던 팀은 빌드 단계에서 멀티아키 대응이 필요하다. 이거 의외로 마이그레이션 발목 자주 잡는다.
  • 스펙 상한: MicroVM당 최대 16 vCPU / 32GB 메모리 / 32GB 디스크. 무거운 LLM을 풀로 메모리에 올리기엔 32GB가 빠듯할 수 있다.
  • 총 런타임: 최대 8시간. 이걸 넘기는 장시간 세션(종일 켜두는 워크스테이션 같은)에는 부적합. 세션 종료/재시작 설계를 미리 해둬야 한다.
  • 리전: 출시 시점 기준 버지니아 북부, 오하이오, 오레곤, 아일랜드, 도쿄. 서울 리전은 아직 없다. 한국 서비스라면 도쿄로 붙이거나 정식 출시(GA)/서울 확장을 기다려야 한다. 지연 시간 민감한 인터랙티브 워크로드면 이게 실질적 결정 요인이 된다.

비용 관점

핵심 비용 절감 포인트는 suspend다. idle 상태로 멈춰두면 running 비용이 낮은 idle 비용으로 떨어지고 상태는 보존된다. 즉 "유저가 잠깐 자리 비운 동안 풀로 과금"되는 걸 피할 수 있다. 다만 suspend 상태에서도 스냅샷 저장 비용은 발생할 것으로 보이며, 구체 단가는 Lambda 요금 페이지 확인이 필요하다. 인터랙티브 세션이 많고 idle 비율이 높은 서비스일수록 이득이 크다.

그래서 언제 일반 Lambda를 쓰고 언제 MicroVM을 쓰나

  • 이벤트 기반, 짧은 요청/응답, 무상태 → 그냥 일반 Lambda 함수. MicroVM은 오버킬이고 더 비싸다.
  • 신뢰 못 할 코드 실행 + 세션 상태 유지 + 빠른 시작MicroVM.
  • 장시간(8시간 초과) 상시 가동, 풀 커스텀 OS 제어, GPU → 여전히 EC2 혹은 ECS/EKS on EC2.
  • 빠른 시작이 필요하지만 신뢰된 자사 코드만 돌림컨테이너(ECS/Fargate)로 충분한 경우가 많다.

원문 표현대로 둘은 경쟁이 아니라 보완 관계다. 이벤트 백본은 Lambda 함수로 두고, 신뢰 못 할 코드를 격리 실행해야 하는 구간만 MicroVM을 호출하는 조합이 정석으로 보인다.

4. 정리

한 줄 요약: MicroVM은 "VM 수준 격리 + 컨테이너 수준 시작 속도 + 세션 상태 보존"을 직접 빌드하지 않고 API로 얻는 서버리스 프리미티브다.

누가 써야 하나 — 멀티테넌트 SaaS에서 유저/AI가 생성한 코드를 안전하게 돌려야 하는 팀. AI 코딩 어시스턴트, 온라인 IDE, 데이터 분석 플랫폼, 취약점 스캐너가 1순위 후보다. 지금까지 Firecracker 위에 자체 샌드박스 오케스트레이션을 직접 짜서 굴리던 팀이라면, 그 유지보수 부담을 통째로 덜 수 있다는 게 가장 큰 가치다.

반대로, 무상태 이벤트 처리만 하거나 8시간 넘는 상시 워크로드, 혹은 서울 리전 저지연이 필수인 서비스라면 아직은 보류하거나 다른 선택지를 봐야 한다. 스냅샷 기반 초기화의 함정(난수·커넥션 박제)은 도입 전에 반드시 코드 리뷰로 걸러야 할 부분이다.

참고 자료

※ 본문의 응답 JSON 필드명, idle-policy 세부 스펙, resume hook API 등은 출시 직후 시점 기준 추정이 포함돼 있습니다. 실제 도입 전 Lambda MicroVMs Developer Guide의 최신 내용을 반드시 확인하세요.

728x90