02. 멀티컨테이너 endpoint: CPU co-host¶
경량 인코더 여러 개를 CPU 인스턴스 하나에 올려 각각 호출할 수 있을까요?
가능합니다. 이 실험에서는 ONNX Runtime의 p50이 58ms였습니다.
| 런타임 | b=1 p50 |
|---|---|
| PyTorch | 1810 ms |
| ONNX Runtime | 58 ms |
ONNX Runtime의 p50은 PyTorch보다 31배 낮았습니다. 검증 sample에서 두 출력은 소수점 6자리까지 일치했습니다. GPU(28ms)보다 latency는 높지만 인스턴스 비용은 낮습니다. 이 모델의 CPU 배포에는 ONNX Runtime 경로를 사용합니다.
이 방식은 GPU를 쓸 수 없습니다
Direct 모드는 GPU 인스턴스를 지원하지 않습니다. 확인한 AWS 문서에는 이 조건이 명시되어
있지 않았습니다. GPU co-host가 필요하면
04_gpu_cohost_lmi를 검토하세요.
멀티컨테이너 endpoint의 구조¶

인스턴스 한 대 안에 컨테이너를 최대 15개까지 띄우고, 컨테이너마다 다른 이미지와 프레임워크를 쓸 수 있습니다. 모델을 미리 로드해 두므로 multi-model endpoint와 달리 콜드 스타트가 없습니다.
멀티컨테이너 endpoint는 Serial과 Direct 두 호출 방식을 제공합니다.
| Serial (직렬) | Direct (직접) | |
|---|---|---|
| 요청 흐름 | 전처리 → 추론 → 후처리 로 체인 | 대상 컨테이너 하나만 호출 |
| 대상 지정 | 불가 (전체를 통과) | TargetContainerHostname |
| 용도 | 추론 파이프라인 | co-host (모델별 독립 호출) |
| GPU | ✅ 가능 | ❌ 거부됨 |
co-host에는 대상 container를 지정할 수 있는 Direct mode가 필요하지만 이 mode는 GPU
인스턴스를 지원하지 않습니다. 같은 GPU image로 Serial mode를 만들면 API validation을
통과하므로 제한은 멀티컨테이너 전체가 아니라 Direct mode에 적용됩니다.
요청 payload 상한은 6MB, timeout은 60초입니다. 이 실습의 512-token NLI payload는 수 KB 수준입니다.
실행¶
# 1) ONNX 변환 (별도 venv를 자동 생성, 약 1분)
uv run python 02_cpu_cohost_multicontainer/scripts/export_onnx.py --models mdeberta minilm
# 2) 출력된 URI를 export
export ONNX_S3_MDEBERTA=s3://...
export ONNX_S3_MINILM=s3://...
# 3) 배포
uv run python 02_cpu_cohost_multicontainer/deploy.py --onnx --dry-run # endpoint 인스턴스 생성 전 확인
uv run python 02_cpu_cohost_multicontainer/deploy.py --onnx
# 4) 호출: TargetContainerHostname으로 대상 지정
uv run python 02_cpu_cohost_multicontainer/invoke.py --endpoint <ep> --mode cloud --all
uv run python -m benchmark.run --mode cloud --endpoint <ep> \
--target-container mdeberta --pad-to-max --sweep-batch
uv run python -m common.cleanup --delete-all # 실습 리소스 삭제
이 방식의 특징¶
컨테이너를 최대 15개까지 올리고 TargetContainerHostname으로 골라 부릅니다.
장점: container마다 서로 다른 image를 사용할 수 있습니다. 이 실험에서 비교한 co-host 구성 중 시간당 비용이 가장 낮았습니다.
제약: GPU를 사용할 수 없고 모델을 추가하면 endpoint를 다시 생성해야 합니다. scaling도 인스턴스 단위로 적용됩니다.
모델별로 스케일할 수 없습니다¶
이 방식의 가장 큰 제약입니다. 스케일아웃하면 컨테이너 구성이 인스턴스마다 통째로 복제됩니다. 인스턴스를 2대로 늘리면 15개 컨테이너가 양쪽에 다 뜨고, 부하가 몰리는 모델 하나만 늘릴 방법이 없습니다.
인스턴스 1대 스케일아웃 후 (2대)
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ mdeberta │ minilm│ → │ mdeberta │ minilm│ │ mdeberta │ minilm│
└──────────────────┘ └──────────────────┘ └──────────────────┘
mdeberta만 늘리는 것은 불가능
오토스케일링 지표가 InvocationsPerInstance 라서 인스턴스 단위로만 판단합니다.
AWS 문서도 이 한계를 이렇게 설명합니다.
각 컨테이너의 모델이 요청마다 비슷한 CPU 사용률과 latency 를 보이는 것을 권장합니다. 트래픽이 CPU 사용률이 낮은 모델에서 높은 모델로 옮겨 가면 전체 호출량은 같으므로 Endpoint가 스케일아웃하지 않고, 높은 사용률 모델의 요청을 처리할 인스턴스가 부족해질 수 있습니다.
크기와 CPU 사용률이 크게 다른 모델을 함께 배포하면 InvocationsPerInstance만으로 부하
변화를 감지하기 어렵습니다. 모델별 traffic과 resource 사용량이 비슷한지 먼저 확인하세요.
인프라로 보면 inference pipeline과 거의 같습니다¶
두 방식 모두 인스턴스 한 대에 컨테이너 여러 개를 띄우고 함께 복제합니다. 차이는 호출 방식뿐입니다.
inference pipeline (Serial) |
멀티컨테이너 Direct |
|
|---|---|---|
| 인프라 구조 | 인스턴스에 컨테이너 N개 | 같음 |
| 스케일 단위 | 인스턴스 | 같음 |
| 호출 | 전체를 체인으로 통과 | 컨테이너를 골라 호출 |
| 제어권 | 파이프라인 순서만 | 어느 컨테이너든 지정 가능 |
Direct mode는 container별 호출을 지원하지만 모델별 자원 배정이나 독립 scaling은 제공하지
않습니다. 해당 기능이 필요하면
03 inference component의 CopyCount를 검토하세요.
놓치기 쉬운 것들¶
Mode: Direct를 생략하면 기본값이 Serial입니다. 그러면 컨테이너가 파이프라인으로
연결되어 골라 부를 수 없습니다.
TargetContainerHostname은 필수입니다. 없는 이름을 주거나, 지정하지 않거나, Direct가
아닌 endpoint에 주면 세 경우 모두 validation error입니다. 확인:
uv run python 02_cpu_cohost_multicontainer/invoke.py --endpoint <ep> --mode cloud \
--show-missing-target-error
Worker를 1개로 제한합니다. ONNX session이 worker마다 모델을 따로 로드하므로 여러 worker를
사용하면 큰 모델 process가 메모리 부족으로 종료될 수 있습니다. deploy.py가 이 값을
설정합니다.
이 mDeBERTa 모델에는 INT8 quantization 결과를 사용하지 않습니다. 검증 sample의 예측이
모두 neutral로 바뀌었습니다(1/4). 이 실습은 fp32 model을 사용합니다.
막힌 경우 → docs/troubleshooting.md
다음으로 읽을 것¶
- GPU가 필요하다 →
04_gpu_cohost_lmi(GPU 1장에 여러 개) - 모델별 독립 스케일링이 필요하다 →
03_gpu_cohost_inference_component