콘텐츠로 이동

ECS vs EC2

분류: Layer 3 - AWS 인프라 & 보안

EC2(Elastic Compute Cloud)는 AWS에서 빌려 쓰는 가상 서버다. ECS(Elastic Container Service)는 컨테이너를 원하는 개수와 상태로 유지하는 AWS의 컨테이너 오케스트레이션 서비스다.

그래서 “ECS vs EC2”는 엄밀히 말하면 같은 층의 비교가 아니다. EC2는 compute 자원이고, ECS는 그 compute 위에서 컨테이너를 배치하고 교체하고 배포하는 orchestration 계층이다. ECS는 EC2 인스턴스 위에서도 실행할 수 있고, Fargate처럼 서버 관리를 AWS에 맡기는 방식으로도 실행할 수 있다.

처음 읽을 때는 아래 문장을 고정한다.

EC2 직접 운영: "서버를 만들고, 그 서버에 직접 컨테이너를 띄운다."
ECS + EC2: "서버 풀은 내가 관리하고, 컨테이너 배치와 유지는 ECS가 맡는다."
ECS + Fargate:"서버 풀 관리까지 AWS에 맡기고, Task 단위만 선언한다."

서비스가 장애 없이 배포되고, 트래픽에 맞춰 늘어나고, 죽은 프로세스가 자동으로 복구되는지는 애플리케이션 코드만으로 결정되지 않는다. 어디에 띄울지, 몇 개를 유지할지, 새 버전을 어떻게 교체할지, 로드밸런서가 어떤 대상에 요청을 보낼지를 누군가 계속 맞춰야 한다.

EC2만 직접 쓰면 이 책임이 대부분 운영자에게 남는다. ECS를 쓰면 “이 이미지의 Task를 3개 유지하라”는 원하는 상태(desired state)를 선언하고, ECS scheduler가 실제 상태(actual state)를 맞춘다. 이 차이를 모르면 배포 실패를 보고도 “서버가 죽었나”, “컨테이너가 죽었나”, “스케줄러가 새 Task를 못 띄우나”, “ALB health check가 막나”를 구분하기 어렵다.

이 문서의 목표는 ECS 설정을 모두 외우는 것이 아니다. EC2, ECS, Fargate, ALB, ENI, ECR, Task Definition, Service, Cluster가 어떤 층에서 만나는지를 그릴 수 있게 만드는 것이다.

2.5 선행 기술의 한계 — 수동 Docker 배포에서 ECS로

섹션 제목: “2.5 선행 기술의 한계 — 수동 Docker 배포에서 ECS로”

ECS는 Docker 컨테이너를 EC2에 직접 띄우던 방식의 운영 한계에서 등장했다. 작은 서비스 하나는 EC2에 SSH로 접속해서 docker run을 실행해도 된다. 하지만 컨테이너가 여러 개, 인스턴스가 여러 대, 배포가 하루 여러 번으로 늘어나면 다음 문제가 반복된다.

수동 운영에서 깨지는 지점실제로 생기는 문제ECS가 제공하는 해법
desired state 부재Task 3개가 정상인지 사람이 콘솔이나 스크립트로 확인한다Service가 desired count를 유지한다
노드 장애 복구EC2 한 대가 죽으면 그 위 컨테이너를 어디에 다시 띄울지 사람이 정한다scheduler가 새 Task를 가능한 capacity에 배치한다
배포 순서새 컨테이너를 먼저 띄울지, 기존 컨테이너를 먼저 내릴지 매번 절차화해야 한다deployment controller가 health check를 보며 rolling update를 수행한다
서비스 디스커버리와 트래픽어떤 IP:port가 살아 있는지 ALB나 프록시에 계속 반영해야 한다Service가 Target Group에 Task를 등록하고 해제한다
bin packingEC2별 CPU/메모리 여유를 사람이 추정해 컨테이너를 배치한다ECS가 Task 요구 리소스와 capacity를 비교해 배치한다

핵심 전환은 명령형에서 선언형으로 바뀐다는 점이다.

명령형: "이 EC2에 접속해서 docker run을 실행한다."
선언형: "이 Task Definition을 Service desiredCount=3으로 유지한다."

ECS의 lineage는 여기서 나온다. 컨테이너를 띄우는 명령 하나가 아니라, 원하는 상태와 실제 상태를 계속 비교해 복구하는 관리 루프가 필요해졌고, ECS는 그 루프를 AWS 서비스로 제공한다. Fargate는 여기서 한 단계 더 나아가 “컨테이너를 올릴 EC2 인스턴스 풀” 관리까지 AWS에 넘긴 실행 방식이다.

아래 용어는 뒤에서 계속 나온다. 외부 prerequisite로 외울 필요는 없고, 여기서 첫 정의를 잡고 본문 예시로 반복해서 확인하면 된다.

용어첫 정의처음 잡아야 할 경계
EC2Elastic Compute Cloud. 사용자가 빌려 쓰는 VM 서버다.OS 패치, 인스턴스 타입, 디스크, 에이전트, capacity를 직접 관리한다.
ECSElastic Container Service. 컨테이너 Task를 배치하고 유지하는 orchestration 서비스다.서버 자체가 아니라 서버 또는 Fargate capacity 위에서 컨테이너 lifecycle을 관리한다.
ECRElastic Container Registry. Docker image를 저장하는 AWS registry다.ECS는 image를 직접 만들지 않는다. Task 시작 시 ECR 같은 registry에서 image를 pull한다.
ALBApplication Load Balancer. HTTP/HTTPS 요청을 target으로 분산하는 L7 로드밸런서다.ECS Service 앞의 public entrypoint 역할을 맡고, Task는 보통 private subnet에 둔다.
ENIElastic Network Interface. VPC 리소스에 붙는 네트워크 카드다.Fargate awsvpc 모드에서는 Task마다 ENI와 private IP가 붙는다.
Task Definition컨테이너 실행 스펙이다. image, CPU, memory, port, env, log 설정을 담는다.실행 중인 인스턴스가 아니라 blueprint다. revision이 쌓인다.
TaskTask Definition을 실제로 실행한 단위다. 하나 이상의 컨테이너를 담을 수 있다.죽고 새로 생기는 runtime instance다. 영구 서버 이름처럼 보면 안 된다.
Service같은 Task를 원하는 개수만큼 유지하고 배포하는 단위다.웹/API처럼 계속 떠 있어야 하는 workload에 맞다. 1회성 batch는 standalone Task도 가능하다.
ClusterService와 Task가 속한 논리 그룹이다.capacity가 어디서 오는지는 Fargate, EC2, capacity provider 설정으로 결정된다.
desired state운영자가 선언한 목표 상태다. 예: Task 3개 유지.”지금 실제로 3개 떠 있다”가 아니라 시스템이 맞춰야 할 목표다.
schedulerdesired state를 만족하도록 Task를 배치하고 교체하는 ECS 내부 주체다.애플리케이션 버그를 고쳐 주지는 않는다. 실행 가능한 capacity와 상태를 맞춘다.
health checkTask가 트래픽을 받아도 되는지 판단하는 검사다.컨테이너가 RUNNING이어도 ALB health check가 실패하면 traffic target이 아니다.
launch typeTask가 어떤 infrastructure에서 실행되는지 가리키는 선택이다.FARGATEEC2가 대표적이고, capacity provider로 더 유연하게 섞을 수 있다.
capacity providerService가 사용할 capacity 공급원을 정의하고 비중을 조절하는 방식이다.Fargate, Fargate Spot, EC2 Auto Scaling Group 같은 공급원을 조합할 때 쓴다.
Fargate서버와 cluster capacity 관리를 AWS에 맡기는 serverless container 실행 방식이다.ECS의 대체물이 아니라 ECS Task를 실행하는 capacity option이다.

