AWS 솔루션 아키텍처, Beanstalk

Siyun·2025년 2월 20일

AWS

목록 보기
11/37

WhatIsTheTime.com

  • 시간을 알려주는 서비스다.
  • DB가 필요없고 각각의 인스턴스와 서버는 시간이 몇시인지 알고있다.
  • 다운타임을 수용할 수 있지만 이를 제거할 수 있도록 수직&수평적으로 확장할 필요가 있다.

이 앱에 대한 솔루션 아키텍트를 해보자!!!

PoC(Proof of Concept)란?
어떤 아이디어나 기술이 실제로 구현 가능하고 작동할 수 있는지 검증하는 과정 또는 시제품

📃첫번째 PoC:
Public t2.micro 인스턴스 하나에 탄력적 IP를 연결하여 사용자가 시간을 물어보면 인스턴스에서 답하기

사용자가 증가했다!
t2.micro인스턴스를 더 큰 것으로 교체(수직 확장) -> m5.large 인스턴스로 교체
교체하기 위해 인스턴스 중지하고 유형을 바꾸고 다시 인스턴스 시작하여 다운타임이 발생함.

사용자가 증가했다!
수평확장을 위해 m5.large EC2 인스턴스 2개를 추가한다. 총 3개의 EC2인스턴스들은 모두 각각의 탄력적IP에 연결되어 있다.
👉🏻 따라서 사용자들이 인스턴스와 통신하려면 세 개의 탄력적 IP의 정확한 값을 알고 있어야 한다.

IP가 너무 많아 탄력적 IP를 제거한다!
한 계정에서 리전마다 최대 5개의 탄력적 IP를 가질 수 있다.
관리하기 힘든 탄력적IP는 없애고 Route 53을 활용하겠다. 웹사이트의 URL은 api.whatisthetime.com이다.
TTL이 한 시간인 A레코드로 정하여 3개 EC2의 IP 리스트를 제공할 것이다.

상황에 따라 인스턴스 수를 조절하고 싶다!
현재 상태에서 스케일 인을 위해 EC2인스턴스 하나를 지우면 TTL이 한 시간이라 해당 EC2인스턴스가 캐시되어있는 클라이언트들은 한 시간 동안 사용을 못한다.

그래서 이제는 Public EC2 인스턴스들 대신 Private EC2 인스턴스들을 사용한다.
이들을 같은 AZ에서 수동으로 실행했다.
ELB 하나를 생성해서 프라이빗 EC2인스턴스들을 대상그룹으로 연결하고 EC2인스턴스들의 보안규칙을 수정해 ELB의 인바운드만을 허용하도록 한다.
이제 사용자들은 Route53에 URL을 쿼리해도 로드밸런서가 IP주소를 지속적으로 바꾸기 때문에 A레코드 대신 별칭 레코드로 Route53이 ELB를 가르키게 한다.

이제 ELB의 상태확인 때문에 다운타임도 없을 것이다.

수동으로 인스턴스 추가 제거는 좀 아닌 것 같다!
이제 ASG을 사용해 오토 스케일링 할 것이다. Private EC2 인스턴스들을 하나의 ASG와 연결한다.
ASG가 자동으로 요청에 따른 확장과 축소를 수행한다.

AZ가 다운되었다!
ELB에서 다중 AZ를 사용해야겠다. 사용중인 ELB 하나를 AZ 1~3에 적용한다.
사용중이던 ASG 하나도 다중AZ에 걸쳐있게 한다.
이제 높은 가용성을 확보하고 장애 발생에도 대비할 수 있다.

이제는 비용을 줄이고싶다!
두 개의 AZ에 각각 하나씩 총 2개의 EC2인스턴스는 1년 내내 실행 중일 것이다.
비용을 줄이기 위해 용량을 예약해보자. 인스턴스가 확장될 때 생기는 온디맨드 비용은 요청량에 따른 확장이라 감당할 수 있다.
비용절감은 스팟 인스턴스를 사용할 수도 있지만 이는 인스턴스를 종료시킬 수 있으니 위험하다.


좋은 아키텍처란?

비용, 성능, 신뢰성, 보안, 운영에서 탁월해야 한다!!


MyClothes.com

  • 상태 유지 웹 어플리케이션
  • 온라인으로 옷 구매 서비스. 장바구니 기능이 있음.
  • 동시에 수백 명의 사용자가 있어 확장이 가능해야 함.
  • 애플리케이션의 웹 티어를 최대한 무상태로 유지하고싶음(장바구니가 있지만 웹 애플리케이션을 최대한 쉽게 확장할 수 있어야 함).
  • 사용자 정보를 DB에 저장할 것임.

