AWS ECS + RDS - Nginx + FastAPI + MySQL (Bridge Mode)
AWS ECS + RDS - Nginx + FastAPI + MySQL (Bridge Mode)
아키텍처 개요
┌─────────────────────────────────────────────────────────────────┐
│ ECS Cluster (EC2) │
│ ┌─────────────────────────────────────────────────┐ │
Internet ──► ALB ──►│ │ EC2 Instance (10.0.10.x) │ │
:80 :32768+ │ │ ├─ nginx (host:32768+ → :80) │ │
│ │ └─ fastapi (:3000) ← links ─────────────────────► RDS │
│ └─────────────────────────────────────────────────┘ (MySQL) │
│ Target Group: Instance Type (bridge, nginx만 연결) 3306 │
└─────────────────────────────────────────────────────────────────┘
bridge 모드 + links + RDS: nginx → fastapi → MySQL (RDS Multi-AZ)
선행 작업
목차
구성 프로세스
| 단계 | 작업 | 설명 | 콘솔 경로 |
|---|---|---|---|
| 1 | VPC/Subnet 생성 | VPC, 서브넷(Public/Private), IGW, NAT 구성 | VPC > VPC 생성 |
| 2 | 보안 그룹 생성 | ALB용, ECS용, RDS용 보안 그룹 생성 | VPC > 보안 그룹 |
| 3 | RDS 서브넷 그룹 | Private 서브넷 2개로 DB 서브넷 그룹 생성 | RDS > 서브넷 그룹 |
| 4 | RDS 인스턴스 생성 | MySQL Multi-AZ 배포 | RDS > 데이터베이스 생성 |
| 5 | ECR 리포지토리 생성 | project-web, project-fastapi-mysql 리포지토리 | ECR > 리포지토리 생성 |
| 6 | Docker 이미지 빌드 & 푸시 | nginx, fastapi-mysql 이미지 빌드 | EC2 SSH 접속 |
| 7 | ECS 클러스터 생성 | EC2 기반 클러스터 생성 | ECS > 클러스터 생성 |
| 8 | 태스크 정의 생성 | project-web + project-fastapi-mysql (환경 변수) | ECS > 태스크 정의 |
| 9 | ⭐ 대상 그룹 생성 | project-tg-nginx 1개만 생성 | EC2 > 대상 그룹 |
| 10 | ⭐ ALB 생성 | 대상 그룹 연결 | EC2 > 로드 밸런서 |
| 11 | ECS 서비스 생성 | 단일 서비스 (project-tg-nginx 연결) | ECS > 서비스 생성 |
| 12 | 점검 | Health Check, DB 연결 확인 | - |
보안 그룹
리소스(project-sg-alb)
| 변수 | 값 | 소스 |
|---|---|---|
| 보안 그룹 이름 | project-sg-alb | - |
| 인바운드 규칙 | TCP 80 | 0.0.0.0/0 |
| 인바운드 규칙 | TCP 443 | 0.0.0.0/0 |
| 아웃바운드 규칙 | 모든 트래픽 | 0.0.0.0/0 |
리소스(project-sg-ecs)
| 변수 | 값 | 소스 |
|---|---|---|
| 보안 그룹 이름 | project-sg-ecs | - |
| 인바운드 규칙 | TCP 32768-65535 | project-sg-alb |
| 인바운드 규칙 | TCP 22 | 관리자 IP |
| 아웃바운드 규칙 | 모든 트래픽 | 0.0.0.0/0 |
| 설명 | 동적 포트 매핑 (bridge 모드) | - |
리소스(project-sg-rds) ⭐
| 변수 | 값 | 소스 |
|---|---|---|
| 보안 그룹 이름 | project-sg-rds | - |
| 인바운드 규칙 | TCP 3306 | project-sg-ecs |
| 아웃바운드 규칙 | 모든 트래픽 | 0.0.0.0/0 |
| 설명 | ECS에서만 MySQL 접근 허용 | - |
💡 RDS 보안 그룹은 ECS 보안 그룹에서만 접근 허용
RDS (MySQL Multi-AZ)
DB 서브넷 그룹
RDS > 서브넷 그룹 > DB 서브넷 그룹 생성
| 변수 | 값 |
|---|---|
| 이름 | project-db-subnet-group |
| 설명 | Pista RDS Subnet Group |
| VPC | project-vpc |
| 가용 영역 | ap-northeast-2a, ap-northeast-2b |
| 서브넷 | project-subnet-private1-1a, project-subnet-private2-1b |
⚠️ Multi-AZ를 위해 최소 2개 AZ의 서브넷 필요
RDS 인스턴스 생성
RDS > 데이터베이스 > 데이터베이스 생성
| 구분 | 변수 | 값 |
|---|---|---|
| 엔진 옵션 | 엔진 유형 | MySQL |
| 엔진 버전 | MySQL 8.0.x | |
| 템플릿 | 템플릿 | 프로덕션 (또는 개발/테스트) |
| 가용성 및 내구성 | 배포 옵션 | Multi-AZ DB 인스턴스 ⭐ |
| 설정 | DB 인스턴스 식별자 | project-rds-mysql |
| 마스터 사용자 이름 | admin | |
| 마스터 암호 | <DB_PASSWORD> | |
| 인스턴스 구성 | DB 인스턴스 클래스 | db.t3.micro (개발) / db.t3.small |
| 스토리지 | 스토리지 유형 | gp3 |
| 할당된 스토리지 | 20 GiB | |
| 스토리지 자동 조정 | ✅ | |
| 연결 | VPC | project-vpc |
| DB 서브넷 그룹 | project-db-subnet-group | |
| 퍼블릭 액세스 | ❌ (아니요) | |
| VPC 보안 그룹 | project-sg-rds | |
| 가용 영역 | 기본 설정 없음 (Multi-AZ) | |
| 데이터베이스 인증 | 인증 옵션 | 암호 인증 |
| 추가 구성 | 초기 데이터베이스 이름 | project |
| 백업 보존 기간 | 7일 | |
| 삭제 방지 | ✅ |
RDS 엔드포인트
생성 후 확인:
project-rds-mysql.xxxxxxxxxx.ap-northeast-2.rds.amazonaws.com
💡 이 엔드포인트를 ECS 태스크 정의의 환경 변수
DB_HOST에 설정
ECR 이미지 준비
| 이미지 | 소스 경로 | 포트 |
|---|---|---|
| nginx | ECR/images/fastapi/nginx/ | 80 |
| fastapi-mysql | ECR/images/fastapi-mysql/ | 3000 |
빌드 및 푸시
# ECR 로그인
aws ecr get-login-password --region ap-northeast-2 | \
docker login --username AWS --password-stdin <ACCOUNT_ID>.dkr.ecr.ap-northeast-2.amazonaws.com
# fastapi-mysql 빌드 및 푸시
cd ECR/images/fastapi-mysql
docker build -t project-fastapi-mysql .
docker tag project-fastapi-mysql:latest <ACCOUNT_ID>.dkr.ecr.ap-northeast-2.amazonaws.com/project-fastapi-mysql:latest
docker push <ACCOUNT_ID>.dkr.ecr.ap-northeast-2.amazonaws.com/project-fastapi-mysql:latest
클러스터 생성
리소스(project-cluster-rds)
| 구분 | 항목 | 값 |
|---|---|---|
| 클러스터 이름 | 클러스터 이름 | project-cluster-rds |
| 인프라 | 컴퓨팅 용량 확보 방법 | EC2 자체 관리형 ✅ |
| Auto Scaling 그룹 | 새 ASG 생성 | |
| 프로비저닝 모델 | 온디맨드 | |
| AMI | Amazon Linux 2023 | |
| EC2 인스턴스 유형 | t3.medium | |
| EC2 인스턴스 역할 | ecsInstanceRole | |
| 원하는 용량 (최소/최대) | 2 / 3 | |
| 네트워크 | VPC | project-vpc |
| 서브넷 | project-subnet-private1-1a, private2-1b | |
| 보안 그룹 | project-sg-ecs | |
| 퍼블릭 IP 자동 지정 | x |
태스크 정의
인프라 요구 사항
| 구분 | 항목 | 값 |
|---|---|---|
| 태스크 정의 구성 | 패밀리 | project-task-rds |
| 인프라 요구 사항 | 시작 유형 | Amazon EC2 인스턴스 ✅ |
| 네트워크 모드 | bridge | |
| CPU | 0.75 vCPU | |
| 메모리 | 1.5 GB | |
| 태스크 역할 | ecsTaskExecutionRole | |
| 태스크 실행 역할 | ecsTaskExecutionRole |
컨테이너 1: project-web (nginx)
| 구분 | 항목 | 값 |
|---|---|---|
| 컨테이너 | 이름 | project-web |
| 이미지 URI | <ACCOUNT_ID>.dkr.ecr...project-web:latest | |
| 포트 매핑 | 호스트 포트 | 0 (동적) |
| 컨테이너 포트 | 80 | |
| 필수 컨테이너 | ✅ | |
| 네트워크 설정 | 링크 | project-fastapi-mysql:fastapi |
컨테이너 2: project-fastapi-mysql ⭐
| 구분 | 항목 | 값 |
|---|---|---|
| 컨테이너 | 이름 | project-fastapi-mysql |
| 이미지 URI | <ACCOUNT_ID>.dkr.ecr...project-fastapi-mysql:latest | |
| 포트 매핑 | 호스트 포트 | 0 (동적) |
| 컨테이너 포트 | 3000 | |
| 필수 컨테이너 | ✅ | |
| 환경 변수 | DB_HOST | project-rds-mysql.xxx.rds.amazonaws.com |
| DB_PORT | 3306 | |
| DB_USER | admin | |
| DB_PASSWORD | ||
| DB_NAME | project |
⚠️ 보안 권장:
DB_PASSWORD는 Secrets Manager 사용 권장
대상 그룹
💡 links 방식: nginx가 fastapi로 프록시하므로 대상 그룹은 nginx 1개만 필요
리소스(project-tg-nginx)
| 변수 | 값 |
|---|---|
| 설정-대상 유형 | 인스턴스 |
| 설정-대상 그룹 이름 | project-tg-nginx |
| 설정-프로토콜 | HTTP |
| 설정-포트 | 80 |
| 설정-VPC | project-vpc |
| 상태 검사-상태 검사 경로 | / |
로드 밸런서
리소스(project-alb-rds)
| 변수 | 값 |
|---|---|
| 기본 구성-로드 밸런서 이름 | project-alb-rds |
| 기본 구성-체계 | 인터넷 경계 |
| 네트워크 매핑-VPC | project-vpc |
| az1 | project-subnet-public1-1a |
| az2 | project-subnet-public2-1b |
| 보안 그룹 | project-sg-alb |
| 리스너 및 라우팅-대상그룹 | project-tg-nginx |
서비스 정의
리소스(project-service-rds)
| 구분 | 항목 | 값 |
|---|---|---|
| 서비스 세부 정보 | 서비스 이름 | project-service-rds |
| 태스크 정의 패밀리 | project-task-rds | |
| 환경 | 컴퓨팅 옵션 | 용량 공급자 전략 |
| 배포 구성 | 원하는 태스크 | 2 |
| 로드 밸런싱 | 로드 밸런서 | project-alb-rds (기존) |
| 대상 그룹 | project-tg-nginx (기존) | |
| 컨테이너 선택 | project-web (포트 80) |
점검
- RDS 인스턴스 상태 확인 (Available)
- RDS 엔드포인트 복사
- ECR 이미지 푸시 확인
- ECS 클러스터 인스턴스 등록 확인
- 대상 그룹 Health Check 통과 확인
- ALB DNS로 접속 테스트
-
http://<ALB-DNS>/→ nginx 정적 페이지 -
http://<ALB-DNS>/api/health→ DB 연결 확인 -
http://<ALB-DNS>/api/db/test→ MySQL 버전 확인
-
- nginx → fastapi → RDS 통신 테스트
Troubleshooting
| 증상 | 원인 | 해결 |
|---|---|---|
| DB 연결 실패 | 보안 그룹 미허용 | project-sg-rds에 project-sg-ecs 허용 확인 |
| RDS 접근 불가 | 서브넷 라우팅 | Private 서브넷의 NAT 라우팅 확인 |
| 환경 변수 미적용 | 태스크 정의 | ECS 태스크 정의에서 환경 변수 확인 |
| Health Check 실패 | fastapi 에러 | CloudWatch 로그 확인 |