4. ECS가 컨테이너를 유지하는 기본 흐름

섹션 제목: “4. ECS가 컨테이너를 유지하는 기본 흐름”

ECS를 공부할 때는 화면 메뉴보다 lifecycle을 먼저 잡는다.

ECS Service가 Task를 유지하는 흐름

  1. 1. Image 저장

    Docker image를 ECR 같은 registry에 저장한다. ECR은 Elastic Container Registry의 약자다.

  2. 2. Task Definition 등록

    image URI, CPU, memory, port, environment, secret, log 설정을 revision으로 고정한다.

  3. 3. Service desired count 선언

    이 Task Definition revision을 몇 개 유지할지 선언한다. 예: desiredCount=3.

  4. 4. Scheduler 배치

    ECS scheduler가 Fargate 또는 EC2 capacity 중 조건을 만족하는 곳에 Task를 배치한다.

  5. 5. Health check와 교체

    컨테이너나 ALB health check가 실패하면 Service가 새 Task를 시작해 desired state를 복원한다.

Task Definition은 “서버 한 대”가 아니라 “컨테이너를 어떻게 실행할지”를 담은 스펙이다. 아래 예시는 Fargate에서 API 컨테이너 하나를 실행하는 최소 감각을 보여준다.

{
"family": "my-api",
"networkMode": "awsvpc",
"requiresCompatibilities": ["FARGATE"],
"cpu": "256",
"memory": "512",
"executionRoleArn": "arn:aws:iam::123456789012:role/ecsTaskExecutionRole",
"taskRoleArn": "arn:aws:iam::123456789012:role/myApiTaskRole",
"containerDefinitions": [
{
"name": "api",
"image": "123456789012.dkr.ecr.ap-northeast-2.amazonaws.com/my-api:2026-07-08",
"portMappings": [{ "containerPort": 3000, "protocol": "tcp" }],
"environment": [{ "name": "NODE_ENV", "value": "production" }],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/my-api",
"awslogs-region": "ap-northeast-2",
"awslogs-stream-prefix": "ecs"
}
}
}
]
}

여기서 IAM 문서와 연결되는 지점이 중요하다.

  • executionRoleArn: ECS 플랫폼이 Task를 시작할 때 쓰는 Role이다. ECR image pull, CloudWatch Logs 전송, secret 주입에 필요하다.
  • taskRoleArn: 컨테이너 안의 애플리케이션 코드가 AWS API를 호출할 때 쓰는 Role이다. S3 업로드, SQS 전송, Secrets Manager 조회 권한은 여기에 붙는다.

반례를 하나 잡자. 애플리케이션이 S3에 파일을 올려야 하는데 executionRoleArn에만 s3:PutObject를 붙이면 Task 시작과 로그 전송은 정상일 수 있다. 하지만 코드가 S3를 호출하는 순간 AccessDenied가 난다. 이때 필요한 것은 “ECS 권한을 더 넓게”가 아니라 Task Role과 Execution Role을 구분해 올바른 Role에 권한을 붙이는 것이다.

desired state reconciliation 손으로 따라가기

섹션 제목: “desired state reconciliation 손으로 따라가기”

ECS Service의 핵심은 desired state reconciliation이다. reconciliation은 “목표 상태와 실제 상태를 비교해 다시 맞춘다”는 뜻이다.

초기 상태:
Service desiredCount = 3
실행 중 Task = A, B, C
장애:
Task B가 exit code 1로 종료
ECS 관찰:
desired = 3
actual = 2
ECS 행동:
새 Task D 시작
ALB health check 통과 후 target 등록
복원:
실행 중 Task = A, C, D
desiredCount = 3 충족

이 예시는 단순하지만 운영 사고의 기준점이다. Task가 죽었을 때 “ECS가 새 Task를 띄우고 있는가”와 “새 Task가 떠도 health check를 통과하지 못하는가”는 다른 문제다. 전자는 scheduler와 capacity 문제이고, 후자는 애플리케이션 부팅, 포트, health endpoint, 네트워크 문제일 가능성이 크다.

ECS의 실행 위치를 고르는 질문은 “ECS냐 EC2냐”가 아니라 ECS가 사용할 capacity를 누가 관리할 것인가다.

ECS capacity 선택

ECS on Fargate

Task 단위로 CPU와 memory를 지정하면 AWS가 실행 환경을 준비한다. EC2 인스턴스 선택, OS patch, cluster packing을 직접 하지 않는다.

팀이 작고, workload가 변동적이며, 서버 운영보다 배포 속도와 단순성이 중요할 때

ECS on EC2 launch type

내가 관리하는 EC2 인스턴스 풀 위에 ECS가 Task를 배치한다. 인스턴스 타입, AMI, agent, patch, Auto Scaling Group을 관리한다.

Task 수가 많고 예측 가능하거나 GPU, privileged container, custom AMI 같은 요구가 있을 때

EC2 직접 운영

ECS 없이 EC2에 직접 process나 container를 실행한다. orchestration, 배포, 복구 자동화를 직접 만든다.

아주 단순한 실험, 특수한 OS 제어, 또는 orchestration 도입 전 단계

