목록으로
오케스트레이션

ECS vs Docker Swarm 컨테이너 오케스트레이션 비교 프로젝트

김민석2026년 05월 11일12분 읽기

ECS vs Docker Swarm 컨테이너 오케스트레이션 비교 프로젝트

"성능 비교에서 운영 철학 비교로 — 실패가 아닌 발견의 과정"



이미지

프로젝트 개요

항목내용
프로젝트 유형인프라 비교 실험
기간2026년 4월
목표동일 EC2 환경에서 Docker Swarm과 Amazon ECS의 성능·운영 특성 비교
핵심 기술Docker Swarm, Amazon ECS(EC2 Launch Type), AWS ALB, Prometheus, Grafana, k6
인프라EC2 t3.small × 2대, ALB, VPC(퍼블릭 서브넷 단일 구성)

초기 목표

  • CPU 부하 상황에서의 오토스케일링 반응 속도 비교
  • 컨테이너 강제 종료 후 복구 시간(Recovery Time) 측정
  • 동일 애플리케이션 · 동일 부하 시나리오 기반의 공정한 비교

시스템 구성

공통 환경

text
1EC2 t3.small × 2대 (각 2GB RAM)
2├── 애플리케이션 컨테이너 (Spring Boot - /env, /stress, /health)
3├── cAdvisor (컨테이너 메트릭 수집)
4└── node-exporter (시스템 메트릭 수집)
5
6모니터링: Prometheus + Grafana
7부하 생성: k6 (ramping-arrival-rate 방식)
8로그 수집: Python autoscale-test.py (2초 간격 컨테이너 수 추적)

Docker Swarm 구성

text
1Manager Node (클러스터 제어 + ingress 담당)
2Worker Node 1 ─┐
3Worker Node 2 ─┘ → 앱 컨테이너 실행 (2 replicas)
4
5네트워크: bridge / overlay
6스케줄링: 로컬 Best-effort 방식

Amazon ECS 구성

text
1ECS Cluster
2├── EC2 인스턴스 1 (ECS Agent + 앱 Task + cAdvisor)
3└── EC2 인스턴스 2 (ECS Agent + 앱 Task + cAdvisor)
4
5Task 스펙: 0.25 vCPU / 0.5GB → 0.5 vCPU / 0.5GB (진행과정에서 변경)
6네트워크: bridge → awsvpc 전환 
7ALB + Target Group(IP 타입) + Health Check(/health)
8오토스케일링: CloudWatch CPU 70% 초과 시 Task 증가

비교 공정성 가설 및 검증

가설 — "Swarm 3대 vs ECS 2대가 공정한 비교다"

두 플랫폼을 같은 인스턴스 수(예: 둘 다 2대)로 맞추는 것이 얼핏 공정해 보이지만, 실제 애플리케이션을 처리하는 데이터 플레인 자원을 기준으로 보면 다르다.

  • Docker Swarm은 Manager 노드가 클러스터 제어(오케스트레이션) 및 ingress 트래픽을 담당하므로, 앱 컨테이너는 Worker 2대에만 배치된다.
  • Amazon ECS는 ECS의 Control Plane이 AWS 관리 영역에 존재하므로, 별도의 Manager 인스턴스가 불필요하다. EC2 2대 모두 앱 Task를 실행하는 워커 역할을 한다.

따라서 공정한 비교 기준은 "앱을 실제로 처리하는 인스턴스 수" 이며, 이 관점에서:

Swarm: Manager 1대 + Worker 2대 (총 3대) ↔ ECS: EC2 2대 (총 2대)
양쪽 모두 앱 처리 인스턴스는 2대로 동일하다.


하지만 이 가설이 성립하려면 한 가지를 검증해야 했다.

"Swarm Manager가 앱 컨테이너를 실행하지 않고, 실제 처리 부하는 Worker 2대가 전담하는가?"


검증 — 노드별 리소스 사용 현황 측정

Grafana + node-exporter로 유휴 상태에서 각 노드의 리소스 사용량을 측정했다.

노드 역할CPU BusySys LoadRAM 사용량비고
Swarm Manager3.1%12.5%25.3%CPU/Load 가장 높음 → 제어 부담
Swarm Worker 12.5%28.5%33.1%Sys Load 매우 높음 → 실제 연산 수행
Swarm Worker 22.5%4.5%34.0%메모리 점유 높음 → 앱 컨테이너 실행
ECS-Clu 12.0%1.0%34.9%안정적 유휴 상태
ECS-Clu 22.1%2.5%34.9%ECS-Clu 1과 거의 동일 패턴