📃초기 PoC는 WhatIsTheTime.com의 최종 상태와 동일
Route53,세 개의 AZ, 다중AZ ELB/ASG

사용자가 ELB를 통해 EC2인스턴스1에서 장바구니를 생성했는데, 다음 요청은 EC2인스턴스2로 가면 장바구니가 사라짐.
고로 ELB에서 고정세션(ELB Stickiness)을 활성화해야함.
그러면 같은 EC2인스턴스로의 연결이 고정세션에서 설정한 기간동안 유지됨.
👉🏻 하지만 EC2인스턴스가 어떤 이유로든 종료되면 장바구니가 사라짐.

사용자 쿠키를 사용해 장바구니를 저장하자!
EC2인스턴스가 장바구니를 저장하는 대신 사용자 쪽에서 장바구니를 저장한다. 그러면 사용자가 직접 EC2인스턴스로 장바구니 내용을 보내주기 때문에 EC2에서는 장바구니를 저장할 필요가 없어진다.
이제 무상태를 달성했지만 HTTP 요청이 점점 더 무거워진다. 장바구니에 뭔가를 추가할수록 사용자는 점점 더 많은 데이터를 HTTP 요청으로 보내게 된다.
또한 쿠키가 공격자에 의해 변경됨으로써 사용자의 장바구니가 수정될 위험도 있다.

👉🏻 이런 아키텍처에서는 EC2인스턴스가 반드시 사용자 쿠키의 내용을 검증해야 한다.
또 전체 쿠키의 크기는 4KB 이하까지만 가능해 대량의 데이터 셋을 저장할 수 없다.

서버 세션 개념을 도입해보자!
전체 장바구니를 웹 쿠키로 보내는 것이 아닌 단순히 사용자의 세션ID만 보낸다.
백그라운드에는 ElastiCache 클러스터가 존재한다.

과정: 사용자가 세션 ID와 장바구니에 담을 물건을 전송 -> EC2는 세션ID-장바구니 물건을 key-value 형식으로 ElastiCache에 추가

사용자가 다른 EC2인스턴스로 세션ID와 함께 두 번째 요청을 보내면 EC2인스턴스는 세션ID로 ElastiCache에서 장바구니 내용을 불러올 수 있다.

ElastiCache는 매우 빨라 성능도 좋아진다.
공격자들은 ElastiCache의 내부를 수정할 수 없기 때문에 훨씬 안전해진다.
*ElastiCache 외에 DynamoDB로 세션 데이터를 저장할 수도 있다.

사용자 데이터를 저장하기 위한 DB연결을 해보자
RDS 하나를 생성해서 DB를 관리하자.
EC2인스턴스들은 사용자 데이터를 저장하거나 불러오기 위해 해당 RDS와 통신할 것이다.

사용자가 늘어난다!
사용자들이 대부분의 시간을 웹사이트를 둘러보며 읽기 요청을 수행한다는 것을 알게된다.

그렇다면 세가지 패턴을 생각해보자

  • 첫 번째 패턴: 그냥 읽기/쓰기를 모두 수행하는 RDS마스터를 사용해서 읽기 요청을 수행한다.
  • 두 번째 패턴: RDS 읽기 전용 복제본을 사용해 뭔가를 읽을 때는 읽기 전용 복제본을 사용한다.(최대 5개까지 복제본 생성 가능)
  • 세 번째 패턴: EC2인스턴스가 먼저 캐시에서 데이터를 찾아 반환하고 캐시에 없으면 RDS마스터로부터 읽어와 ElastiCache에 집어넣는다.
    👉🏻 캐시 유지 보수가 애플리케이션쪽에서 이뤄져야 하는데 이는 꽤 어려운 일이다.

DB의 장애에 대비하자!
RDS 또한 다중AZ 기능이 있으므로 설정해준다.
Redis를 사용한다면 ElastiCache도 다중AZ 기능을 가진다.

서비스간의 보안 그룹을 설정하자!
ELB는 어느 쪽에서나 HTTP HTTPS 트래픽을 열 수 있다.
EC2인스턴스 측면에서는 로드밸런서로부터 오는 트래픽만 허락한다.
ElastiCache, RDS 측면에서는 EC2 보안 그룹으로부터 오는 트래픽만 허락한다.

이 아키텍처는 프레젠테이션(클라이언트), 애플리케이션(웹), 데이터(데이터베이스) 3가지 계층으로 분리된 3티어 아키텍처(3-Tier Architecture) 구조이다.
비용은 좀 더 들겠지만 아키텍처 관련 결정을 할 때 도움이 되는 것들을 얻을 수 있다.