AWS 공식 문서는 ECS capacity를 Fargate, EC2 instances, ECS Managed Instances 같은 infrastructure option으로 설명한다. 다만 첫 회독에서는 Fargate와 EC2 launch type의 차이만 정확히 잡아도 충분하다. Managed Instances는 “서버 관리를 어느 정도 AWS가 대신하되 EC2 계층의 제어를 일부 유지하려는 capacity option”으로 나중에 읽으면 된다.

Fargate는 각 Task에 전용 실행 환경을 제공한다. AWS 문서 기준으로 Fargate Task는 다른 Task와 underlying kernel, CPU, memory, ENI를 공유하지 않는 격리 경계를 가진다. 같은 Task 안의 여러 컨테이너는 localhost와 Task 리소스를 공유할 수 있지만, Task 바깥과는 분리된다.

이 모델의 학습 포인트는 세 가지다.

  1. 운영 책임 이동: OS patch, container runtime patch, EC2 capacity packing을 직접 하지 않는다.
  2. 네트워크 단위 변화: awsvpc 모드에서 Task마다 ENI와 private IP가 붙으므로 Security Group을 Task 단위로 적용할 수 있다.
  3. 제어 제약: privileged container, host 접근, 일부 Linux capability, GPU 같은 요구는 Fargate에서 안 되거나 제한된다. 이때 ECS on EC2를 검토한다.

Fargate가 “무조건 더 안전하고 빠르다”는 뜻은 아니다. 서버 관리를 덜 하는 대신, 실행 환경을 세밀하게 만지는 권한도 줄어든다.

Fargate는 아무 CPU/memory 조합이나 고를 수 없다. Task Definition에 허용된 조합만 넣을 수 있고, 조합이 틀리면 등록 시점에 실패한다. 아래 표는 학습용 요약이다. 실제 설계 전에는 공식 문서의 최신 표와 리전별 quota를 확인한다.

CPUmemory 조합 감각처음 읽을 때의 해석
0.25 vCPU512 MiB, 1 GB, 2 GB작은 API, worker, sidecar 없는 입문용 Task
0.5 vCPU1~4 GB낮은 트래픽의 API나 가벼운 batch
1 vCPU2~8 GB일반적인 소규모 서비스 시작점
2 vCPU4~16 GB동시 요청이 늘거나 런타임 memory가 큰 서비스
4 vCPU8~30 GBCPU와 memory를 모두 더 쓰는 API/worker
8 vCPU16~60 GB큰 batch, 무거운 런타임, 높은 동시 처리
16 vCPU32~120 GB메모리 집약 workload의 상위 조합
32 vCPU60 GB, 120 GB, 244 GB매우 큰 workload. quota, 비용, cold start를 따로 검토

이 표에서 얻어야 할 결론은 “큰 조합이 있으니 다 Fargate로 가능하다”가 아니다. 조합이 커질수록 Task 하나의 비용과 시작 시간이 커지고, 장애가 났을 때 한 Task가 잃는 처리량도 커진다. 반대로 너무 작은 Task를 많이 띄우면 ENI/IP, log stream, DB connection, downstream 호출 수가 먼저 문제가 될 수 있다.

launch type은 Task Definition이나 Service가 사용할 실행 환경을 직접 고르는 방식이다. 대표 값은 FARGATEEC2다.

capacity provider는 이 선택을 한 단계 추상화한다. 예를 들어 FARGATEFARGATE_SPOT을 1:3 비중으로 섞거나, EC2 Auto Scaling Group capacity와 Fargate capacity를 Service 전략 안에서 조합할 수 있다.

{
"capacityProviderStrategy": [
{ "capacityProvider": "FARGATE", "weight": 1, "base": 1 },
{ "capacityProvider": "FARGATE_SPOT", "weight": 3 }
]
}

이 예시는 “최소 1개 Task는 On-Demand Fargate에 두고, 나머지는 가능한 한 Spot으로 둔다”는 의도다. 단, Spot은 중단될 수 있다. 로그 ingestion, 결제 처리, 긴 transaction처럼 중단되면 데이터 손실이나 중복 처리가 어려운 workload에는 비용 절감률보다 중단 처리 설계가 먼저다.

Fargate는 awsvpc 네트워크 모드만 지원한다. awsvpc에서는 Task마다 ENI(Elastic Network Interface)와 private IP를 받는다. 이 말은 Task가 단순 process가 아니라 VPC 안의 네트워크 주체가 된다는 뜻이다.

외부 HTTP 요청은 보통 ALB(Application Load Balancer)를 거쳐 ECS Task로 들어간다.

외부 요청이 ECS Task까지 도달하는 경로
sequenceDiagram
participant User as 인터넷 사용자
participant ALB as ALB
participant TG as Target Group
participant Service as ECS Service
participant Task as Task ENI/IP

User->>ALB: HTTPS 요청
ALB->>TG: healthy target 선택
TG->>Service: 등록된 Task IP 확인
Service->>Task: containerPort로 전달
Task-->>User: 응답 반환

ALB는 Public Subnet의 진입점이고, Task는 보통 Private Subnet에서 Target Group을 통해서만 접근된다.

Fargate Task를 Target Group에 등록할 때는 보통 target type을 ip로 둔다. Task가 EC2 instance ID가 아니라 ENI에 붙은 private IP로 식별되기 때문이다. 그래서 ALB 문제를 볼 때는 “Task가 RUNNING인가”와 “Target Group에서 healthy인가”를 분리해야 한다.

ENI와 IP가 스케일링 한계를 만든다

섹션 제목: “ENI와 IP가 스케일링 한계를 만든다”

Task가 늘면 CPU와 memory만 쓰는 것이 아니다. awsvpc에서는 Task마다 private IP를 하나씩 소비한다.

Private Subnet A: /27
표기상 주소 수: 32
AWS 예약 후 대략 사용 가능: 27
현재 Task: 20개
rolling update 중 신규 Task: 20개
순간 필요 IP: 40개
결과:
Task를 모두 띄우기 전에 Subnet IP가 부족해질 수 있다.

반대로 /24 subnet은 AWS 예약분을 제외해도 약 251개를 사용할 수 있다. 같은 20 -> 20 rolling update를 훨씬 여유 있게 흡수한다. VPC 문서에서 배운 /24/27의 차이가 ECS에서는 “배포 중 Task가 안 뜨는가”로 바로 드러난다.

실패 신호는 다음처럼 나타난다.