검증 결과 — 가설 입증

측정 결과는 가설을 명확히 지지한다.

  • Manager: RAM 25.3%로 Worker(33~34%)보다 유의미하게 낮고, Sys Load도 낮다. 앱 컨테이너를 실행하지 않고 클러스터 제어 부담만 지고 있음이 확인됐다.
  • Worker 1·2: RAM 33~34% 점유 및 높은 Sys Load → 실제 앱 컨테이너들이 Worker 노드에 배치되어 자원을 점유하고 있음.
  • ECS-Clu 1·2: RAM 34.9%로 Swarm Worker와 유사한 수준 → 동일한 앱 처리 부담을 지고 있음.

결론: "Swarm 3대(Manager + Worker 2) vs ECS 2대"는 공정한 비교다.
앱을 실제로 처리하는 데이터 플레인은 양쪽 모두 2대이며,
ECS는 관리형 서비스이므로 Manager 인스턴스 비용 없이 동일한 처리 용량을 확보할 수 있다.



실험 1 — 컨테이너 장애 복구 테스트

테스트 방법

run_recovery_test.py 스크립트를 각 노드에 대해 실행해 측정을 자동화했다.
SSH로 원격 접속하여 docker kill로 컨테이너를 강제 종료하고, Prometheus API를 5초 간격으로 폴링해 컨테이너 수가 다시 EXPECTED_REPLICAS(1) 이상으로 복구되는 시점을 감지한다.

text
1[측정 흐름]
2kill 명령 실행 (kill_epoch 기록)
3    → 5초 간격 Prometheus 폴링 (container_start_time_seconds 기반)
4    → 새 컨테이너의 start_time이 kill_epoch 이후임을 확인
5    → 복구 시각 기록 (recovery_seconds = recovered_epoch - kill_epoch)
6    → 결과를 recovery_summary.csv / recovery_raw.csv 에 저장

Prometheus 쿼리 구조

  • Swarm: container_label_com_docker_swarm_service_name="myapp" 으로 서비스 단위 집계
  • ECS: name=~"ecs-toy.*" 정규식으로 Task 컨테이너 집계
  • 복구 판단: max(container_start_time_seconds{...}) 값이 kill 시점 이후로 갱신되었는지 확인

이미지

Docker Swarm Test 이미지 ※ 그라파나 대시보드의 시간축은 UTC 기준으로 표시되며, 실제 테스트 실행 시각(KST, UTC+9)과 9시간 차이가 있습니다.



ECS Test

이미지

※ 그라파나 대시보드의 시간축은 UTC 기준으로 표시되며, 실제 테스트 실행 시각(KST, UTC+9)과 9시간 차이가 있습니다.


전체 측정 결과 (recovery_summary.csv)

8회 테스트 수행 (Swarm 4회, ECS 4회).

테스트 ID플랫폼kill 시각복구 시각복구 시간(초)결과
swarm_worker1_20260406Swarm14:32:2714:32:4619.08초✅ success
swarm_worker2_20260406Swarm15:34:4215:35:0119.19초✅ success
ecs1_20260407ECS02:42:49timeout❌ fail
ecs2_20260407ECS03:19:0703:30:25677.63초 (약 11분)✅ success
swarm_worker1_20260411Swarm13:50:2513:50:4621.20초✅ success
swarm_worker2_20260411Swarm13:54:4413:55:0521.21초✅ success
ecs1_20260411ECS13:56:2614:13:541047.99초 (약 17분)✅ success
ecs2_20260411ECS14:17:2514:40:391394.02초 (약 23분)✅ success

플랫폼별 요약

구분측정 횟수평균 복구 시간범위성공률
Docker Swarm4회약 20초19.08 ~ 21.21초4/4 (100%)
Amazon ECS4회약 1,040초 (약 17분)677초 ~ 1,394초 (1회 timeout 제외)3/4 (75%)