MyWordPress.com

  • 상태 유지 웹 애플리케이션
  • 웹사이트에 접근하면 업로드한 그림이 바르게 나타나길 원함
  • 어떤 드라이브에 그림을 저장하고 모든 인스턴스들이 그 데이터에 접근해야 함
  • 사용자 데이터와 블로그 내용 등 모든게 MySQL 데이터베이스에 저장되어야 함
  • 글로벌하게 확장할 수 있어야 함

📃초기 PoC는 앞서 구성한 3-Tier 아키텍처
백엔드에 RDS가 있는 계층, 다중 AZ

정말 크게 확장하고싶다면 이 계층을 Aurora MySQL로 교체한다. 다중 AZ, 읽기 전용 복제본, 글로벌 데이터베이스까지 적용할 수 있다. 고로 연산을 줄일 수 있다.

이미지 저장은 어떻게 할까
하나의 EC2 인스턴스에 하나의 EBS가 연결된 상태에서는 이미지는 EBS에 저장되고 불러올 때도 EBS에서 불러온다.
이것은 EC2 인스턴스 하나로만 서비스를 작동시킬 때는 아무 문제가 없다.
하지만 확장되기 시작하면 문제가 생긴다.

EFS, 즉 네트워크 파일 시스템을 사용한다. EFS는 각각의 AZ에 탄력적인 네트워크 인터페이스인 ENI를 생성한다. 이 ENI는 EFS 드라이브에 접근하는 모든 EC2에 사용할 수 있다. 이로써 하나의 스토리지가 모든 인스턴스에게 공유된다.


애플리케이션을 빠르게 인스턴스화하기

어떻게 EC2 인스턴스에 애플리케이션을 설치하고 배포하는 것을 빠르게 할까?

EC2 인스턴스에서는 Golden AMI를 사용할 수 있다.
애플리케이션과 OS 종속성 등 모든 것을 사전에 설치하고 그것으로부터 AMI를 생성하는 것이다.
이후로는 EC2인스턴스를 Golden AMI로부터 직접 실행하면 되어 가장 빠르게 실행할 수 있고 부트스트래핑보다 빠르다.

Elastic Beanstalk는 AMI를 구성하고 UserData를 추가하는 하이브리드 원칙을 적용한다.

데이터베이스와 스토리지는 DB 스냅샷과 EBS 스냅샷을 사용해 빠르게 복구할 수 있다.


Beanstalk

  • 하나의 인터페이스에서 EC2,ASG,ELB,RDS와 같이 모든 구성요소를 재사용하여 자동으로 배포해주는 관리형 서비스이다.
  • 용량 프로비저닝, 로드밸런서 구성, 자동 확장, 애플리케이션 안전성 모니터링과 인스턴스 구성 등을 처리한다.
  • Beanstalk는 무료이지만 Beanstalk가 사용하는 다른 AWS 자원들은 비용 지출.

Beanstalk의 구성요소(컴포넌트)

  • 애플리케이션 (환경, 버전, 구성 등)
  • 애플리케이션 버전 (개발자가 지정한 애플리케이션 코드의 버전1,버전2...)
  • 환경(특정 애플리케이션 버전을 실행하는 리소스의 모음. 한 번에 하나의 애플리케이션 버전만 사용 가능. 환경 내에서 어플리케이션 버전을 1->2로 업데이트 가능.)
    • 티어: 웹 서버 환경, 작업자 환경의 두가지 티어가 존재함.
    • 개발, 테스트, 프로덕션 등 여러 환경을 생성할 수 있다.
  • 생애주기
    어플리케이션 생성 -> 버전 업로드 -> 환경 실행 -> 환경 관리
    새로운 버전을 업로드해 환경에 다시 배포해서 애플리케이션 스택을 업데이트할 수 있다.
  • 다양한 언어 제공 :Go, Java SE, Java with Tomcat, .Net Core on Linux, .Net on Windows Server, Node.js, PHP, Python, Ruby, Packer Builder, 단일 Docker 컨테이너, 다중 Docker 컨테이너, 사전 구성된 Docker (거의 모든 것을 배포 가능)

웹 서버 티어와 작업자 티어

  • 웹 환경: 전통적인 아키텍처로 로드밸런서가 트래픽을 오토 스케일링 그룹으로 보내고 여기에 여러 EC2 인스턴스가 포함되어 있어 웹서버 역할을 한다. (=EC2가 웹 서버 티어)
  • 작업자 환경 : EC2인스턴스에 직접 액세스하는 클라이언트가 없고 메시지 대기열인 SQS 대기열을 사용한다. EC2인스턴스가 작업자 역할을 하고 SQS 대기열에서 메시지를 가져와 처리한다. 이 경우 작업자 환경은 SQS 메시지 수에 따라 확장된다.(=EC2가 작업자 티어)
  • 웹 환경과 작업자 환경을 함께 배치해 일부 메세지를 작업자 환경의 SQS대기열에 전송하도록 설정할 수 있다.