증상의미먼저 볼 개념
Service desiredCount까지 Task가 올라가지 않는다capacity 또는 IP가 부족할 수 있다Subnet free IP, Service events
이벤트에 RESOURCE:ENI, insufficient free addresses가 보인다Task에 붙일 ENI/IP를 확보하지 못했다VPC CIDR, Subnet 크기
특정 AZ에만 Task가 몰린다한쪽 Subnet capacity가 부족하거나 배치 제약이 다르다Multi-AZ subnet, capacity provider

전형적인 웹 서비스 구성을 한 번에 그리면 ECS가 다른 L3 토픽과 어떻게 연결되는지 보인다.

인터넷
-> ALB (Public Subnet, HTTPS 443)
-> Target Group (target type = ip, health check = /health)
-> ECS Service (Private App Subnet A/B)
-> Task 2개 이상 (Fargate, awsvpc, SG = sg-api)
Task에서 나가는 연결:
-> RDS (DB Subnet, SG inbound source = sg-api, port 5432)
-> S3 (Gateway Endpoint 또는 NAT 경유)
-> ECR / CloudWatch Logs / Secrets Manager (Interface Endpoint 또는 NAT 경유)
-> 외부 결제 API (NAT Gateway 경유)

이 구성에서 public한 것은 ALB뿐이다. ECS Task와 RDS는 private subnet에 둔다. 하지만 private이라는 말이 “아무 데도 나갈 수 없음”은 아니다. Task가 ECR에서 image를 받고, CloudWatch로 logs를 보내고, 외부 API를 호출하려면 NAT Gateway나 VPC Endpoint 같은 outbound 경로가 필요하다.

작은 수치 예시를 붙이면 설계 감각이 더 선명해진다.

desiredCount = 6
rolling update maximumPercent = 200
배포 중 최대 Task = 12
Private Subnet A/B를 /27로 만들면:
AZ별 사용 가능 IP가 약 27개라 다른 리소스와 같이 쓰는 순간 빠듯하다.
Private Subnet A/B를 /24로 만들면:
AZ별 사용 가능 IP가 약 251개라 Task, ENI, Endpoint 확장을 더 여유 있게 흡수한다.

따라서 ECS Service의 최대 Task 수는 ECS 화면 안에서만 정하지 않는다. VPC CIDR, Subnet 크기, RDS 연결 수, NAT/Endpoint 비용까지 같이 계산한다.

ECS Service rolling update는 새 버전 Task를 띄우고, health check를 통과한 뒤, 기존 Task를 내리는 흐름이다.

Rolling Update에서 트래픽이 바뀌는 순서

  1. 1. 새 Task Definition revision 등록

    image tag, environment, resource 설정 변경이 새 revision으로 고정된다.

  2. 2. 신규 Task 시작

    Service가 새 revision Task를 시작한다. maximumPercent가 동시에 실행 가능한 Task 상한을 정한다.

  3. 3. Target Group 등록과 health check

    신규 Task가 ALB health check를 통과하기 전까지 기존 Task가 계속 traffic을 받는다.

  4. 4. Traffic 전환

    신규 Task가 healthy가 되면 ALB가 새 Task IP에도 요청을 분산한다.

  5. 5. 구버전 drain 후 종료

    minimumHealthyPercent를 지키면서 기존 target을 deregister하고 연결을 drain한 뒤 Task를 종료한다.

두 설정이 배포 중 capacity 요구량을 크게 바꾼다.

설정의미예시
maximumPercent배포 중 desiredCount 대비 최대 몇 %까지 Task를 동시에 띄울 수 있는가desired=10, maximum=200이면 최대 20개까지 공존
minimumHealthyPercent배포 중 최소 몇 %의 healthy Task를 유지해야 하는가desired=10, minimum=100이면 최소 10개는 healthy여야 함

반례를 보자. desiredCount가 10이고 minimumHealthyPercent=100, maximumPercent=100이면 새 Task를 띄울 여유도 없고 기존 Task를 먼저 내릴 수도 없다. 설정만 보면 안정적으로 보이지만, 실제로는 rolling update가 진행될 수 없다. 보통은 새 Task가 먼저 올라올 여유를 주거나, capacity provider와 subnet IP 여유를 함께 확보해야 한다.

ALB 502가 배포 직후 낮은 비율로만 보이면 평균 에러율에서는 묻힌다. 하지만 원리는 단순하다. Task 종료, ALB target deregistration, 애플리케이션 shutdown 시간이 서로 맞지 않으면 긴 요청만 잘린다.

ALB deregistration delay >= 애플리케이션의 긴 요청 p99 처리 시간
ECS stopTimeout >= 애플리케이션이 SIGTERM 후 정리하는 시간
애플리케이션 shutdown hook은 새 요청을 거절하고 진행 중 요청을 마무리한다

예를 들어 파일 업로드나 외부 API 대기가 p99 25초인데 deregistration delay가 10초라면 짧은 요청은 정상이고 긴 요청만 502가 된다. 이 패턴은 “서비스가 대부분 정상”처럼 보여서 늦게 발견된다. 본문에서 기억할 것은 명령어가 아니라 배포와 scale-in은 정상 동작 중인 연결을 끊을 수 있는 사건이라는 점이다.

HealthCheckGracePeriod가 필요한 경우

섹션 제목: “HealthCheckGracePeriod가 필요한 경우”

Task가 RUNNING으로 바뀌었다고 해서 애플리케이션이 traffic을 받을 준비를 마친 것은 아니다. NestJS 같은 서버가 DB 연결, migration check, module loading, cache warmup을 수행하는 동안 /health가 아직 200을 반환하지 못할 수 있다. 이때 ALB health check가 너무 빨리 실패를 누적하면 ECS가 새 Task를 비정상으로 보고 교체한다.

애플리케이션 완전 부팅 시간: 35~45초
ALB health check interval: 30초
unhealthy threshold: 2
healthCheckGracePeriodSeconds: 0
결과:
Task가 정상 부팅 중인데도 첫 health check 실패가 누적되어 교체될 수 있다.

학습 포인트는 “grace period를 무조건 길게”가 아니다. 부팅 시간이 40초라면 grace period를 60초처럼 여유 있게 시작하고, health endpoint가 DB 같은 외부 의존성까지 검사해야 하는지 분리해서 본다. /live는 process 생존, /ready는 traffic 가능 상태처럼 역할을 나누면 배포 중 불필요한 교체를 줄일 수 있다.

8. Auto Scaling은 Task 수만 늘리지 않는다

섹션 제목: “8. Auto Scaling은 Task 수만 늘리지 않는다”

