Notice
Recent Posts
Link
Tags
- spring mvc
- ORM
- 자바
- nginx
- 문자열
- select
- hibernate
- join
- spring
- 데이터베이스
- 프로그래머스
- SSL
- PYTHON
- Docker
- mysql
- 스프링
- DI
- AWS
- spring security 6
- static
- sql
- string
- 1차원 배열
- java
- jpa
- @transactional
- springboot
- spring boot
- 스프링부트
- Django
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | |
7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 29 | 30 |
Archives
개발하는 자몽
[TIL / AWS] SpringBoot 서버리스로 배포하기: ECR + Fargate(ECS) + ALB + Private Link 본문
Architecture & Tool/AWS
[TIL / AWS] SpringBoot 서버리스로 배포하기: ECR + Fargate(ECS) + ALB + Private Link
jaamong 2025. 8. 7. 23:54📌공유도 있지만, 기록이 더 큰 목적... Windows 11, Gradle/SpringBoot.
AWS에서 "아.. Fargate 좋은데... 안쓰나... 진짜 좋은데..." 라고 계속 홍보하는 것 같아서 이번 프로젝트에서는 도대체 얼마나 좋길래? 하고 사용해봤다.
후기! EC2 보다 비용이 좀(꽤) 나가지만, 서버 설정이 편리하다. 서버 설정 자체는 신경을 안쓰게 되긴하는데 인프라는 건들게 너무... 많다...
- 자세히는, 퍼블릭 서브넷에 배포한다면 정말 금방 끝낼 수 있다. 하지만 프라이빗 서브넷에 배포한다면 많은 설정들이 기다리고 있다. (이때 배포하는 과정에서 Private Link 관련으로 삽집을 많이해서 기록용으로 작성하게 됐다)
- 불편한 점이 꽤 있다. EC2로 배포하면 당연했던 것들이 서버리스라서 그런지 안되는 게 꽤 있다. 그 중 하나는 보통 private subnet에 위치한 RDS에 EC2를 터널링으로 사용하여 접근했는데, Fargate는 이게 안된다.(서버 접근할 때 사용하는 키페어가 없음) 그래서 Bastion Host 용도로 nano 인스턴스 타입의 EC2를 하나 생성했다🥲
- 로그 설정이나 확인이 EC2보다 어려운 것 같다.
컨테이너 오케스트레이션 목적이 크지 않다면, 다음에도 Fargate를 또 쓸지는 모르겠다.
사전 준비
- Docker 계정
- AWS CLI 설치
- AWS CLI를 사용할 수 있는 AWS IAM 계정 (충분히 권한이 있는지)
Fargate
- Fargate는 서버리스 컴퓨팅 서비스로 컨테이너를 실행하기 위해 사용할 수 있다. ECS와 함께 사용해야 한다(단독 사용 X).
- ECS는 Elastic Container Service의 줄임말로, 이름대로 완전 관리형 컨테이너 오케스트레이션 서비스이다. 쿠버네티스가 아닌 도커 컨테이너 관리를 위한 서비스이다. 쿠버네티스는 EKS라고 따로 있다.
- Fargate는 EC2와 달리 사용자가 서버나 클러스터를 관리할 필요가 없지만, 실제로는 EC2 위에서 실행된다.
- EC2와 동일 스펙으로 두고 보았을 때 요금이 더 비싸다. (솔직히 EC2에 비해 조금... 부담될 수도 있다.)
- CloudWatch와 자동 연동 된다.
- 리소스(Task) 생성 시 VPC 내부 서브넷에 위치한다.
ECR
- ECR은 컨테이너 이미지를 저장 및 관리할 수 있는 서비스이다. 여기에 빌드한 Docker 이미지를 올려서 ECS(Fargate)를 통해 배포할 수 있다.
- 컨테이너 이미지 레이어를 S3에 저장한다.
- VPC 밖에 위치한다.
- 따라서 Fargate(VPC 내부)에서 ECR(S3)에 저장된 컨테이너 이미지를 가져오려면 인터넷 통신이 필요함
- Fargate의 위치가 퍼블릭 서브넷이고, 생성 시 공인 IP가 자동 할당되도록 설정했다면 문제없음
- 프라이빗 서브넷이면 공인 IP가 할당되어도 인터넷 통신이 불가능하므로 ECR(S3)에서 컨테이너 이미지를 가져올 수 없음 → NAT Gateway 사용 또는 Private Link 구성으로 해결해야 함
- 따라서 Fargate(VPC 내부)에서 ECR(S3)에 저장된 컨테이너 이미지를 가져오려면 인터넷 통신이 필요함
Private Link
- VPC 엔드포인트, Gateway Endpoints(S3 또는 DynamoDB)를 사용해서 VPC 밖에 있는 두 서비스 사이에서 인터넷이 아닌 사설(private) 통신이 가능하도록 하는 서비스
- 둘 중에 무엇을 선택할지는 비용을 따지는 편. 발생하는 비용은 각자 서비스의 데이터 처리량 등을 고려하여 계산.
Fargate로 SpringBoot 애플리케이션 배포하기
- Dockerfile 작성하기
- 도커 이미지 빌드 및 도커 허브에 push (이미지 이름 기억해 두기)
- ECR에서 Private Repository 생성
- 생성한 레포지토리를 선택하고 푸시 명령 보기 클릭, 가이드 보면서 순차적으로 진행
- ECR 레지스트리에 Docker 클라이언트 인증 시 AWS CLI default 프로필 외에 다른 프로필 사용 시 아래와 같이 진행
aws ecr get-login-password --region ap-northeast-2 --profile {profile_alias}| docker login --username AWS --password-stdin {account_id}.dkr.ecr.ap-northeast-2.amazonaws.com
- 태깅할 때 태그는 앞으로 생성될 이미지 태그와 겹치지 않게 고유한 태그로 생성할 것
- ECR 레지스트리에 Docker 클라이언트 인증 시 AWS CLI default 프로필 외에 다른 프로필 사용 시 아래와 같이 진행
- 클러스터 생성: 클러스터는 서비스나 태스크의 논리적인 그룹이다.
- ECS > 클러스터 > 클러스터 생성
- 인프라: AWS Fargate
- 클러스터 이름 작성이랑 인프라 선택만 하고 완료하기
- 작업(Task) 정의: Task에 필요한 명세를 정의한다. Amazon ECS에서 Docker 컨테이너를 실행하려면 작업 정의(Task Definition)가 필요함. 이전에 생성한 도커 이미지를 참조하는 작업 정의를 생성한다.
- ECS > 태스크 정의 > 새 태스크 정의 생성 > 새 태스크 정의 생성
- 태스크 정의 패밀리: 고유한 이름 지정
- 인프라
- 시작 유형: AWS Fargate
- 태스크 역할
- 태스크 역할: 건들지 않음
- 태스크 실행 역할: Amazon ECS를 처음 사용하는 경우 `ecsTaskExcutionRole IAM` 역할이 존재 X. 이 경우는 Task execution role 설정에서 Create new role을 선택하면 자동으로 `ecsTaskExcutionRole` IAM 역할이 생성됨.
- 애플리케이션에 필요한 사양에 맞춰서 진행
- 컨테이너
- 이름: 임의 지정
- 이미지 URI: ECR에 올린 도커 이미지의 URI로 ECR > 프라이빗 레지스트리 > 리포지토리 > {생성한 리포지토리}에서 이미지 URI를 복사할 수 있음
- 필수 컨테이너: 예
- 프라이빗 레지스트리: 비활성화
- 포트 매핑: 여기에서는 스프링부트의 8080번 포트로 지정. 이 부분은 각자의 환경에 맞춰 설정. 로드밸런싱을 사용한다면 여기에서 로드밸런서의 요청을 받을 포트를 설정.
- 로깅
- `awslogs-region`을 잘 확인하고, 나머지는 위와 같이 설정한다.
- 나머지는 기본 상태로 두고 작업 정의를 완료한다.
- ECS > 태스크 정의 > 새 태스크 정의 생성 > 새 태스크 정의 생성
- ECS 작업 IAM 역할 수정: 앞 단계에서 자동 생성된 ECS 작업의 IAM 역할인 `ecsInstanceRole`에 `CloudWatchLogsFullAccess`를 추가
- IAM > 역할 > ecs 검색 > `ecsInstanceRole` 선택
- 권한 탭 > 우측 권한 추가 메뉴 > 정책 연결 클릭
- 검색창에서 `CloudWatchFullAcess` 검색 > ` CloudWatchFullAcessV2` 선택 > 권한 추가 클릭
- 추가된 정책 확인
- ALB 구성 및 생성: private subnet에 위치한 ECS와 연결하여 외부 트래픽 진입점이 될 ALB를 생성한다.
- 대상 그룹 생성
- EC2 > 대상 그룹 > 대상 그룹 생성
- 대상 유형: IP address
- 타겟 그룹 이름: 자유롭게 설정(보통 tg를 이름에 넣어서 대상 그룹임을 명시하는 편)
- 프로토콜 : 포트: HTTP : 8080(ALB가 요청을 보내줄 포트, 배포할 컨테이너(ECS)의 실행 포트로 입력. 모르겠다면 애플리케이션의 실행포트로 입력)
- VPC: 로드 밸런서를 호스팅 할 VPC 선택(ECS가 있는 VPC로)
- 상태 검사: 애플리케이션에 헬스 체크 API가 있다면 여기에 입력
- 나머지는 기본값으로 놔두고 다음 클릭
- 대상 등록: 아무것도 건들지 않고, 대상도 등록하지 않고 생성 완료하기. 나중에 ECS가 생성될 때 생성된 태스크가 자동으로 등록됨.
- ALB 생성
- EC2 > 로드 밸런서 > 로드 밸런서 생성
- ALB 생성
- 로드 밸런서 이름: 자유롭게 설정(tg처럼 이름에 alb를 추가해서 명시하는 편)
- 체계(schema): 인터넷 경계(internet-facing)
- 네트워크 매핑: 대상 그룹과 동일한 VPC
- 선택 후, 가용 영역 및 서브넷: 2개 이상 선택
- 보안 그룹: 이 ALB를 위해 생성해 둔 것이 없다면 새롭게 생성. 보안 그룹은 아래 조건을 만족하면 됨.
- 새로 생성 시 아웃바운드는 건들지 않고, 외부 트래픽을 받을 수 있도록 인바운드만 설정
- 유형: HTTP
- 포트: 80
- 소스: 0.0.0.0/0
- 새로 생성 시 아웃바운드는 건들지 않고, 외부 트래픽을 받을 수 있도록 인바운드만 설정
- 리스너 및 라우팅: 외부 트래픽을 어떤 프로토콜과 포트로 받을지 결정하여 이 통로만 열어두고(리스너) , 받은 요청을 어디로 보낼지(라우팅) 설정
- 프로토콜: HTTP
- 포트: 80
- 대상 그룹: 방금 생성한 대상 그룹 선택. 여기로 요청이 라우팅 된다.
- 요약 정보를 확인하고, 모두 맞다면 완료하기
- 대상 그룹 생성
- ECS 서비스 생성: Amazon ECS를 사용하여 Amazon ECS 클러스터에서 지정된 작업 정의 인스턴스를 동시에 실행하고 관리할 수 있다. 이를 서비스라고 한다.
- ECS > 생성한 클러스터 선택 > 서비스 탭 > 생성 버튼 클릭
- 서비스 세부 정보 설정
- 환경 > 컴퓨팅 구성
- 컴퓨팅 옵션: 시작 유형
- 시작 유형: FARGATE
- 플랫폼 버전: LATEST
- 배포 구성
- 스케줄링 전략: 복제본
- 원하는 태스크: 서비스(여기서는 개발하는 프로덕트를 의미) 상황에 맞게 (여기서는 1개만 함)
- Task: 특정 애플리케이션 기능을 수행하는 하나 이상의 컨테이너
- Service: 동일한 다수의 Task 그룹
- 나머지는 기본값으로 두기
- 네트워킹 설정
- VPC: VPC는 이미 생성된 것을 사용하거나 다른 서비스/프로젝트와 구분 지어 사용하고 싶다면 새롭게 생성. 잘 모르겠다면 default VPC 사용도 상관 X.
- 서브넷: 프라이빗 서브넷(private subnet)으로 선택.
- 퍼블릭 서브넷(public subnet)도 가능함. 이 경우 다음을 참고.
- ALB & VPC 엔드포인트나 NAT 없이도 외부 트래픽을 받을 수 있음
- 퍼블릭 IP 옵션을 활성화 → 하나의 퍼블릭 IP에 대해서 시간당 0.005 USD의 요금이 부과됨
- ALB와 VPC 엔드포인트 설정이 별도로 필요 없음
- 퍼블릭 서브넷에 두면 보안 및 확장성 측면에서 좋지 않음
- 퍼블릭 서브넷(public subnet)도 가능함. 이 경우 다음을 참고.
- 보안 그룹: 위에서 생성한 ALB를 고려해서 ECS를 위해 미리 만들어둔 보안 그룹이 없다면, 새로 생성하기
- 보안 그룹 이름: 여기에서도 sg를 이름에 추가해서 보안 그룹임을 명시하는 편
- 설명: 보통 어떤 목적의 보안 그룹인지 작성하는 편
- 인바운드 규칙
- 유형: 사용자 지정
- 포트 범위: 8080 (대상 그룹에서 입력한 포트와 동일하게)
- 소스: ALB를 위해 만들었던 보안그룹을 선택 (ALB를 통해서만 외부 트래픽이 들어올 수 있게 됨)
- 로드 밸런싱
- 로드 밸런싱 사용: 활성화
- VPC: 로드 밸런싱이 위치한 VPC로 선택
- 로드 밸런서 유형: ALB
- Application Load Balancer: 기존 로드 밸런서 사용
- 컨테이너: 기본적으로 잘 선택되어 있을 테니, 가만히 내버려 두거나 아래를 참고해서 틀렸다면 수정하기
- 포트가 `8080:8080` 이렇게 되어 있을 텐데, 이런 의미다. `{컨테이너가 실행되는 호스트 머신의 포트}:{컨테이너 내부 포트}` → a:b 라면 a번 포트를 컨테이너의 b 포트로 연결하여 외부에서 a번 포트로 접근하면 컨테이너의 b번 포트로 연결됨(포트 포워딩)
- 로드 밸런서: 위에서 생성했던 로드 밸런서 선택
- 리스너: 8080-HTTP (대상 그룹에서 입력한 포트와 동일하게)
- 대상 그룹: 기존 대상 그룹 사용
- 대상 그룹 이름: 위에서 생성한 대상 그룹 선택
- 상태 확인 경로: 헬스 체크 API 있으면 작성
- 나머지는 기본값으로 놔두고 완료하기
- Private Link: 이대로 배포하면 ECR에서 이미지를 가져올 수 없다고 하는 통신/연결 에러가 발생할 것이다. 해결을 위해 다음 설정을 진행한다. 여기서는 3개의 VPC Endpoint(개당 0.01 USD / hour)와 S3 Gateway Endpoint(무료)를 생성한다.
- VPC 엔드포인트
- VPC > PrivateLink 및 Lattice > 엔드포인트
- 엔드 포인트 생성 클릭
- 유형: AWS 서비스
- 서비스 > 검색창: `ecr`
- 검색 시 `ecr.api`와 `ecr.dkr`이 나타남. 모두 필요하지만, 한 번에 여러 개 생성 불가능. 우선 둘 중 하나 선택하여 진행
- 네트워크 설정: ECS가 있는 VPC 선택
- 서브넷: ECS가 있는 서브넷
- 보안그룹: VPC 엔드포인트용 보안 그룹 생성
- EC2 > 보안 그룹 > 보안 그룹 생성 - 인바운드 규칙만 추가
- 유형: HTTPS
- 소스 유형: 사용자 지정
- 소스: ECS가 속한 VPC의 IP 범위 (IPv4 CIDR)
- 정책: 전체 액세스
- 완료 (다음 셋 중 하나라도 안 하면 배포 실패)
- 동일한 과정으로 총 3번 반복: `api`, `dkr`, `logs`
- VPC Gateway
- VPC 엔드포인트의 3번까지 동일
- 서비스 > 검색창: `s3`
- 유형이 `Gateway`인 항목으로 선택
- 네트워크 설정: ECS가 있는 VPC 선택
- 라우팅 테이블: ECS가 있는 서브넷과 연결된 라우팅 테이블 선택
- 정책: 전체 액세스
- 완료
- VPC 엔드포인트
- 드디어 모든 설정 끝!!! ECS 배포 상태를 확인해 보기
- ECS > 클러스터 > 생성한 클러스터 클릭 > 서비스 탭 > 생성한 서비스 선택 > 배포 탭 클릭
- 배포가 정해진 횟수만큼 실패하다 보면, 자동으로 배포가 실행되지 않는다. 이때는 서비스 업데이트를 클릭.
- 배포 구성 > 새 배포 강제 적용: 활성화
- 나머지는 손대지 말고 업데이트 완료하기
- 이제 배포가 진행된다.
- 배포가 성공했다면, ALB의 DNS를 통해 접근할 수 있다. (HTTPS 미적용 상태임을 잊지 말기~)
- 선택된 서비스에서 구성 및 네트워킹 > DNS 이름이 해당 정보이다.
CoudWatch
별도로 설정을 안 했으면 기본 옵션으로 되어있다. 기본적으로 CloudWatch가 ECS에서 수집하는 지표는 ECS 클러스터 내 전체 자원의 평균 CPU 사용률, 평균 메모리 사용률 등 간단한 지표만 제공한다. 클러스터 수준의 지표만 수집하므로 세부 수준의 지표는 모니터링할 수 없다.
Container Insight를 사용하면 클러스터 내에서 더 세부적인 지표를 수집할 수 있다. 두 가지가 있다.
- 일반 컨테이너 인사이트: ECS 클러스터 및 ECS 서비스 수준에 대해 지표를 수집
- 일반 CloudWatch 지표 수집 비용과 동일. 수집한 지표 당 0.30 USD /month
- 향상된 관찰 기능을 갖춘 컨테이너 인사이트: ECS 클러스터, ECS 서비스, ECS 태스크 정의, ECS 태스크, 실행 중인 컨테이너 수준에서 더 많은 지표를 수집
- 수집한 지표 당 0.07 USD / month
후자가 더 많은 지표를 수집하여 자세한 정보를 알 수 있긴 하지만, 지표 수가 많을수록 비용이 많이 부과되므로 잘 생각해 보고 선택해야 한다. 또한 서비스나 태스크는 트래픽 상황에 따라 얼마든지 증가할 수 있는데, 지표도 그만큼 많이 수집되므로 비용이 생각보다 많이 부과될 수도 있다. 주의하자!
📌비용 관련 공식 정보: https://aws.amazon.com/ko/cloudwatch/pricing/
🔖
- https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-best-practices.html
- https://catalog.us-east-1.prod.workshops.aws/workshops/8c9036a7-7564-434c-b558-3588754e21f5/ko-KR/01-intro
- https://docs.aws.amazon.com/ko_kr/AmazonECR/latest/userguide/vpc-endpoints.html
- https://blog.kyobodts.co.kr/2023/08/18/hands-on-alb-amazon-ecs-on-fargate-%EB%A9%80%ED%8B%B0-%ED%83%80%EA%B2%9F%EA%B7%B8%EB%A3%B9-%EC%97%B0%EA%B2%B0%EA%B9%8C%EC%A7%80/
- https://goodahn.tistory.com/220
- https://sharplee7.tistory.com/125
'Architecture & Tool > AWS' 카테고리의 다른 글
CI/CD에 블루-그린 무중단 배포 적용하기: AWS ELB, AWS Auto Scaling Groups(ASG) (1) | 2025.08.09 |
---|---|
CI/CD 구축하기: GitHub Actions (OIDC) + Amazon S3 + Amazon CodeDeploy (3) | 2025.07.28 |
[AWS RDS] MySQL 파라미터 그룹 생성과 설정 - timezone, encoding (1) | 2025.01.31 |
[AWS & Docker] Docker 컨테이너 로그를 AWS CloudWatch로 보내기 (1) | 2025.01.04 |
잊기 전에 남겨두는 Amazon API Gateway 사용 이유 (0) | 2024.11.30 |
Comments