Beanstalk의 두 가지 배포모드

1) 개발 목적에 적합한 단일 인스턴스
탄력적 IP를 가진 EC2인스턴스가 하나 있다. (잠재적으로 RDS 등을 생성할 수 있지만 이는 모두 하나의 인스턴스와 탄력적 IP를 기반으로 한다.)

2) 고가용성 모드
: 로드밸런서, 오토스케일링 그룹 및 여러 AZ에서 관리되는 하나 이상의 EC2인스턴스가 생성된다. 로드를 분산시킬 수 있으며 이는 프로덕션 환경에 적합하다. 마스터, 스탠바이 인스턴스를 가진 Muli-az RDS 데이터베이스를 가질 수도 있다.

Beanstalk 실습

1. Elastic Beanstalk > Create application 선택

2. 환경 설정

  • 웹서버 , 작업자 환경 중에 고른다.
    👉🏻 웹 사이트를 실행하길 원하면 웹 서버환경 선택
    👉🏻 대기열에서 오는 작업을 처리하려 한다면 워커 환경 선택

  • 어플리케이션 이름을 입력한다.

  • 환경 정보를 설정한다. (환경 이름, 도메인 이름을 설정한다. 해당 도메인으로 웹 서버에 엑세스할 것이다.)

  • 플랫폼을 선택한다.(스프링부트면 JAVA, 도커이미지면 Docker 등등..)

  • 애플리케이션 코드는 샘플애플리케이션, 직접 코드 업로드 중에 선택한다.

  • 프리셋을 설정한다.
    1) 싱글인스턴스 (프리티어, 스팟인스턴스 사용 중 선택. 탄력적IP가 자동생성됨 주의)
    2) 고가용성 (로드밸런서 포함)
    3) 커스텀 설정

3. 서비스 엑세스 (IAM Role) 설정


Beanstalk이 AWS의 다른 서비스에 접근할 수 있도록 IAM 설정을 해준다.
Role 새로 생성을 선택하면 자동으로 Role이 만들어진다. 내용은 아래와 같다.

Beanstalk이 Trusted entity가 되고 아래 Action의 내용이 Beanstalk에게 허락된다.
그리고 EC2 instance profile에서 만들어질 EC2의 role도 IAM에서 새로 생성하여 적용해준다.

이때 EC2의 권한정책에서 beanstalk을 입력해 WebTier, WorkerTier, MulticontainerDocker를 추가해준다.

이후 내용은 단일 인스턴스를 생성할거라면 다 스킵하고 생성하면 된다.
그러면 생성된 Beanstalk을 통해 이벤트들을 확인할 수 있다.

4. CloudFormation에서 확인

Beanstalk이 생성되면 배후에서 CloudFormation에서 스택이 생성되고 거기에서 리소스들이 생성되어 같은 이벤트를 확인할 수 있다.
Template를 선택하면 애플리케이션을 생성한 탬플릿을 볼 수 있고,
View in Designer를 선택하면 현재 애플리케이션의 아키텍처를 시각적으로 확인할 수 있다.

Beanstalk이 생성하는 모든 리소스는 배후에서 CloudFormation이 생성한다!

빈스톡이 생성되면 생성할 때 선택했던 인스턴스, 탄력적 IP, 오토스케일링 그룹 등이 자동으로 생성된다. 그리고 생성한 Beanstalk을 선택하면 도메인 이름을 확인할 수 있다.
해당 도메인 이름을 클릭하면 Beanstalk 환경과 EC2의 웹서버에 접속할 수 있다.
Health에서는 EC2인스턴스들의 상태를 확인할 수 있고 Logs에서는 애플리케이션의 로그를 확인할 수 있다.
Monitoring에서 애플리케이션의 모든 메트릭을 확인할 수 있다.

5. 새 버전 업로드하기

생성한 Beanstalk에서 Upload and deploy를 누르면 어플리케이션의 새 버전으로 파일을 올릴 수 있는데 이것을 올리면 자동으로 배포된다.

6. Beanstalk 환경에 관한 모든 설정 확인 및 수정하기

Elastic Beanstalk 콘솔 > Configuration에서 환경에 관한 모든 설정을 보고 수정하고 적용할 수 있다.

7. 새 환경 만들기

Elastic Beanstalk 콘솔 > MyApplication에서 Create new enviroment를 선택해 새 환경을 만들 수도 있다.
예를 들어 나의 앱1(개발용)의 환경과 나의 앱2(프로덕션용)의 환경을 만들어 관리할 수 있다.

profile
공부 기록

0개의 댓글