Swarm은 4회 모두 19~21초로 일관된 복구를 보인 반면,
ECS는 677초~1,394초로 회차마다 편차가 크고, 1회는 180초 timeout 내에 복구 자체를 실패했다.
ECS timeout 케이스(ecs1_20260407)는 스크립트 제한(180초) 때문에 실패로 기록됐지만,
이후 테스트에서 같은 노드가 1,047초 만에 복구된 것으로 보아 실제 복구는 이뤄졌으나 측정 범위를 벗어난 것으로 판단된다.


원인 분석 (ECS 복구 지연)

ECS의 복구 지연은 단순한 성능 문제가 아니라 구조적 설계 차이에서 비롯된다.

① ALB Health Check 대기 (가장 큰 원인)

  • 체크 주기: 기본 30초
  • 정상 임계 횟수: 기본 5회
  • 최소 소요: 30초 × 5회 = 150초(2분 30초)

② Deregistration Delay (Connection Draining)

  • 기존 컨테이너 등록 해제 대기: 기본 300초(5분)
  • 이론 합계: 5분 + 2분 30초 ≈ 7분 30초
  • 실측값(677초~1,394초)은 이 이론치보다도 훨씬 큰데, 이는 테스트 당시 EC2 자원 여유 부족으로 새 Task 생성 자체가 지연됐기 때문으로 추정된다.

③ ECS Agent 폴링 주기

  • EC2 내 ECS Agent는 실시간 Push가 아닌 주기적 Poll 방식으로 AWS Control Plane과 통신
  • Swarm 대비 수초~수십초 추가 지연 발생

④ ECS 회차별 편차의 원인

  • 실험 당시 EC2 t3.small(2GB)에 ECS Agent, cAdvisor, node-exporter가 상주 중이었고, 새 Task 생성 시 메모리 여유가 부족한 경우 배치 자체가 지연됐다.
  • 이는 ECS의 Resource reservation 기반 스케줄링 특성상, 자원이 확보되지 않으면 배치를 아예 거부하는 구조에서 비롯된다.

최적화 가능 방향

설정 항목기본값최적화 값효과
Deregistration Delay300초30초 이하대기 시간 대폭 단축
Health Check Interval30초10초확인 주기 단축
Healthy Threshold5회2회통과 시간 20초로 단축
EC2 메모리 여유 확보Task 0.25vCPU/0.5GB인스턴스 업그레이드 or Task 스펙 조정Task 배치 지연 해소

실험 2 — CPU 부하 오토스케일링 테스트

부하 시나리오 (k6 stress-test.js)

text
1시나리오: ramping-arrival-rate
2워밍업(30→2분) → CPU 상승(60→3분) → 70% 근접(80→3분)
3→ 유지(80, 5분) → 추가 확장(100, 3분) → 유지(100, 5분)
4오토스케일링 트리거: CPU Utilization 70% 초과

Docker Swarm 오토스케일링 결과

이벤트시각내용
Scale-Out10:56:152 → 4 컨테이너 증가
Stabilization10:56:15 이후count=4로 안정 유지
Scale-In11:00:154 → 2 컨테이너 감소
Self-Healing실험 중1→0→1 컨테이너 재생성 확인
이미지
이미지

Amazon ECS 오토스케일링 결과 및 이슈

ECS에서는 의도한 Scale-Out 대신 Self-Healing(Task 교체) 현상이 반복됐다.

증상

  • /stress 요청으로 CPU 100% → /health 지연 → ALB Health Check 실패
  • ECS가 Unhealthy Task를 종료 후 새 Task 생성 (Desired Count 유지)
  • container=error 로그 반복 확인

원인

  • 부하가 한쪽 컨테이너에 집중 → 전체 평균 CPU가 낮아 오토스케일링 미충족
  • bridge 모드 고정 hostPort(80) → 동일 인스턴스에 복수 Task 배치 불가
이미지
이미지

조치 및 awsvpc 전환 후

  • 네트워크 모드: bridge → awsvpc 전환
  • Target Group 타입: instance → IP 타입 재생성
  • 부하 방식: constant-arrival-rate → ramping-arrival-rate로 변경

이미지

전환 후 2→3 증가는 확인됐으나 Task 1개가 종료되는 현상 재발. 실험 시간 제약으로 완전한 안정화 달성 전 종료.



주요 트러블슈팅 기록

T-1. Bridge 모드 고정 hostPort Scale-out 실패

