컨테이너 이미지를 다 받기 전에 실행하는 법: AWS SOCI 톺아보기
(medium.com/@mintplo)컨테이너 이미지를 “다 받기 전에 실행”하게 만드는 AWS SOCI(Seekable OCI)의 내부 동작을, HTTP Range Request/FUSE/zTOC(인덱스) 관점에서 풀어쓴 글입니다.
도입 배경 (Slacker 논문에서 나온 인사이트)
- Slacker: Fast Distribution with Lazy Docker Containers(USENIX FAST ’16)는 컨테이너 “cold start”가 왜 느린지부터 계측함
- HelloBench라는 벤치마크를 만들고, 57개 컨테이너 워크로드에 대해 “배포 시작 → 유의미한 작업(서비스 준비) 가능”까지의 시간을 측정
- 관찰 1) 시작 시간의 대부분이 ‘이미지/패키지 pull + 복사’에 쓰임
- pulling packages(패키지/이미지 데이터 복사)가 컨테이너 시작 시간의 76%를 차지
- 관찰 2) 그런데 시작 직후 실제로 읽는 데이터는 전체 중 극히 일부
- pull/복사된 데이터 중 평균 6.4%만 “컨테이너가 유의미한 작업을 시작하기 전” 실제로 read 됨
- 관찰 3) 이미지들은 생각보다 “공유/중복”이 많음
- 이미지 단위 gzip 압축보다, 이미지들 사이에 공통 블록을 찾는 단순 block-level dedup이 더 좋은 압축 효과를 보였다고 보고
- 결론(문제의식): “전부 다 내려받고 나서 실행”하는 방식은 낭비가 크고,
시작에 필요한 것만 먼저 가져오고(우선 실행), 나머지는 필요할 때 가져오는(lazy) 방식이 유효할 수 있음 - 위 관찰을 바탕으로 Slacker라는 Docker storage driver를 설계
- 모든 Docker worker/registry가 중앙 스토리지를 공유하고, 백엔드 스토리지의 snapshot/clone을 이용해 파일시스템 프로비저닝 비용을 줄임
- 컨테이너 데이터는 “필요할 때” lazily fetch 하며, 결과적으로 push/pull 및 개발/배포 사이클을 크게 단축했다고 보고
SOCI Snapshotter (AWS)
- SOCI snapshotter README에서도 Slacker(FAST ’16)의 “76% vs 6.4%” 관찰을 레이지 로딩이 먹히는 근거로 직접 인용
- Slacker가 “Docker driver + 특정 스토리지(서버) 기능”에 강하게 기대는 접근이었다면,
SOCI는 OCI 생태계에서 쓰기 위해 이를 “레지스트리(ECR 등)에서의 lazy loading”으로 일반화한 형태 - SOCI는 컨테이너 실행 시점에 이미지를 전부 받기보다,
별도 인덱스(zTOC/Index Manifest)로 파일 위치/스팬 정보를 확보한 뒤 필요한 조각만 먼저 가져와(on-demand) 시작을 앞당기고,
나머지는 백그라운드로 계속 prefetch 하는 하이브리드 전략을 취함
SOCI 핵심 구성요소
- HTTP Range Request: 레지스트리(ECR)에서 필요한 바이트 범위만 206 Partial Content로 가져옴
- zTOC: 파일 오프셋/메타 + 압축 체크포인트(zInfo)로 “중간부터” 압축 해제 가능하게 함
- FUSE: 레이어를 파일시스템처럼 마운트해 open/read를 가로채고, 필요한 span(기본 4MB)을 on-demand로 fetch
동작 흐름(ECS Fargate 기준)
- 인덱스(manifest) 확인 → zTOC 다운로드 → FUSE 마운트 → 컨테이너 실행
- 파일 접근 시 해당 span만 Range Request로 즉시 다운로드/압축해제 후 전달
- 동시에 전체 이미지는 백그라운드로 계속 내려받는 “하이브리드” 전략
한계/트레이드오프
- 인덱스/마운트 오버헤드로 작은 이미지(예: 250MB 미만)는 손해 가능
- 효과는 이미지 크기보다 “초기 파일 접근 패턴”에 민감
- span 크기(요청 수 vs 불필요 다운로드) 튜닝 여지, LOD(Load Order Document) 같은 개선 방향 언급