ECS Service는 Application Auto Scaling으로 desiredCount를 늘리거나 줄일 수 있다. 가장 흔한 방식은 target tracking이다.

목표:
ECSServiceAverageCPUUtilization = 60%
현재:
Task 4개, 평균 CPU 85%
Scaling 판단:
Task 수를 늘려 평균 CPU가 목표값 근처로 내려가게 한다.

실무에서 시작점으로 자주 쓰는 감각은 CPU 60%, memory 70% 부근이다. 이것은 정답이 아니라 초기 가설이다. latency가 CPU보다 먼저 나빠지는 서비스라면 ALB request count per target, queue depth, p95 latency 같은 서비스 메트릭을 같이 봐야 한다.

최소/최대 Task 수는 단순히 “트래픽이 많다”로 정하면 안 된다.

잡는 기준
최소 Task 수Multi-AZ를 위해 보통 2개 이상에서 시작한다. cold start 동안 버틸 baseline도 포함한다.
최대 Task 수Subnet IP 수, Fargate service quota, RDS max_connections, downstream rate limit을 같이 본다.
scale-out cooldown급증 트래픽에 너무 늦지 않게 짧게 시작하되, cold start와 image pull 시간을 감안한다.
scale-in cooldown플래핑을 막기 위해 더 길게 둔다. scale-in은 연결 drain과 graceful shutdown을 동반한다.

RDS 문서에서 배운 connection pool 계산은 ECS scaling 상한과 직접 연결된다.

RDS max_connections >= ECS Task 수 x 애플리케이션 pool max
예시:
RDS max_connections = 90
pool max = 10
안전한 Task 수 상한:
90 / 10 = 9개
Service maxCapacity를 20으로 두면:
트래픽 spike 때 Task 20개 x pool 10 = 200 연결 시도
=> DB는 CPU보다 먼저 "too many connections"로 실패할 수 있다.

이 예시는 “ECS autoscaling은 애플리케이션만 보는 기능이 아니다”라는 점을 보여준다. Task를 늘리면 IP, DB 연결, cache connection, 외부 API 호출량도 같이 늘어난다. 그래서 autoscaling 최대값은 compute capacity가 아니라 가장 먼저 포화되는 downstream 자원을 기준으로 제한해야 한다.

RDS Proxy를 쓰면 계산이 바뀐다. Proxy가 모든 문제를 없애지는 않지만, 애플리케이션 Task 수와 실제 DB backend connection 수를 분리할 수 있다.

Proxy 없음:
Task 40개 x pool max 5 = DB 연결 200개
Proxy 있음:
Task 40개 -> Proxy client 연결 200개
Proxy -> RDS backend 연결 40개 수준으로 multiplex 가능

단, transaction을 오래 잡거나 session variable, temporary table 같은 pinning 조건이 많으면 multiplexing 효율이 떨어진다. 그래서 ECS scaling 설계에서 RDS Proxy는 “연결 수를 줄이는 도구”이지, “무제한 scale-out 허가증”이 아니다.

cold start를 autoscaling으로만 해결할 수 없는 이유

섹션 제목: “cold start를 autoscaling으로만 해결할 수 없는 이유”

Fargate는 새 Task를 시작할 때 실행 환경 준비, image pull, 컨테이너 부팅, health check 통과 과정을 거친다. workload와 image 크기에 따라 시간이 달라지며, 30~60초 수준을 측정 시작값으로 잡는 서비스도 있다. SOCI 같은 image lazy loading 옵션으로 image pull 시간을 줄일 수 있지만, “새 Task가 즉시 traffic을 받는다”는 가정은 위험하다.

반례를 보자.

평상시 필요 Task: 4개
갑작스러운 피크에서 필요한 Task: 12개
새 Task가 health check 통과까지 걸리는 시간: 45초
Auto Scaling이 바로 반응해도:
첫 45초는 기존 4개 Task가 피크 대부분을 감당한다.

이때 해결책은 무조건 maxCapacity를 키우는 것이 아니다. 예측 가능한 피크가 있으면 baseline Task를 피크의 70~80% 수준으로 미리 올려 두거나, scheduled scaling을 쓰거나, queue를 앞에 두어 burst를 흡수한다. 비용을 아끼려고 baseline을 지나치게 낮추면 scale-out이 시작되기 전에 ALB 5xx나 latency spike가 먼저 온다.

Fargate와 EC2 launch type의 비용 차이는 “어느 쪽이 싸다”가 아니라 과금 단위가 다르다는 데서 시작한다.

항목FargateECS on EC2
과금 단위Task가 요청한 vCPU와 memory 사용 시간EC2 인스턴스, EBS, 데이터 전송, 운영 비용
빈 capacityTask가 없으면 compute 비용도 줄어든다인스턴스가 켜져 있으면 빈 capacity도 비용이다
bin packingAWS가 처리하지만 task 단위 과금 프리미엄이 있다여러 Task를 한 인스턴스에 채워 비용을 낮출 수 있다
운영 비용OS patch, agent, AMI 관리 부담이 작다인스턴스 보안 패치, scaling, draining을 직접 다룬다

실제 설계에서는 반드시 현재 리전의 공식 요금표로 다시 계산해야 한다. 아래 숫자는 계산 방법을 익히기 위한 학습용 기준점이며, 리전, CPU 아키텍처, OS, pricing 갱신 시점에 따라 달라질 수 있다.

Task 1개, 0.25 vCPU / 0.5 GB, 24시간 x 30일

항목계산월 비용 감각
Fargate vCPU0.25 x $0.04048 x 720h약 $7.29
Fargate memory0.5 x $0.004445 x 720h약 $1.60
Fargate 합계vCPU + memory약 $8.89
t3.small On-Demand$0.0208/h x 720h약 $14.98

이 예시만 보면 Fargate가 싸 보인다. 하지만 Task 하나가 아니라 Task 10개를 계속 띄우면 그림이 바뀐다.

Task 10개, 각 0.5 vCPU / 1 GB

방식월 비용 감각해석
Fargate x 10 Task약 $177Task마다 vCPU/memory 과금이 붙는다
t3.large x 2대약 $120인스턴스에 여러 Task를 집약할 수 있다. 대신 운영 비용이 붙는다

결론은 “10개부터 EC2”처럼 외우는 것이 아니다. 팀이 인스턴스 patch, capacity planning, draining, 보안 기준을 안정적으로 운영할 수 있는지까지 합쳐서 본다. 작은 팀의 변동성 큰 서비스는 Fargate 비용이 운영 단순성을 살 수 있고, 큰 팀의 예측 가능한 workload는 EC2 launch type의 bin packing이 유리해질 수 있다.