내용
증상Desired Count 3~4로 변경해도 Running Task는 2개에서 증가 안 함
원인hostPort=80 고정 시 EC2 한 대에 동일 포트 컨테이너 2개 배치 불가
조치hostPort=0(동적 포트) 변경 → 이후 awsvpc + IP Target Group으로 전환

T-2. Target Group 설정 오류 → Health Check 실패 → Self-Healing 오해

발생 흐름

text
1bridge 모드에서 hostPort 고정
2    → Scale-out 시도 시 포트 충돌로 신규 Task 배치 실패
3    → awsvpc 전환 결정
4    → 기존 instance 타입 Target Group을 ip 타입으로 변경 시도 → AWS 정책상 불가(immutable)
5    → Target Group 신규 생성했으나 포트 설정 미스
6    → ALB가 Task를 Unhealthy로 판정
7    → ECS가 Unhealthy Task 종료 후 새 Task 생성 반복
8    → Task가 죽었다 살아나는 걸 보고 Scale-out으로 오해
9    → 실제로는 Self-Healing(장애 교체) 이었음
내용
증상Scale-out을 기대했으나 기존 Task가 종료되고 새 Task가 생성되는 패턴 반복
근본 원인instance 타입 Target Group → awsvpc 전환 후 ip 타입으로 재생성 필요. AWS ALB Target Type은 생성 후 변경 불가(immutable)이므로 신규 생성했으나 포트 설정 불일치로 Health Check 계속 실패
조치Target Group ip 타입으로 재생성 (port 8080, /health) → ALB Security Group에서 8080 인바운드 허용 확인 → /stress?timeout=10timeout=1로 부하 완화

T-3. Grafana 컨테이너 수 과다 표시

내용
증상ECS Running Task 2개인데 Grafana에서 4~5개로 표시
원인awsvpc 모드에서 Task마다 internalecspause 컨테이너 자동 생성
조치PromQL에 container_label_com_amazonaws_ecs_container_name="toy-sb" 필터 추가

비교 분석

핵심 지표 비교

항목Docker SwarmAmazon ECS
설계 목적경량 오케스트레이션클라우드 운영 플랫폼
복구 시간약 21초약 7분 (기본 설정)
스케일링 반응즉시 (로컬 스케줄러)수십초~수분 (CloudWatch 기반)
스케줄링 방식Best-effort (공격적)Resource reservation (보수적)
오버커밋가능거의 불가
네트워크 오버헤드낮음 (bridge/overlay)높음 (ENI, ALB, Target Group)
운영 복잡도낮음높음
안정성상대적으로 낮음높음
모니터링 통합직접 구성 필요CloudWatch 기본 연동

왜 ECS가 느린가 (구조적 이해)

text
1[Docker Swarm 복구 흐름]
2컨테이너 종료 감지 (Docker Engine 내장)
3    → 즉시 재스케줄링 (로컬 의사결정)
4    → 컨테이너 Running → 즉시 트래픽 수신
5    ≈ 수초~20초
6
7[Amazon ECS 복구 흐름]
8Docker Engine 장애 감지
9    → ECS Agent 전달 → AWS Control Plane 보고 (네트워크 왕복)
10    → 새 Task 생성 → ENI 할당 → ALB Target Group 등록
11    → Health Check 대기 (30초 × 5회 = 150초)
12    → Deregistration Delay 대기 (300초)
13    ≈ 7분+

ECS의 느림은 **"안전한 트래픽 전환을 보장하는 설계"**의 결과다.


💡 프로젝트를 통해 얻은 핵심 인사이트

1. 동일 환경 비교의 어려움 — ECS는 불리한 조건에서 측정됐다

ECS를 Swarm 수준에 맞추기 위해 세팅 초기에 Task 리소스를 0.25 vCPU/0.5GB로 제한하자 컨테이너 불안정, 메모리 부족, GC 문제가 발생했다. "비교를 공정하게 만들려다 ECS의 장점을 모두 제거하는" 역설을 경험했다.

이번 실험에서 측정된 ECS의 느린 복구 시간(677초~1,394초)은 ECS 자체의 한계가 아니라 실험 조건의 한계다.

