배운 내용
- EC2
- 로드 밸런서
- 오토 스케일링 그룹(ASG)
- VPC
- 일라스틱 빈스톡
본문
개념
EC2(Elastic Compute Cloud)는 서버 컴퓨터다. 로컬 환경에서 애플리케이션을 실행한 것 처럼 EC2에서 애플리케이션을 실행할 수 있다. EC2에서 애플리케이션을 실행하는 경우 EC2의 IP나 EC2가 제공하는 public domain으로 앱에 접근할 수 있다.
로드 밸런서는 EC2 인스턴스의 스케일을 키울 수 있도록 트레픽을 여러 인스턴스로 분배한다. VIP(Virtual IP)라는 공유 IP로 GET 요청이 오면 로드 밸런서에 연결된 인스턴스들에 트래픽을 균형있게 분배한다.
오토 스케일링 그룹(ASG)는 트래픽의 변동에 따라 자동으로 로드 밸런서에 연결된 인스턴스를 Scale in(서버 증설) 또는 Scale out(서버 수축) 해준다. 우리는 ASG에 최소(min), 최대(max), 적정(desired) 인스턴스 수를 정할 수 있다.
VPC(Virtual Private Cloud)는 AWS 계정 전용 가상 네트워크다. 즉, 우리의 EC2는 특별한 네트워크 설정 없이는 다른 계정 or 인터넷에서 접근할 수 없는 독립된 가상의 네트워크(Virtual Network)에 존재한다. VPC 안에는 서브넷(subnet, 여러 개로 쪼개진 네트워크)이 여러 개 존재한다. VPC의 한 서브넷 안에 EC2 서버를 생성하고, 서브넷 설정에 따라 EC2 IP 주소가 결정된다.
일라스틱 빈스톡은 EC2, 로드 밸런서, DB, RDS, ASG 등 애플리케이션을 만드는 데 필요한 인프라(리소스)를 대신 구축해준다. 일라스틱 빈스톡은 내부적으로 AWS 클라우드포메이션을 이용하는데, 이 서비스는 리소스-리소스 간의 관계를 적은 JSON이나 YML 파일을 인풋으로 받고, 이 설정 파일에 묘사된 인프라 코드를 통해 인프라를 구축한다. 이렇게 파일에 코드로 인프라를 묘사하고 이를 서비스가 반영해 인프라를 구축하는 것을 IaC(Infrastructure as Code)라 한다.
AWS CLI & EB CLI 설치
AWS Console에 로그한 한 후 AWS CLI를 설치한다. AWS CLI가 root(어드민) 계정으로 접근하는 것이 아닌 다른 권한, 역할 등을 가진 사용자로 접근하도록 AWS는 IAM(Identity and Access Management) 툴을 제공한다. 이 때 사람에게는 Id, pw를 사람이 아닌 프로그램에게는 액세스키, 비밀 액세스키를 제공한다.
AWS CLI 프로그램에서 사용할 액세스키와 비밀 액세스키를 발급받겠다.
정책(Policy)은 권한(Permission)을 나열해 놓은 문서다. 우리가 선택한 AdministratorAccess는 모든 AWS 리소스(ec2, rds, emr 등)에 대해 모든 권한을 준다는 뜻이다.
태그는 작성하지 않고 사용자 만들기를 완료한다. 액세스 키, 비밀 액세스 키의 경우 메모하지 않으면 다시 확인할 수 없다. 이 경우 새로 사용자를 추가해야 한다.
aws cli를 다운로드 해준다.
$ pip3 install awscli --upgrade --user
이제 다시 터미널로 돌아가 아래 명령어로 aws cli를 설정해준다.
$ aws configure
codespace를 사용할 경우 AWS Toolkit을 사용해주고, AWS Credentials를 만들어준다.
AWS CLI는 AWS의 모든 서비스를 위한 CLI다. 따라서 AWS CLI를 사용하면 EC2, 로드 밸런서, ASG, 라우트 53, 다이나모 디비 등을 사용할 수 있다. 반면, EB CLI는 일라스틱 빈스톡을 위한 CLI로 이 CLI로는 일라스틱 빈스톡 환경을 구축하고 설정할 수 있다.
[pip을 이용한 EB CLI 설치]
$ pip3 install awsebcli --upgrade --user
[EB CLI 설치 확인]
$ eb --version
// 출력
EB CLI 3.20.3 (Python 3.8.1)
정리
배포를 위한 사전 작업으로 AWS 툴을 설치했고, AWS CLI를 pip을 이용해 설치했다.
AWS의 일라스틱 빈스톡을 이용한 백엔드 배포
일라스틱 빈스톡을 이용하면 일라스틱 빈스톡이 애플리케이션 로드 밸런서, 오토 스케일링 그룹, RDS, EC2를 구축해주고 연결해준다. 우리 백엔드 애플리케이션은 MySQL(RDS)를 DB로 두고 서버는 로드 밸런서에 오토 스케일링 그룹을 연결하는 형태다. 해주어야할 작업은 아래와 같다.
- DB를 설정한다.
- 오토 스케일링 그룹을 생성하고 오토 스케일링 그룹 내에 실행되는 EC 인스턴스들이 애플리케이션을 실행할 수 있도록 스크립트를 작성한다.
- 로드 밸런서에 오토 스케일링 그룹을 타깃 그룹으로 지정한다.
일라스틱 빈스톡에서 애플리케이션은 환경, 환경의 구성, 버전 등 여러 컴포넌트의 집합이다. 여기서 환경은 AWS의 리소스를 뜻한다. 환경의 구성은 이 환경에 적용될 매개변수를 뜻한다.
eb init <app 이름>을 이용해 로컬 환경에 일라스틱 빈스톡 애플리케이션을 생성한다. 이 커맨드는 아직 실제로 AWS에 아무 작업도 하지 않는다.
$ eb init TodoApplcation-backend
- Select a default region : 이후 생성되는 리소스가 여기서 선택한 region에 생성된다. (10)
- Select a platform & Select a platform branch : 이 앱이 사용할 플랫폼(서버, 미들웨어(JVM), 운영체제 등) (6 & 3)
- set up SSH : EB를 통해 생성한 EC2에 접근할 때 SSH를 설정할 것인가?, 우리는 No
설정을 완료하면 .elasticbeanstalk 디렉터리가 생성된다. 이 디렉터리의 config.yml 파일에 우리가 설정한 항목들이 나열돼 있다.
백엔드 애플리케이션 설정
백엔드 앱을 배포하기 전 애플리케이션 프로퍼티 파일을 개발용/배포용으로 분리해야한다. /src/main/resources에 application-prod.yaml, application-dev.yaml 파일을 생성한다.
[application-prod.yaml]
server:
port: 5000
spring:
jpa:
database: MYSQL
show-sql: true
database-platform: org.hibernate.dialect.MySQL8Dialect
hibernate:
ddl-auto: update
datasource:
url: jdbc:mysql://${rds.hostname}:${rds.port}/${rds.db.name}
username: ${rds.username}
password: ${rds.password}
[application-dev.yaml]
//공백
개발용 프로퍼티는 공백으로 남겨둔다. 이렇게 남겨두면 dev 사용 시 h2 DB를, prod 사용 시 mysql을 사용할 수 있다.
- server 설정
- EB는 기본적으로 애플리케이션이 5000포트를 사용한다.
- jpa 설정
- show-sql : true → jpa가 실행한 sql 쿼리를 로그에 보여줄지 여부
- database-platform:org.hiber..MySQL8Dialect → MySQL8Dialect는 java의 data type과 DB의 data type을 매핑해주는 라이브러리이다.
- ex (String - Varchar로 매핑, @Id, @GeneratedValue 등의 어노테이션을 DB 키워드로 전환)
- hinernate: ddl-auto: update → ddl(Data Definition Language)은 Create, Alter, Drop 같은 쿼리를 의미한다. ddl-auto는 애플리케이션 시작 시 DB Table을 어떻게 하겠느냐?
- create: 모든 Table을 지우고 새로 만들기
- update: 없는 Table은 새로 만들고, 수정된 Table은 업데이트
- validate: 아무것도 하지 않고 현재 DB Table의 스키마가 애플리케이션에 정의된 Model가 일치하는지 확인
- datasource 설정
- url: DB의 url이다. 보통 jdbc:<db_type>://<host>:<prot>/<db_name> 형태로 되어 있다. DB는 EB가 만들어주므로 EB가 애플리케이션을 실행하면서 이 값을 지정해줄 수 있다. 이를 위해 실제 값 대신 ${rds.hostname} 등으로 대체한다.
- username: DB 사용자 이름
- password: DB 패스워드
target jar 설정
프로젝트 루트(demo)에서 아래 명령어를 수행한다.
$ gradlew build
빌드가 완료된 프로젝트는 build/libs 아래에 생성되는데, 생성된 demo-0.0.1.SNAPSHOT.jar을 .elasticbeanstalk/config.yml에 deploy:artifact 부분을 추가해 준다. 일라스틱 빈스톡에게 우리 애플리케이션을 자동으로 S3에 업로드하고 일라스틱 빈스톡 환경에 설정해달라고 애플리케이션의 경로를 알려줘야 한다.
[config.yml]
branch-defaults:
default:
environment: PROD-TODO-BACKEND
group_suffix: null
deploy:
artifact: build/libs/demo-0.0.1-SNAPSHOT.jar
global:
application_name: TodoApplcation-backend
branch: null
default_ec2_keyname: null
default_platform: Java 8 running on 64bit Amazon Linux
default_region: ap-northeast-2
include_git_submodules: true
instance_profile: null
platform_name: null
platform_version: null
profile: null
repository: null
sc: null
workspace_type: Application
eb create를 이용해 AWS에 환경 생성
$ eb create --database --elb-type application --instance-type t2.micro
- eb create: AWS에 일라스틱 빈스톡 환경을 생성하는 커맨드
- --database: 생성하는 환경에 RDS DB를 자동으로 추가해주는 매개변수
- --elb-type <ELB 타입>: 일라스틱 로드 밸런서 타입 매개변수 (로드밸런서 & ASG 이용)
- --instance-type <인스턴스 타입> 애플리케이션이 동작할 인스턴스 타입 (t2.micro는 프리티어)
build.gradle에 아래 코드를 추가한다. severe에서 application profile을 적용해야하기 때문이다.
[build.gradle]
bootRun {
String activeProfile = System.properties['spring.profiles.active']
systemProperty "spring.profiles.active", activeProfile
}
애플리케이션 배포시 eb setenv를 통해, 환경이 사용할 애플리케이션 yaml 파일을 지정해 준다. eb deploy는 build.gradle 파일을 업데이트한 것을 반영해주기 위해서 입력한다.
$ eb setenv SPRING_PROFILES_ACTIVE=prod
$ eb deploy
환경 구성
현재 환경 구성은 일라스틱 빈스톡에서 TodoApllication → 구성에서 확인할 수 있다.
환경 내부에 나열된 것들은 일라스틱 빈스톡이 우리를 대신에 AWS에 리소스를 생성해준 것이다. 우리는 각 리소스를 개별적으로도 확인할 수 있다.
RDS (Relational Database Service)
$ aws rds describe-db-instances --region ap-northeast-2
위 커맨드로 EB가 생성한 RDS 인스턴스를 확인할 수 있다.
// 결과
{
"DBInstances": [
{
"DBInstanceIdentifier": "aa1v5cbdfe20iux",
"DBInstanceClass": "db.t2.micro",
"Engine": "mysql",
"DBInstanceStatus": "available",
"MasterUsername": "ebroot",
"DBName": "ebdb",
... 다른 필드들
"TagList": [
...
{
"Key": "elasticbeanstalk:environment-name", ★
"Value": "PROD-TODO-BACKEND" ★
},
{
"Key": "Name",
"Value": "PROD-TODO-BACKEND"
}
],
...
}
]
}
ASG
오토 스케일링 그룹도 AWS CLI를 통해 확인할 수 있다.
$ aws rds describe-db-instances --region ap-northeast-2
{
"AutoScalingGroups": [
{
"AutoScalingGroupName": "awseb-e-5uihpm62p9-stack-AWSEBAutoScalingGroup-1K9UXN68X6GX",
...
"AvailabilityZones": [ // ASG의 인스턴스는 아래 AZ 중 하나에서 생성된다.
"ap-northeast-2a"
],
"LoadBalancerNames": [],
"TargetGroupARNs": [ // 로드 밸런서에 연결될 타깃 그룹
"arn:aws:elasticloadbalancing:ap-northeast-2:196521808741:targetgroup/awseb-A
WSEB-CJU4EY4H7J7M/ecc014fb762cd1e4"
],
...
"Instances": [
{
"InstanceId": "i-04fd724dc5c2f5a8d", // ASG 속 인스턴스
"InstanceType": "t2.micro",
"AvailabilityZone": "ap-northeast-2a",
"LifecycleState": "InService", // 인스턴스의 라이프사이클 상태
"HealthStatus": "Healthy", // 인스턴스의 상태
"LaunchConfigurationName": "awseb-e-5uihpm62p9-stack-AWSEBAutoScalingLaunchC
onfiguration-oWtpAVLruFii",
"ProtectedFromScaleIn": false
}
],
...
"Tags": [
...
{
"ResourceId": "awseb-e-87h9feuirc-stack-AWSEBAutoScalingGroup-168MRC38TRT0Z",
"ResourceType": "auto-scaling-group",
"Key": "elasticbeanstalk:environment-name",
"Value": "PROD-TODO-BACKEND", // 일라스틱 빈스톡 환경 이름
"PropagateAtLaunch": true
}
],
...
}
]
}
애플리케이션 로드 밸런서
$ aws elbv2 describe-load-balancers --region ap-northeast-2
로드벨런서도 확인할 수 있다.
{
"LoadBalancers": [
{
"LoadBalancerArn": "arn:aws:elasticloadbalancing:ap-northeast-2:196521808741:
loadbalancer/app/awseb-AWSEB-KILHOCHKWING/1fabd34216548ac8",
"DNSName": "awseb-AWSEB-KILHOCHKWING-1728932366.ap-northeast-2.elb.amazonaws.com",
...
"LoadBalancerName": "awseb-AWSEB-KILHOCHKWING",
...
}
]
}
로드 밸런서와 ASG를 연결하는 타깃 그룹을 확인할 수도 있다.
$ aws elbv2 describe-target-groups --region ap-northeast-2
{
"TargetGroups": [
{
"TargetGroupArn": "arn:aws:elasticloadbalancing:ap-northeast-2:196521808741
:targetgroup/awseb-AWSEB-1PO69O80TGLBB/2b797a644184b1d3",
// ASG의 TargetGroupArn과 같음
"TargetGroupName": "awseb-AWSEB-1PO69O80TGLBB",
"Protocol": "HTTP",
"Port": 80,
...
"LoadBalancerArns": [
"arn:aws:elasticloadbalancing:ap-northeast-2:196521808741:loadbalancer/app
/awseb-AWSEB-1JJDOMDZRCFYK/334e735492e39a48"
],
"TargetType": "instance",
"ProtocolVersion": "HTTP1",
"IpAddressType": "ipv4"
}
]
}
CloudWatch와 EC2에 생성된 리소스도 확인할 수 있다. 각 필드에 대한 자세한 설명은 AWS 문서에 자세히 나와 있다.
$ aws elbv2 describe-target-groups --region ap-northeast-2
$ aws ec2 describe-instances --region ap-northeast-2
aws cli를 통해 리소스를 알아본 이유는 일라스틱 빈스톡이 AWS 내에서 어떻게 서로 다른 리소스를 생성하고 관리하는지 알아보기 위해서였다. 일라스틱 빈스톡은 태그에 일라스틱 빈스톡 환경을 붙여 구별하고 관리한다는 사실을 알 수 있다.?
클라우드포메이션
AWS 콘솔 - Cloud Formation에서 Template - Designer에서 보기를 클릭하면 일라스틱 빈스톡이 생성한 리소스를 개괄적으로 확인할 수 있다.
일라스틱 빈스톡이 Cloud Formation을 이용해 로드 밸런서, ASG, RDS, CloudWatch 알람뿐 아니라 각종 시큐리티 그룹과 정책을 알아서 생성해주고 그 사이의 관계를 정의해줬다는 사실을 알 수 있다.
엔드포인트 테스팅
curl로 계정 생성 API를 테스팅 했는데, 잘 동작함을 알 수 있다.
curl -d '{"email":"hello@world.com","username":"user1","password":"12345"}'\
-H 'Content-Type:application/json'\
-X POST http://prod-todo-backend.ap-northeast-2.elasticbeanstalk.com/auth/signup
// 결과
{"token":null,"email":"hello@world.com","username":"user1","password":null,
"id":"2c9f8ec2801157450180118867dd0000"}
정리
EB CLI를 이용해 백엔드 환경을 생성하고 생성된 리소스를 확인하는 작업을 했다. 이를 통해 EB CLI를 사용해 환경을 생성하고, 애플리케이션을 배포하고, AWS CLI를 통해 생성한 리소스를 확인하는 방법을 배웠다.
AWS의 일라스틱 빈스톡을 이용한 프론트엔드 배포
eb init을 이용해 애플리케이션 생성
리엑트 애플리케이션 프로젝트 폴더(todo-react-app)로 이동한 후 해당 폴더를 일라스틱 빈스톡 환경으로 초기화한다.
eb init TodoApplication-frontend
- Select a default region : 이후 생성되는 리소스가 여기서 선택한 region에 생성된다. (10)
- Is Node.js? & Select a platform branch : Y & 2
- set up SSH : EB를 통해 생성한 EC2에 접근할 때 SSH를 설정할 것인가?, 우리는 No
소스 코드를 빌드한다.
npm run build
eb create를 이용해 환경을 생성한다.
eb create --elb-type application --instance-type t2.micro
크로스 오리진 문제
URL이 localhost → elasticbeanstalk.com 으로 바뀌었기 때문에 백엔드 코드의 WebMvcConfig의 allowedOrigins에 프론트엔드 주소를 추가해야 한다. 이후 도메인을 사 프론트엔드 - 백엔드에 도메인을 연결해줄 때도 이 작업을 해야한다.
// class WebMvcConfig 중
@Override
public void addCorsMappings(CorsRegistry registry){
// 모든 경로에 대해
registry.addMapping("/**")
// Origin이 다음과 같은 것들에 대해
.allowedOrigins("http://prod-todo-frontend2.ap-northeast-2.elasticbeanstalk.com/")
// GET, POST, PUT, PATCH, DELETE, OPTIONS 메서드를 허용한다.
.allowedMethods("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS")
.allowedHeaders("*")
.allowCredentials(true)
.maxAge(MAX_AGE_SECS);
}
코드를 수정한 후 컴파일한다.
./gradlew clean && ./gradlew build
그 다음 새 버전의 백엔드 애플리케이션을 배포한다.
eb deploy
정리
프론트엔드 애플리케이션을 배포하는 것도 백엔드와 비슷하게 'eb init'으로 환경을 초기화하고, 'eb create'를 이용해 환경을 생성한다. 그리도 'eb deploy'를 이용해 애플리케이션을 재배포할 수 있었다.
또다시 CORS 문제와 마주쳤는데, 이 문제는 addCorsMappings 메서드에 프론트엔드 주소를 추가해 줌으로써 해결했다.
Route 53 도메인 설정
- 호스팅 영역(Host Zone): DNS 영역(Zone) 파일이다. 즉, wonchanlee.click이 관리할 영역을 의미한다. DNS는 여러 개의 레코드를 한 곳에서 관리하기 위해 존재한다.
- 레코드: 이름과 IP를 연결해 놓은 파일 또는 엔트리다.
- SOA(Start of Authority) 레코드: 호스트 영역(wonchanlee.click)을 관리하는 관리자의 정보를 갖는다.
- NS(Name Server) 레코드: wonchanlee.click의 IP를 물어볼 서버들을 갖고 있다.
- A 레코드: app.wonchanlee.click을 다른 도메인(로드 밸런서의 도메인)이나 특정 IP로 연결하는 레코드다.
AWS Route 53에서 도메인 설정완료한 후, 백엔드에서 CORS 설정에 새로 등록한 도메인을 추가해주면 된다.
HTTPS 설정
AWS Certificate Manager에서 인증서를 요청하고 AWS EB 환경-로드밸런서-편집-리스너 추가를 통해 443포트에 SSL 인증서를 추가해주면 https 인증이 완료된다.
https://app.wonchanlee.click 으로 접속하면 제가 만든 app에 들어가실 수 있습니다.
궁금한 점
- example
알게된 점
- example
출처: React.js, 스프링 부트, AWS로 배우는 웹 개발 101
'React, 스프링, AWS로 배우는 웹개발 101' 카테고리의 다른 글
이 책을 마치며.. (0) | 2022.04.12 |
---|---|
인증 프론트엔드 통합 (0) | 2022.04.08 |
인증 백엔드 통합 (0) | 2022.03.28 |
프론트엔드 개발 (0) | 2022.03.16 |
백엔드 개발 (0) | 2022.02.27 |