right-sizing은 평균보다 peak와 headroom을 본다

섹션 제목: “right-sizing은 평균보다 peak와 headroom을 본다”

비용 최적화에서 가장 흔한 실수는 평균 CPU만 보고 Task size를 줄이는 것이다. 평균 CPU가 20%라도 배포 직후 warmup, 매시 정각 batch, GC, image processing에서 peak가 90%까지 튈 수 있다. 메모리는 CPU보다 더 보수적으로 본다. memory limit을 넘으면 throttling이 아니라 OOMKilled로 바로 종료될 수 있기 때문이다.

관찰성급한 결론더 나은 판단
평균 CPU 15%CPU를 절반으로 줄인다p95/p99 CPU와 burst 시간대를 먼저 본다
평균 memory 45%memory를 절반으로 줄인다peak memory와 GC, image 처리, model warmup을 본다
Task 1개 비용이 낮다Task 수를 계속 늘린다ENI/IP, RDS connection, log volume, downstream rate limit을 같이 본다
Fargate가 EC2보다 비싸다EC2 launch type으로 옮긴다운영 인력 비용, patch 책임, incident 대응 시간을 포함한다

right-sizing의 좋은 순서는 관측 -> 가설 -> 작은 조정 -> 배포 후 비교다. 운영 중 Task CPU/memory를 한 번에 크게 줄이면 비용은 줄 수 있지만, autoscaling이 더 자주 발생하고 cold start가 사용자 latency로 노출될 수 있다.

Fargate Spot은 spare capacity를 할인받는 대신 중단을 받아들인다. “중단 가능”은 단순히 stateless라는 말보다 더 엄격하다.

workloadSpot 적합성이유
이미지 thumbnail 재생성 batch높음실패한 작업을 queue에서 재시도하기 쉽다
개발/스테이징 API중간비용 절감은 크지만 중단 시 팀 workflow 영향을 본다
결제 callback 처리낮음중복 처리와 손실 방지 설계가 먼저다
로그 ingestion writer낮음중단 시 데이터 유실 또는 backlog 폭증이 생길 수 있다

Compute Savings Plans는 예측 가능한 사용량에 약정을 거는 방식이다. 먼저 right-sizing과 baseline 분석을 한 뒤, 계속 켜져 있는 Fargate나 EC2 사용량에 적용하는 순서가 낫다.

Public IPv4 비용도 작은 서비스에서는 눈에 띌 수 있다. Task마다 public IP를 붙이는 구조보다 ALB만 public subnet에 두고 Task는 private subnet에 두면 노출면과 비용을 함께 줄일 수 있다. 다만 private subnet Task가 외부로 나가야 한다면 NAT Gateway나 VPC Endpoint 비용이 생기므로, “public IP 제거 = 항상 비용 절감”으로 단정하지 않는다.

10. Fargate 한계와 EC2 launch type 전환 신호

섹션 제목: “10. Fargate 한계와 EC2 launch type 전환 신호”

Fargate는 단순하지만 모든 workload에 맞지는 않는다. AWS 공식 CPU/memory 조합표 기준으로 Fargate는 정해진 조합 안에서만 Task size를 고를 수 있다. 학습용 스냅샷으로 보면 Linux Fargate는 작은 쪽으로 0.25 vCPU/512 MiB부터, 큰 쪽으로 32 vCPU/244 GB 조합까지 제공된다. 숫자는 서비스 업데이트로 바뀔 수 있으므로 설계 전에는 공식 표를 다시 확인한다.

처음 공부할 때 중요한 것은 최대 숫자 자체보다 제어권의 경계다.

요구Fargate에서의 경계EC2 launch type이 필요한 신호
GPU일반 ECS Fargate workload에서 GPU를 직접 고르지 않는다ML inference, CUDA, video processing
privileged containerFargate는 privileged access를 지원하지 않는다eBPF agent, Docker-in-Docker, host namespace 접근
custom AMI/host tuningunderlying host에 접근하지 않는다커널 모듈, 특수 보안 에이전트, OS-level tuning
매우 큰 memory/CPU정해진 Fargate CPU/memory 조합 안에서만 선택한다조합을 넘거나 특정 instance family가 필요
predictable high densityTask 단위 과금이 커질 수 있다많은 Task를 EC2에 packed 배치해 비용을 낮출 수 있음

또 하나의 경계는 debugging 방식이다. EC2에 직접 들어가던 습관으로 Fargate host에 SSH 접속할 수는 없다. 컨테이너 안에서 짧게 확인해야 할 때는 ECS Exec을 설정해 shell을 열 수 있지만, 이것도 IAM 권한, SSM 경로, audit log를 전제로 한 진단 도구다. 장기적으로는 “들어가서 고친다”보다 로그, metric, health endpoint, config validation으로 문제를 밖에서 관측 가능하게 만드는 것이 맞다.

decision 실패 사례 1: memory 상한과 OOMKilled

섹션 제목: “decision 실패 사례 1: memory 상한과 OOMKilled”

임베딩 추론 서비스가 큰 모델을 메모리에 올리고 batch size를 키우면 Task당 working set이 빠르게 늘어난다. 처음에는 Fargate의 더 큰 CPU/memory 조합으로 올리면 해결될 것처럼 보인다. 하지만 모델 warmup, 동시 요청 queue, GC peak가 겹치면 OOMKilled가 반복될 수 있다.

선택지는 둘이다.

  1. batch size와 concurrency를 줄여 Fargate 조합 안에 맞춘다. latency나 throughput을 포기한다.
  2. ECS on EC2로 옮겨 memory가 큰 instance family, GPU, host-level agent를 직접 관리한다. 운영 부담이 돌아온다.

이 반례는 “Fargate가 나쁘다”가 아니라 serverless container의 단순성이 host-level 제어권을 줄인 대가라는 점을 보여준다.

decision 실패 사례 2: launch type 전환 비용

섹션 제목: “decision 실패 사례 2: launch type 전환 비용”

초기에 Fargate launch type으로 Service를 만들고 운영하다가 나중에 EC2 launch type으로 바꾸려 하면, 일부 속성은 직접 flip하듯 바뀌지 않는다. 새 capacity provider, 새 Service, Target Group 연결, DNS 또는 traffic cutover 계획이 필요할 수 있다.

처음부터 capacity provider 전략으로 설계하면 전환 비용이 줄어든다. 특히 장기적으로 Fargate와 EC2를 섞을 가능성이 있으면 “launch type 하나를 고정”하기보다 capacity provider를 학습 모델의 기본값으로 보는 편이 낫다.