text
1[이번 실험의 ECS 조건 — 불리한 환경]
2EC2 t3.small (2GB) 위에 ECS Agent + cAdvisor + node-exporter 상주
3→ Task 리소스를 0.25vCPU/0.5GB로 억지로 제한
4→ 메모리 여유 부족으로 새 Task 배치 자체가 지연
5→ Swarm 비교를 위해 ECS 본래 설계 방식을 벗어난 구성
6 
7[ECS 본래 용도로 사용했다면]
8Fargate 사용 → EC2 관리 불필요, AWS가 미리 준비한 자원 풀에서 즉시 컨테이너 주입
9→ Task 배치 지연 없음
10→ Health Check 설정 튜닝 (Interval 10초, Threshold 2회) 시 복구 시간 ~20초대도 가능

즉, "ECS가 느리다"가 아니라 "EC2 위에 억지로 올린 ECS가 느렸다" 는 것이 정확한 표현이다.
Fargate로 ECS 본래 용도대로 운영했다면 복구 속도 자체는 Swarm과 크게 다르지 않을 수 있다.


2. 비교 관점의 전환

BeforeAfter
단순 성능 비교 (속도)운영 전략 비교 (적합한 환경의 차이)
"ECS가 느리다""EC2 위에 억지로 올린 ECS가 느렸다"
"Swarm이 더 좋다""온프레미스엔 Swarm, 클라우드엔 ECS(Fargate)"

3. 실무 관점에서의 선택 기준

ECS가 Swarm보다 낫다거나, 기업이 Swarm을 버리고 ECS를 선택한다는 식의 결론은 정확하지 않다.
실제로는 인프라 환경(온프레미스 vs 클라우드 온디맨드) 에 따라 각각이 적합한 상황이 다르다.

상황적합한 선택이유
온프레미스 / 자체 서버 보유Docker Swarm클라우드 벤더 종속 없이 직접 소유한 서버에서 경량 오케스트레이션 운영 가능. AWS API 호출 비용·지연 없음.
AWS 클라우드 온디맨드Amazon ECSALB·CloudWatch·IAM·VPC 등 AWS 에코시스템과 완전 통합. 인프라를 직접 소유하지 않고 사용한 만큼만 과금.
클라우드지만 벤더 독립이 중요Docker Swarm멀티클라우드 또는 이식성이 중요한 환경에서는 Swarm이 유리.
서버리스 지향, 인프라 관리 최소화ECS (Fargate)EC2 자체를 관리할 필요 없이 컨테이너 단위로 과금·운영 가능.

이 프로젝트를 통해 깨달은 핵심은, "어느 쪽이 더 좋은가"가 아니라
"우리 인프라 환경이 온프레미스냐 클라우드냐에 따라 자연스럽게 선택이 갈린다"
는 점이다.
온프레미스 서버를 보유한 조직이 굳이 ECS를 쓸 이유가 없고,
AWS 위에서 운영하는 조직이 굳이 Swarm을 직접 관리할 이유도 없다.


4. 트러블슈팅 역량

단순 기능 구현을 넘어, 네트워크 모드 선택이 확장성에 미치는 영향, ALB Health Check가 복구 시간을 결정하는 메커니즘, ECS Agent 폴링 방식의 한계 등 인프라 내부 동작 원리를 실험을 통해 직접 검증했다.


기술 스택

구분기술
컨테이너 오케스트레이션Docker Swarm, Amazon ECS (EC2 Launch Type)
애플리케이션Spring Boot (Java)
인프라AWS EC2 (t3.small), ALB, VPC, Target Group
모니터링Prometheus, Grafana, cAdvisor, node-exporter
부하 테스트k6 (ramping-arrival-rate), Python (autoscale-test.py)
네트워크bridge, overlay, awsvpc, ENI

회고 및 결론

본 프로젝트는 "완벽한 비교 실험"보다 더 가치 있는 것을 남겼다.

단순히 수치를 비교하는 과정에서, 두 시스템이 서로 다른 문제를 풀기 위해 설계됐다는 점을 발견했다. ECS를 Swarm처럼 다운그레이드해서 비교하는 것 자체가 잘못된 접근이었음을 실험 도중 깨달았고, 그 깨달음 자체가 이 프로젝트의 핵심 성과다.

Docker Swarm은 빠르고 단순한 오케스트레이터,
Amazon ECS는 느리지만 안정적인 클라우드 운영 플랫폼이다.

This post is licensed under CC BY 4.0 by the author.

Share:

Further Reading

댓글 0

첫 번째 댓글을 남겨보세요

댓글 작성