개발하는 자몽

[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 구성으로 해결해야 함

Private Link

  • VPC 엔드포인트, Gateway Endpoints(S3 또는 DynamoDB)를 사용해서 VPC 밖에 있는 두 서비스 사이에서 인터넷이 아닌 사설(private) 통신이 가능하도록 하는 서비스
  • 둘 중에 무엇을 선택할지는 비용을 따지는 편. 발생하는 비용은 각자 서비스의 데이터 처리량 등을 고려하여 계산.

 

 

Fargate로 SpringBoot 애플리케이션 배포하기

  1. Dockerfile 작성하기
  2. 도커 이미지 빌드 및 도커 허브에 push (이미지 이름 기억해 두기)
  3. ECR에서 Private Repository 생성
  4. 생성한 레포지토리를 선택하고 푸시 명령 보기 클릭, 가이드 보면서 순차적으로 진행
    • 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
    • 태깅할 때 태그는 앞으로 생성될 이미지 태그와 겹치지 않게 고유한 태그로 생성할 것
  5. 클러스터 생성: 클러스터는 서비스나 태스크의 논리적인 그룹이다. 
    1. ECS > 클러스터 > 클러스터 생성
    2. 인프라: AWS Fargate
    3. 클러스터 이름 작성이랑 인프라 선택만 하고 완료하기 
  6. 작업(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`을 잘 확인하고, 나머지는 위와 같이 설정한다.
      • 나머지는 기본 상태로 두고 작업 정의를 완료한다. 
  7. ECS 작업 IAM 역할 수정: 앞 단계에서 자동 생성된 ECS 작업의 IAM 역할인 `ecsInstanceRole`에 `CloudWatchLogsFullAccess`를 추가
    1. IAM > 역할 > ecs 검색 > `ecsInstanceRole` 선택
    2. 권한 탭 > 우측 권한 추가 메뉴 > 정책 연결 클릭
    3. 검색창에서 `CloudWatchFullAcess` 검색 > ` CloudWatchFullAcessV2` 선택 > 권한 추가 클릭
    4. 추가된 정책 확인
  8. ALB 구성 및 생성: private subnet에 위치한 ECS와 연결하여 외부 트래픽 진입점이 될 ALB를 생성한다.
    • 대상 그룹 생성
      1. EC2 > 대상 그룹 > 대상 그룹 생성
      2. 대상 유형: IP address
      3. 타겟 그룹 이름: 자유롭게 설정(보통 tg를 이름에 넣어서 대상 그룹임을 명시하는 편)
      4. 프로토콜 : 포트: HTTP : 8080(ALB가 요청을 보내줄 포트, 배포할 컨테이너(ECS)의 실행 포트로 입력. 모르겠다면 애플리케이션의 실행포트로 입력)
      5. VPC: 로드 밸런서를 호스팅 할 VPC 선택(ECS가 있는 VPC로)
      6. 상태 검사: 애플리케이션에 헬스 체크 API가 있다면 여기에 입력
      7. 나머지는 기본값으로 놔두고 다음 클릭
      8. 대상 등록: 아무것도 건들지 않고, 대상도 등록하지 않고 생성 완료하기. 나중에 ECS가 생성될 때 생성된 태스크가 자동으로 등록됨.
    • ALB 생성
      1. EC2 > 로드 밸런서 > 로드 밸런서 생성
      2. ALB 생성
      3. 로드 밸런서 이름: 자유롭게 설정(tg처럼 이름에 alb를 추가해서 명시하는 편)
      4. 체계(schema): 인터넷 경계(internet-facing)
      5. 네트워크 매핑: 대상 그룹과 동일한 VPC
        • 선택 후, 가용 영역 및 서브넷: 2개 이상 선택
      6. 보안 그룹: 이 ALB를 위해 생성해 둔 것이 없다면 새롭게 생성. 보안 그룹은 아래 조건을 만족하면 됨.
        • 새로 생성 시 아웃바운드는 건들지 않고, 외부 트래픽을 받을 수 있도록 인바운드만 설정
          • 유형: HTTP
          • 포트: 80
          • 소스: 0.0.0.0/0
      7. 리스너 및 라우팅: 외부 트래픽을 어떤 프로토콜과 포트로 받을지 결정하여 이 통로만 열어두고(리스너) , 받은 요청을 어디로 보낼지(라우팅) 설정
        • 프로토콜: HTTP
        • 포트: 80
        • 대상 그룹: 방금 생성한 대상 그룹 선택. 여기로 요청이 라우팅 된다. 
        • 요약 정보를 확인하고, 모두 맞다면 완료하기
  9. ECS 서비스 생성: Amazon ECS를 사용하여 Amazon ECS 클러스터에서 지정된 작업 정의 인스턴스를 동시에 실행하고 관리할 수 있다. 이를 서비스라고 한다.
    1. ECS > 생성한 클러스터 선택 > 서비스 탭 > 생성 버튼 클릭
    2. 서비스 세부 정보 설정
    3. 환경 > 컴퓨팅 구성
      • 컴퓨팅 옵션: 시작 유형
      • 시작 유형: FARGATE
      • 플랫폼 버전: LATEST
    4. 배포 구성
      • 스케줄링 전략: 복제본
      • 원하는 태스크: 서비스(여기서는 개발하는 프로덕트를 의미) 상황에 맞게 (여기서는 1개만 함)
        • Task: 특정 애플리케이션 기능을 수행하는 하나 이상의 컨테이너
        • Service: 동일한 다수의 Task 그룹
      • 나머지는 기본값으로 두기
    5. 네트워킹 설정
      1. VPC: VPC는 이미 생성된 것을 사용하거나 다른 서비스/프로젝트와 구분 지어 사용하고 싶다면 새롭게 생성. 잘 모르겠다면 default VPC 사용도 상관 X.
      2. 서브넷: 프라이빗 서브넷(private subnet)으로 선택.
        • 퍼블릭 서브넷(public subnet)도 가능함. 이 경우 다음을 참고.
          • ALB & VPC 엔드포인트나 NAT 없이도 외부 트래픽을 받을 수 있음
          • 퍼블릭 IP 옵션을 활성화 → 하나의 퍼블릭 IP에 대해서 시간당 0.005 USD의 요금이 부과됨
          • ALB와 VPC 엔드포인트 설정이 별도로 필요 없음
          • 퍼블릭 서브넷에 두면 보안 및 확장성 측면에서 좋지 않음
      3. 보안 그룹: 위에서 생성한 ALB를 고려해서 ECS를 위해 미리 만들어둔 보안 그룹이 없다면, 새로 생성하기
        1. 보안 그룹 이름: 여기에서도 sg를 이름에 추가해서 보안 그룹임을 명시하는 편
        2. 설명: 보통 어떤 목적의 보안 그룹인지 작성하는 편
        3. 인바운드 규칙
          1. 유형: 사용자 지정
          2. 포트 범위: 8080 (대상 그룹에서 입력한 포트와 동일하게)
          3. 소스: ALB를 위해 만들었던 보안그룹을 선택 (ALB를 통해서만 외부 트래픽이 들어올 수 있게 됨)
    6. 로드 밸런싱
      1. 로드 밸런싱 사용: 활성화
      2. VPC: 로드 밸런싱이 위치한 VPC로 선택
      3. 로드 밸런서 유형: ALB
      4. Application Load Balancer: 기존 로드 밸런서 사용
      5. 컨테이너: 기본적으로 잘 선택되어 있을 테니, 가만히 내버려 두거나 아래를 참고해서 틀렸다면 수정하기
        • 포트가 `8080:8080` 이렇게 되어 있을 텐데, 이런 의미다. `{컨테이너가 실행되는 호스트 머신의 포트}:{컨테이너 내부 포트}` → a:b 라면 a번 포트를 컨테이너의 b 포트로 연결하여 외부에서 a번 포트로 접근하면 컨테이너의 b번 포트로 연결됨(포트 포워딩)
      6. 로드 밸런서: 위에서 생성했던 로드 밸런서 선택
      7. 리스너: 8080-HTTP (대상 그룹에서 입력한 포트와 동일하게)
      8. 대상 그룹: 기존 대상 그룹 사용
      9. 대상 그룹 이름: 위에서 생성한 대상 그룹 선택
      10. 상태 확인 경로: 헬스 체크 API 있으면 작성
    7. 나머지는 기본값으로 놔두고 완료하기
  10. Private Link: 이대로 배포하면 ECR에서 이미지를 가져올 수 없다고 하는 통신/연결 에러가 발생할 것이다. 해결을 위해 다음 설정을 진행한다. 여기서는 3개의 VPC Endpoint(개당 0.01 USD / hour)와 S3 Gateway Endpoint(무료)를 생성한다.
    • VPC 엔드포인트
      1. VPC > PrivateLink 및 Lattice > 엔드포인트
      2. 엔드 포인트 생성 클릭
      3. 유형: AWS 서비스
      4. 서비스 > 검색창: `ecr`
        • 검색 시 `ecr.api`와 `ecr.dkr`이 나타남. 모두 필요하지만, 한 번에 여러 개 생성 불가능. 우선 둘 중 하나 선택하여 진행
      5. 네트워크 설정: ECS가 있는 VPC 선택
      6. 서브넷: ECS가 있는 서브넷
      7. 보안그룹: VPC 엔드포인트용 보안 그룹 생성 
        1. EC2 > 보안 그룹 > 보안 그룹 생성 - 인바운드 규칙만 추가
        2. 유형: HTTPS
        3. 소스 유형: 사용자 지정
        4. 소스: ECS가 속한 VPC의 IP 범위 (IPv4 CIDR)
      8. 정책: 전체 액세스
      9. 완료 (다음 셋 중 하나라도 안 하면 배포 실패)
        • 동일한 과정으로 총 3번 반복: `api`, `dkr`, `logs`
    • VPC Gateway
      1. VPC 엔드포인트의 3번까지 동일
      2. 서비스 > 검색창: `s3`
        • 유형이 `Gateway`인 항목으로 선택
      3. 네트워크 설정: ECS가 있는 VPC 선택
      4. 라우팅 테이블: ECS가 있는 서브넷과 연결된 라우팅 테이블 선택
      5. 정책: 전체 액세스
      6. 완료
  11. 드디어 모든 설정 끝!!! 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/

 

 

 

 

 

 

🔖

Comments