EC2 직접 운영, ECS on EC2, ECS on Fargate

섹션 제목: “EC2 직접 운영, ECS on EC2, ECS on Fargate”
질문EC2 직접 운영ECS on EC2ECS on Fargate
컨테이너 자동 복구직접 스크립트/프로세스 매니저 구성ECS Service가 담당ECS Service가 담당
서버 patch와 AMI직접직접AWS에 대부분 위임
bin packing직접ECS가 인스턴스 pool 안에서 수행AWS가 task 단위로 처리
세밀한 host 제어가장 높음높음낮음
운영 난이도높음중간~높음낮음
비용 최적화 여지높지만 직접 구현높음workload가 작거나 변동적일 때 유리

첫 서비스라면 Fargate로 시작해 개념과 배포 흐름을 익히는 것이 단순하다. 하지만 높은 사용률로 24시간 많은 Task를 돌리고, 팀이 인스턴스 운영 역량을 갖췄으며, 특수 hardware나 host 제어가 필요하다면 ECS on EC2가 더 합리적일 수 있다.

ECS와 EKS는 둘 다 컨테이너 orchestration 계층이다. EC2와 ECS의 관계보다 이쪽이 더 진짜 “vs”에 가깝다.

선택 기준ECS가 유리한 경우EKS가 유리한 경우
AWS 단일 환경AWS 서비스 통합과 운영 단순성이 중요하다Kubernetes 표준 API가 꼭 필요하지 않다
멀티클라우드/온프레미스요구가 약하다Kubernetes 생태계와 이식성이 중요하다
팀 전문성Kubernetes 전담 운영자가 없다cluster upgrade, add-on, policy 운영을 감당할 수 있다
생태계ALB, IAM, CloudWatch 중심이면 충분하다Istio, Argo CD, OPA, KEDA 같은 CNCF 도구가 필요하다

EKS는 EC2의 대체물이 아니라 Kubernetes control plane을 AWS에서 관리해 주는 서비스다. ECS를 이해한 뒤 EKS를 읽을 때는 “Task Definition은 Pod spec에 가깝고, Service desiredCount는 Deployment replicas에 가깝다” 정도로 옮겨 가면 된다.

12. 실패 신호로 이해하는 ECS 문제

섹션 제목: “12. 실패 신호로 이해하는 ECS 문제”

긴 CLI 런북보다 먼저 증상과 개념을 연결한다.

증상의미먼저 볼 개념
Task가 STOPPED로 반복 재시작컨테이너가 시작 후 종료된다Stopped reason, container logs, env validation
CannotPullContainerErrorimage를 pull하지 못한다Execution Role, ECR 권한, NAT 또는 ECR/S3/Logs endpoint
PROVISIONING에서 오래 멈춤Task 실행 준비에 필요한 capacity나 network path가 부족하다Subnet IP, ENI, NAT, VPC endpoint
OOMKilled 또는 exit code 137Task memory 한도를 넘었다Task Definition memory, application peak, Node heap
배포가 계속 in progress새 Task가 healthy가 되지 못하거나 교체 여유가 없다ALB health check, minimum/maximum percent, capacity
ALB 502가 배포 직후 낮은 비율로 발생drain과 shutdown 시간이 맞지 않는다deregistration delay, stopTimeout, graceful shutdown
Task는 RUNNING인데 S3 접근만 실패앱 코드 권한이 없다Task Role과 Execution Role 구분, IAM policy
환경변수 오타가 조용히 기본값으로 대체앱은 뜨지만 잘못된 외부 시스템을 호출한다Config validation, Task Definition revision diff
scale-out 후 DB too many connectionsTask 수 x pool max가 DB 한도를 넘었다RDS max_connections, pool max, RDS Proxy
특정 AZ에서만 Task가 부족subnet/capacity가 AZ별로 다르다subnet free IP, capacity provider, placement

Task Definition에 DATABASE_URL 대신 DATABSE_URL을 넣어도 ECS는 key 이름의 의미를 모른다. 애플리케이션이 process.env.DATABASE_URL || fallback 같은 패턴을 쓰면 정상 부팅하고 ALB health check도 통과할 수 있다. 하지만 실제 트래픽은 fallback DB, 잘못된 callback URL, 비활성 feature flag로 흐른다.

이 문제의 해법은 콘솔에서 환경변수를 눈으로 찾는 것이 아니라 부팅 시 필수 설정 검증을 실패시키는 것이다. 설정 누락을 loud failure로 만들면 ECS Service가 잘못된 Task를 healthy로 받아들이지 않는다.

전체 요청 중 0.05%만 502라면 평균 대시보드에서는 노이즈처럼 보인다. 그러나 배포 직후나 scale-in 직후에만 spike가 생기고, ALB access log에서 target_processing_time = -1 또는 target status code 누락이 반복된다면 긴 요청이 drain 전에 잘렸을 수 있다.

이때는 “ALB가 가끔 이상하다”가 아니라 다음 관계를 본다.

긴 요청 p99
< ALB deregistration delay
<= ECS stopTimeout과 애플리케이션 shutdown 처리 시간의 조합

정확한 숫자는 서비스마다 다르지만, 부등식이 깨지면 짧은 요청은 정상이고 긴 요청만 실패하는 silent failure가 된다.

13. 선택 부록 — 절차는 짧게 확인한다

섹션 제목: “13. 선택 부록 — 절차는 짧게 확인한다”

본문을 이해하는 데 필요한 것은 위의 원리다. 실제 콘솔에서 확인할 때는 다음 순서로 좁힌다.

Task가 멈췄을 때
  1. ECS Service Events에서 배포 상태와 실패 메시지를 본다.
  2. Stopped Task의 Stopped reason과 container exit code를 본다.
  3. CloudWatch Logs에서 애플리케이션 로그를 본다.
  4. CannotPullContainerError면 애플리케이션 로그가 아니라 Execution Role과 ECR/network path를 본다.
  5. OOMKilled면 코드보다 Task memory와 peak 사용량을 먼저 본다.
Private Subnet Task가 AWS 서비스에 접근하지 못할 때
  1. Task가 속한 Subnet의 route table을 본다.
  2. 외부 인터넷 목적지가 필요하면 NAT Gateway 경로가 있는지 본다.
  3. ECR, S3, CloudWatch Logs, Secrets Manager처럼 AWS 서비스 목적지라면 VPC Endpoint가 있는지 본다.
  4. ECR image pull 실패는 Execution Role 권한과 network path를 함께 본다.
배포가 멈췄을 때
  1. 새 Task가 RUNNING까지 갔는지 본다.
  2. Target Group에서 새 Task IP가 healthy인지 본다.
  3. health check path, port, security group을 본다.
  4. minimumHealthyPercentmaximumPercent가 새 Task를 띄울 여유를 주는지 본다.
  5. Subnet IP와 capacity provider가 rolling update 중 공존 수를 감당하는지 본다.

14. 오케스트레이션 원리의 전이

섹션 제목: “14. 오케스트레이션 원리의 전이”

ECS를 제대로 이해하면 Kubernetes나 Nomad를 처음 볼 때도 질문을 옮겨 갈 수 있다. 이 절은 hard prerequisite가 아니라 선택 심화다.

ECS 개념을 Kubernetes로 옮겨 읽기

Task Definition ↔ Pod Spec

컨테이너 image, resource, port, env 같은 실행 스펙을 정의한다.

새 workload의 실행 단위를 읽을 때

Task ↔ Pod

정의된 스펙이 실제로 떠 있는 runtime instance다. 죽고 새로 만들어질 수 있다.

로그, 상태, 종료 원인을 추적할 때

Service ↔ Deployment + Service

원하는 개수를 유지하고, health와 traffic routing을 관리한다.

무중단 배포와 트래픽 전환을 볼 때

Task Role ↔ ServiceAccount

애플리케이션 코드가 외부 API나 cloud API를 호출할 때 쓰는 identity다.

S3, SQS, Secret 접근 권한을 점검할 때

Health check ↔ Probe

살아 있는 process와 traffic을 받아도 되는 endpoint를 구분한다.

배포가 멈추거나 반복 재시작할 때

새 오케스트레이터를 보면 네 질문만 먼저 던진다.

  1. 원하는 상태를 어디에 선언하는가?
  2. actual state와 desired state를 비교하는 주체는 누구인가?
  3. 새 workload를 배치할 capacity는 누가 관리하는가?
  4. traffic을 받을 수 있는 healthy 상태는 어떤 check로 판단하는가?

이 네 질문에 답하면 이름이 달라도 큰 구조는 읽힌다.

  • AWS 콘솔에서 팀 ECS Cluster를 열고 Service, desired count, running count를 비교한다.
  • Service의 최신 deployment에서 Task Definition revision이 무엇인지 확인한다.
  • Task Definition에서 executionRoleArntaskRoleArn을 구분해 본다.
  • 실행 중 Task 하나를 열어 Subnet, ENI, Security Group, private IP를 확인한다.
  • Target Group에서 ECS Task IP가 healthy로 등록되어 있는지 본다.
  • Service Auto Scaling의 min/max capacity가 RDS max_connections와 subnet IP를 넘지 않는지 손으로 계산한다.
  • 배포 직후 ALB 5xx가 있으면 target deregistration, stopTimeout, 애플리케이션 shutdown hook의 관계를 확인한다.
  • 환경변수 silent failure가 의심되면 Task Definition revision의 key 목록과 앱의 필수 config validation 목록을 비교한다.
개념 A개념 B차이점
EC2ECSEC2는 compute 서버, ECS는 컨테이너 orchestration 서비스다.
ECSFargateECS는 orchestration 계층, Fargate는 ECS Task를 실행하는 serverless capacity다.
ECS on EC2EC2 직접 운영둘 다 EC2를 쓰지만, 전자는 ECS가 Task 배치/복구/배포를 맡는다.
Task DefinitionTaskDefinition은 실행 스펙, Task는 그 스펙으로 실제 실행된 instance다.
TaskServiceTask는 실행 단위, Service는 Task를 원하는 개수로 유지하는 관리 단위다.
Task RoleExecution RoleTask Role은 앱 코드 권한, Execution Role은 ECS가 Task를 시작하는 권한이다.
ALB target healthyTask RUNNINGRUNNING이어도 health check 실패 시 traffic을 받지 않는다.
capacity 부족애플리케이션 버그새 Task를 못 띄우는 문제와 Task가 떠서 바로 죽는 문제는 다르다.

ECS vs EC2 복습 체크리스트

  • EC2는 compute 자원이고 ECS는 orchestration 계층이라고 구분할 수 있다.
  • ECS가 EC2 launch type과 Fargate launch type 모두에서 실행될 수 있음을 설명할 수 있다.
  • ECR, Task Definition, Task, Service, Cluster의 관계를 image부터 실행까지 순서로 말할 수 있다.
  • desiredCount=3에서 Task 하나가 죽었을 때 ECS Service가 어떻게 desired state를 복원하는지 설명할 수 있다.
  • ALB → Target Group → Task IP 흐름과 Fargate awsvpc/ENI의 관계를 그릴 수 있다.
  • rolling update 중 maximumPercent와 minimumHealthyPercent가 왜 capacity와 IP 요구량을 바꾸는지 설명할 수 있다.
  • autoscaling 최대 Task 수를 subnet IP와 RDS max_connections 기준으로 제한해야 함을 계산할 수 있다.
  • Fargate와 ECS on EC2의 비용, 운영 부담, 제어권 trade-off를 비교할 수 있다.
  • CannotPullContainerError, OOMKilled, 배포 stuck, 낮은 비율의 ALB 502를 증상별로 먼저 의심할 개념에 연결할 수 있다.

ECR, ALB Target Group, Fargate Spot, Capacity Provider, Service Auto Scaling, Blue/Green Deployment, ECS Exec, CloudWatch Container Insights, EKS, Kubernetes Deployment, RDS Proxy

  1. EC2는 가상 서버이고, ECS는 컨테이너를 desired state로 유지하는 orchestration 서비스다.
  2. ECS는 EC2 위에서도, Fargate 위에서도 실행된다. 따라서 “ECS vs EC2”보다 “서버 관리를 어디까지 맡길 것인가”가 정확한 질문이다.
  3. ECS의 핵심 흐름은 ECR image → Task Definition → Task → Service → Cluster이고, Service가 health check와 scheduler로 Task 수를 맞춘다.
  4. Fargate는 서버 운영 부담을 줄이지만 ENI/IP, CPU/memory 조합, privileged/GPU/host 제어 제약을 이해해야 한다.
  5. 배포와 scaling 문제는 Task 상태만 보지 말고 ALB target health, subnet IP, RDS max_connections, graceful shutdown까지 함께 봐야 한다.