-
1. Cors 설정하기
-
WebMvcConfigurer
-
2. Spring Boot 환경변수 분리하기
-
로컬, 개발, 운영환경 나누기
-
3. IAM 계정 등록 및 Elastic Beanstalk을 위한 권한 설정
-
IAM 계정 등록
-
Elastic Beanstalk에 사용할 권한 설정
-
4. RDS, Elastic Beanstalk 생성하기
-
RDS 생성
-
Elastic Beanstalk 생성
-
5. IAM 인증키를 받아서 GitHub에 등록하기
-
IAM 인증키 생성하기
-
GitHub Actions에 등록하기
-
6. GitHub Actions 스크립트 파일 작성
-
브랜치, Java, 빌드 설정
-
빌드된 jar 파일을 Beanstalk에 배포하기 위한 zip파일로 만들기
-
Beanstalk Deploy 플러그인을 통해 Elastic Beanstalk 배포 설정 스크립트 작성
-
완성된 deploy.yml
-
7. Beanstalk 애플리케이션 구성
-
.ebextensions
-
Procfile
-
.platform/nginx/nginx.conf
-
8. 애플리케이션 배포
-
어려웠던 부분, 시간을 들였던 부분
-
참고 레퍼런스
3회차 미션은 지금까지 만들었던 익명 게시판을 배포하는 것입니다!
배포 환경은 AWS Elastic Beanstalk 이용합니다.
우선 Elastic Beanstalk은 EC2, RDS, S3 환경을 동시에 제공해줍니다.
더 나아가 프로비저닝, 로드 밸런싱, Auto Scaling과 같은 기능을 Beanstalk가 제공해줍니다.
Elastic Beanstalk은 기본적으로 Nginx를 이용한 리버스 프록싱을 지원해줍니다!
이전시간까지는 단순히 CRDU API와 API DOCS를 만들었습니다.
이번 시간은 실제 배포를 위한 Spring Boot에서의 설정과 배포 시스템을 구성하여 무중단 배포를 할 수 있도록 진행해보겠습니다!
참고로 Elastic Beanstalk을 생성하려면 EC2 인스턴스를 생성하고 키페어를 발급받아야 합니다!
1. Cors 설정하기
React.js를 사용한다면 http://localhost:3000을 사용합니다.
Tomcat 서버는 기본적으로 http://localhost:8080을 사용하므로
Protocol, Host는 동일하지만 Port가 달라지므로 서로 다른 출처 Cross Origin으로 간주됩니다.
브라우저는 이들 중 하나라도 다르면 차단됩니다.
사실 이를 해결하는 방안이 Cross-Origin Resource Sharing으로 Cors라고 합니다. 또한 브라우저는 기본적으로 동일 출러(Same-Origin Policy)를 따르고 있으므로 react에서 톰캣으로 보낸 요청이 막히게 됩니다.
Cors를 적용하기 위해서는 Spring Boot에서의 설정을 많이 이용하는데 아무래도 인터페이스와 메소드 하나만 구현하면 간단하게 적용할 수 있기 때문인것 같습니다!
WebMvcConfigurer
Spring Boot는 WebMvcConfigurer 인터페이스를 제공해주는데 해당 인터페이스에서는 Spring MVC에 대한 설정을 커스텀하게 적용할 수 있습니다.
여기서 void addCorsMappings(CorsRegistry registry)
메소드를 오버라이딩하여 Cors 정책을 적용할 컨트롤러 매핑과 요청을 허용할 클라이언트의 주소 및 허용 HTTP Method등 다양한 설정을 할 수 있습니다.
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
private static final String ALLOWED_METHOD_NAMES = "GET,HEAD,POST,DELETE,TRACE,OPTIONS,PATCH,PUT";
@Override
public void addCorsMappings(final CorsRegistry registry) {
registry.addMapping("/**") (1)
.allowedOrigins("http://localhost:3000") (2)
.allowedMethods(ALLOWED_METHOD_NAMES.split(",")); (3)
}
}
- (1): Cors 정책을 모든 컨트롤러 매핑에 적용합니다.
- (2): React에서 사용되는 3000번 포트를 허용합니다. (별도의 도메인이 있다면 해당 도메인을 적용)
- (3):
ALLOWD_METHOD_NAMES
에 작성한 모든 HTTP Method를 허용합니다.
2. Spring Boot 환경변수 분리하기
배포를 한다면, 기존에 사용하던 로컬 개발 환경이 아닌 배포를 위한 새로운 환경을 구성해야 합니다.
Spring Boot는 application.yml 혹은 properties를 통해 쉽게 개발환경과 배포환경을 분리할 수 있는 기능을 제공합니다!
하나의 yml 파일을 사용할 수 도있지만, 3개의 yml파일을 구성해 각각, 로컬 환경, 개발 환경, 운영 환경으로 구성해보겠습니다.
로컬, 개발, 운영환경 나누기
기존 application.yml은 다음과 같습니다
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/jscode-spring-class?characterEncoding=UTF-8
username: hoseok
password: 1234
jpa:
hibernate:
ddl-auto: create
naming:
physical-strategy: org.hibernate.boot.model.naming.CamelCaseToUnderscoresNamingStrategy
properties:
hibernate:
format_sql: true
jdbc:
time_zone: UTC
database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
logging:
level:
org:
hibernate:
SQL: debug
type: trace
로컬 MySQL DB를 이용하고 있으며 ddl-auto가 create로 배포환경에는 적합하지 않습니다.
운영환경을 적용하려면 몇가지를 적용하거나 변경해주어야 합니다.
spring: datasource: url, username, password
: RDS를 이용하므로 RDS에 맞게 적용시켜줘야 합니다.jpa: hibernate: ddl-auto: none
: 운영환경에서는 절대 DB 테이블이 초기화되면 안됩니다!!
application.yml: Spring Boot가 제일 먼저 읽고 어떤 profile을 읽을지 설정한다. prod로 설정했으므로 application-prod.yml 파일을 이용해 Spring Boot가 시작됩니다!
spring:
profiles:
active: prod
application-local.yml: 로컬 환경에서 사용될 설정입니다.
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/jscode-spring-class?characterEncoding=UTF-8
username: hoseok
password: 1234
jpa:
hibernate:
ddl-auto: create
naming:
physical-strategy: org.hibernate.boot.model.naming.CamelCaseToUnderscoresNamingStrategy
properties:
hibernate:
format_sql: true
jdbc:
time_zone: UTC
database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
logging:
level:
org:
hibernate:
SQL: debug
type: trace
application-dev.yml: 개발 환경에서 사용됩니다.(현재 상황에서는 나누는것의 의미가 거의 없고, 연습을 위해 나눴습니다!)
spring:
datasource:
url: jdbc:h2:mem:testdb;MODE=MYSQL
username: sa
password:
jpa:
hibernate:
ddl-auto: none
naming:
physical-strategy: org.hibernate.boot.model.naming.CamelCaseToUnderscoresNamingStrategy
properties:
hibernate:
format_sql: true
jdbc:
time_zone: Asia/Seoul
database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
logging:
level:
org:
hibernate:
SQL: debug
type: trace
application-prod.yml: 배포시 운영환경에서 사용될 설정입니다. Elastic Beanstalk에서 설정한 key, value 값을 입력하기 위해서 민감한 정보에 대해서는 노출시키지 않습니다! 배포환경에 민감 정보에 대한 관리 방법에 대한 자세한 내용은 다음 블로그를 참고하시면 좋습니다!
spring:
datasource:
url: jdbc:mysql://${rds.endpoint}:${rds.port}/${rds.schema}?characterEncoding=UTF-8
username: ${rds.username}
password: ${rds.password}
jpa:
hibernate:
ddl-auto: none
naming:
physical-strategy: org.hibernate.boot.model.naming.CamelCaseToUnderscoresNamingStrategy
properties:
hibernate:
format_sql: true
jdbc:
time_zone: Asia/Seoul
database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
logging:
level:
org:
hibernate:
SQL: debug
type: trace
3. IAM 계정 등록 및 Elastic Beanstalk을 위한 권한 설정
IAM 계정 등록
Elastic Beanstalk을 통해 배포를 하려면 IAM 계정을 등록하고 권한을 설정해야 합니다!
해당 과정은 AWS 공식문서에서 자세히 설명하고 있으므로 다음 과정을 착실히 따라가면 생성할 수 있습니다!
https://docs.aws.amazon.com/ko_kr/singlesignon/latest/userguide/getting-started.html
Elastic Beanstalk에 사용할 권한 설정
IAM 설정에 들어가서 역할 탭의 역할 만들기
를 통해 역할!
을 생성한다.
Elastic Beanstalk가 자동 설정해주는 EC2에 적용하기 위해 EC2를 선택한다.
beanstalk를 검색해서 상위 3개의 정책을 선택하고 다음을 누른다. 이후 이름을 설정하고 생성을 완료하면 된다.
4. RDS, Elastic Beanstalk 생성하기
Elastic Beanstalk을 이용하면 RDS까지 통합적으로 생성할 수 있지만, 개인적으로는 분리하는 편이 관리하기가 쉽다고 느껴져서 RDS와 Elastic Beanstalk을 분리했습니다!
RDS 생성
우선 RDS를 생성하는 과정은 워낙 간단하므로, 따로 설명하진 않겠습니다!
RDS도 AWS 프리티어 기간에서 무료로 이용할 수 있지만, 과금을 방지하기 위해 몇가지 해야할 설정이 있습니다! 해당 설정을 고려한 RDS 생성 글이 존재하므로 다음 글을 참고하시면 좋을것 같습니다!
AWS RDS(mySql) 프리티어 생성하기
Elastic Beanstalk 생성
웹 서버 환경으로 설정하고, 애플리케이션 이름을 작성합니다.
플랫폼은 Java이며, Java11을 선택합니다. (현재 프로젝트 기준)
프리셋은 사용자 지정 구성으로 설정해야 무중단 배포를 위한 로드 밸런서를 설정할 수 있습니다.
Elastic Beanstalk을 처음 생성하면 새 서비스 역할 생성 및 사용
을 선택하여 등록하고 사전에 생성한 EC2 인스턴스의 키페어를 등록합니다. EC2 인스턴스 프로파일은 위에서 만들었던 역할 권한
을 선택하고 다음을 누릅니다!
3단계에서는 네트워킹 및 DB를 설정합니다. 우리는 별도의 RDS를 구성했으므로 건너뛰어도 무관합니다!
루트 볼륨은 기본값을 사용하고 보안 그룹은 현재 애플리케이션에서 이용하는 호스트에 대해 인바운드 아웃바운드 규칙을 적용한 보안 그룹을 이용합니다!
오토 스케일링 그룹의 환경 유형은 밸런싱된 로드
를 선택합니다.
로드 밸런서는 애플리케이션 로드 밸런서(ALB)를 이용합니다.
로드 밸런서에 대해 자세한 내용은 알지 못하지만, 예정된 이벤트가 아닌 갑작스런 트래픽에 대응하기에 유용합니다. 로드 밸런서에 대한 리스너를 활성화 합니다.
또한 배포 정책으로 추가 배치를 사용한 롤링을 이용합니다. 따라서 배포시에 신규 인스턴스에 신규 버전을 올리고, 해당 인스턴스가 문제가 없다면 기존 인스턴스를 죽이는 방식이다. 1개의 인스턴이며 배치 크기가 100프로 이므로 해당 설정을 사용합니다!
하단에 환경속성이 존재하는데, 여기서 RDS에 대한 설정을 key, value로 등록할 수 있습니다. 애플리케이션을 배포하게 되면 여기서 등록한 환경속성은 application-prod.yml
에서 ${}
와 설정한 내용을 비교하여 적절하게 매핑해줍니다! 이를 통해 민감한 속성을 GitHub에 노출하지 않을 수 있습니다!
생성을 완료하면 5 ~ 10분의 시간동안 Elastic Beanstalk 애플리케이션 및 환경을 구성합니다!
5. IAM 인증키를 받아서 GitHub에 등록하기
IAM 인증키 생성하기
Beanstalk 설정이 완료됐다면 GitHub Actions에서 Elastic Beanstalk에 접근할 수 있도록 인증키를 발급받아야 합니다.
인증키를 발급 받기 위해선 IAM에서 별도의 사용자를 생성해야 합니다! 아래 화면에서 사용자 추가를 누르고 사용자 이름을 생성합니다! (aws-eb-admin은 본인이 배포를 진행하면서 미리 만들어 둔 사용자 입니다!)
권한 설정에서 직접 정책 연결을 통해 AdministratorAccess-AWSElasticBeanstalk
권한을 부여 합니다.
생성한 사용자를 구분할 수 있도록 Name
태그를 추가하고 사용자를 생성합니다.
사용자 목록에서 우리가 생성한 사용자를 클릭하여 보안 자격 증명
탭을 클릭하여 하단에 액세스 키
항목에서 액세스 키 만들기
를 클릭합니다.
이후 AWS 컴퓨팅 서비스에서 실행되는 애플리케이션
항목을 선택합니다.
설명 태그 값에 대한 입력을 완료하고 액세스 키를 만들면 액세스 키와 value가 생성된것을 확인할 수 있습니다!
GitHub Actions에 등록하기
위에서 생성한 액세스 키와 밸류를 GitHub Actions에 등록하려면 우선 리포지토리의 Settings
의 Secrets and variables
를 들어갑니다.
이곳에서 AWS_ACCESS_KEY_ID
로 생성한 액세스 키의 id를 입력하고, AWS_SECRET_ACCESS_KEY
에 실제 키 값을 입력하여 등록합니다. 이렇게 함으로써 GitHub Actions에서 배포동작시 해당 값을 이용해 Elastic Beanstalk에 접근할 수 있습니다.
6. GitHub Actions 스크립트 파일 작성
브랜치, Java, 빌드 설정
우선 프로젝트 리포지토리에서 최상단 디렉토리에 .github/workflows/deploy.yml
생성을 하고 아래의 기본 스크립트를 추가한다.
name: anonymous-board
on:
push:
branches:
- main # (1) 트리거 브랜치 설정: 해당 브랜치에 push되면 스크립트 실행됨
paths: 'anonymous-board/**' # 해당 디렉토리 하위에 gradlew가 존재하므로
workflow_dispatch: # (2) 수동 실행: main 브랜치 push외에도 수동으로 해당 스크립트를 실행가능하도록 한다.
defaults:
run:
working-directory: anonymous-board # 해당 디렉토리 하위에 gradlew가 존재하므로 시작 디렉토리를 조정한다.
jobs:
build:
runs-on: ubuntu-latest # (3) Github Action 스크립트가 작동될 OS 환경 지정
steps:
- name: Checkout
uses: actions/checkout@v2 # (4) 프로젝트 코드 체크아웃
- name: Set up JDK 11
uses: actions/setup-java@v1 # (5) GitHub Action이 실행될 OS에 Java 설치
with:
java-version: 11
- name: Grant execute permission for gradlew
run: chmod +x ./gradlew # (6) gradle wrapper를 실행할 수 있도록 실행권한 줌
shell: bash
- name: Build with Gradle
run: ./gradlew clean build # (7) gradle wrapper를 통해 해당 프로젝트를 build함
shell: bash
- name: Get current time
uses: 1466587594/get-current-time@v2
id: current-time
with:
format: YYYY-MM-DDTHH-mm-ss # (8) action은 기존의 Momentjs를 지원하므로 동일한 포맷을 사용함
utcOffset: "+09:00" # (9) UTC기준 +9시간이 한국시간 KST가 된다.
번호 순서대로 읽어보면 위의 스크립트가 어떤 동작을 하는지 이해가 갈 것 입니다!
빌드된 jar 파일을 Beanstalk에 배포하기 위한 zip파일로 만들기
- name: Generate deployment package # (1)
run: |
mkdir -p deploy
cp build/libs/*.jar deploy/application.jar
cp Procfile deploy/Procfile
cp -r .ebextensions deploy/.ebextensions
cp -r .platform deploy/.platform
cd deploy && zip -r deploy.zip .
Gradle Build를 통해 만들어진 jar파일을 Beanstalk에 배포하기 위해 deploy.zip파일로 만들어주는 스크립트 입니다.
빌드가 끝나면 → Jar파일명을 application.jar로 변경
(매 빌드마다 jar의 파일명이 버전과 타임스탬프로 파일명이 교체됨, 따라서 매번 달라질 파일명을 찾기보다는 하나로 통일해 사용)
build/libs/*.jar
는 해당 디렉토리에 존재하는 빌드된 jar 파일을 deploy/application.jar
로 변경한다. 이때 주의점이 있는데 Spring Boot 2.5 버전 이상부터는 빌드를 하게 되면 ~plain.jar
라는 jar 파일이 하나 더 생성되므로 다음 설정을 build.gradle에 추가해 생성을 방지한다.
jar {
enabled = false
}
추가되는 스크립트에서 이용되는 Procfile, .ebextensions, .platform은 이후에 좀 더 자세히 설명하겠습니다!
Beanstalk Deploy 플러그인을 통해 Elastic Beanstalk 배포 설정 스크립트 작성
Beanstalk Deploy는 GitHub Actions를 통해 Beanstalk 배포를 편리하게 도와주는 플러그인 입니다! 이를 이용하면 편하게 배포 코드를 작성할 수 있습니다. 따라서 다음 스크립트를 추가해줍니다!
- name: Deploy to EB # (2)
uses: einaregilsson/beanstalk-deploy@v14
with:
aws_access_key: ${{ secrets.AWS_ACCESS_KEY_ID }} # 우리가 Secret 키로 설정한 값들
aws_secret_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
application_name: MyApplicationName # Beanstalk에서 생성한 애플리케이션의 이름
environment_name: MyApplication-Environment # Beanstalk에서 생성한 환경의 이름
version_label: github-action-${{steps.current-time.outputs.formattedTime}}
region: ap-northeast-2
deployment_package: anonymous-board/deploy/deploy.zip
Beanstalk 플러그인을 사용하는데 이때 생성한 IAM 인증키가 이곳에서 사용됩니다.
Beanstalk가 플러그인을 통해 배포될때마다 유니크한 버전을 갖기 위해 시간을 추가했습니다.
한가지 주의해야 하는 부분은
deployment_package
입니다. 현재 프로젝트는 anonymous-board라는 디렉토리 하위에 실제 프로젝트 코드들이 존재합니다. 따라서 초기 deploy.yml 설정에서working-directory: anonymous-board # 해당 디렉토리 하위에 gradlew가 존재하므로 시작
과 같이 실제 동작 디렉토리를 설정해주었습니다.하지만 Beanstalk 플러그인을 사용하는 부분에서는 해당 설정이 적용되지 않으므로 정확한 프로젝트 경로(anonymous-board 디렉토리가 포함)를 작성해야 합니다.
완성된 deploy.yml
name: anonymous-board
on:
push:
branches:
- main # (1) 실습하시는분들은 master로 하시면 됩니다. (저는 별도 브랜치로 지정)
paths: 'anonymous-board/**'
workflow_dispatch: # (2) 수동 실행
defaults:
run:
working-directory: anonymous-board
jobs:
build:
runs-on: ubuntu-latest # (3)
steps:
- name: Checkout
uses: actions/checkout@v2 # (4)
- name: Set up JDK 11
uses: actions/setup-java@v1 # (5)
with:
java-version: 11
- name: Grant execute permission for gradlew
run: chmod +x ./gradlew # (6)
shell: bash
- name: Build with Gradle
run: ./gradlew clean build # (7)
shell: bash
- name: Get current time
uses: 1466587594/get-current-time@v2
id: current-time
with:
format: YYYY-MM-DDTHH-mm-ss # (1)
utcOffset: "+09:00"
- name: Generate deployment package # (1)
run: |
mkdir -p deploy
cp build/libs/*.jar deploy/application.jar
cp Procfile deploy/Procfile
cp -r .ebextensions deploy/.ebextensions
cp -r .platform deploy/.platform
cd deploy && zip -r deploy.zip .
- name: Deploy to EB
uses: einaregilsson/beanstalk-deploy@v21
with:
aws_access_key: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws_secret_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
application_name: my-eb-server-final
environment_name: anonymous-board
version_label: github-action-${{steps.current-time.outputs.formattedTime}}
region: ap-northeast-2
deployment_package: anonymous-board/deploy/deploy.zip
7. Beanstalk 애플리케이션 구성
위의 name: Genereate deployment package
작업에서 언급되었던 Prockfile
, .platform/nginx/nginx.conf
, .ebextensions/00-makeFiles.config
에 대해서 애플리케이션을 구성해봅시다!
다른 부분도 잘 모르지만 특히 현재 진행할 부분은 추가 공부가 필요합니다. 단순히 해당 코드가 어떤 역할이겠다는 어림짐작은 있지만, 정확한 의미는 잘 알지 못합니다 ㅠ
우선 위의 3개의 파일은 프로젝트에서 아래와 같이 위치하고 있습니다!
.ebextensions
Beanstalk는 시스템의 대부분을 AWS에서 자동 구성을 해주므로 EC2에서 직접 설치할때 처럼 사용할 수 없습니다.
따라서 Custom하게 사용할 수 있도록 설정하려면 .ebextensions
디렉토리를 이용합니다.
해당 디렉토리에 .config
파일 확장 명을 가진 YAML 혹은 JSON 형태의 설정 코드를 두면 그에 맞춰 Beanstalk 배포시/환경 재구성시 사용됩니다.
현재 만들고자 하는 Custom 기능은 애플리케이션 실행 스크립트(java -jar application.jar
)를 생성하는 것입니다.
조금더 구체적으로 Beanstalk이 GitHub Actions로 전달 받은 zip파일(배포파일)이 압축이 풀리고 난후 내부의 특정 파일을 어떤 파라미터로 설정하는지 설정하는 스크립트 입니다!
.ebextension/00-makeFiles.config
files:
"/sbin/appstart" :
mode: "000755"
owner: webapp
group: webapp
content: |
#!/usr/bin/env bash
JAR_PATH=/var/app/current/application.jar
# run app
killall java
java -Dfile.encoding=UTF-8 -jar $JAR_PATH
/sbin
아래에 스크립트 파일을 두면 전역에서 실행 가능합니다.- 따라서 해당 디렉토리 아래 appstart라는 스크립트 파일을 생성하고
- 권한은 755(소유자만 모든 것(쓰기, 읽기, 실행)이 가능하고 그 외 사용자의 경우는 읽기, 실행은 가능하나 쓰기는 불가능)를 주고 사용자는
webapp
으로 하여content
내용을 가진 스크립트 파일이 생성됩니다. - 이곳에서 만들어진
/sbin/appstart
스크립트 파일은Procfile
에서 실행됩니다.
Procfile
Beanstalk 입장에선 배포 애플리케이션의 실행은 Procfile의 실행을 의미합니다.
이미 실행 스크립트는 위의 00-makeFiles.config
에서 생성한 sbin/appstart
스크립트를 실행하기만 하면 됩니다.
따라서 다음과 같이 추가합니다.
Procfile
web: appstart
.platform/nginx/nginx.conf
해당 파일은 Elastic Beanstalk에서 리버스 프록시를 담당하는 Nginx에 대한 설정을 합니다.
이미 ALB(Application Load Balancer)를 통해 무중단 배포를 하도록 구성했습니다.
따라서 여기서 설정하는 Nginx는 무중단 배포를 위한 것이 아닙니다.
Nginx는 임베디드 톰캣으로 클라이언트의 요청을 보내는 역할만을 합니다.
.platform/nginx/nginx.conf
user nginx;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
worker_processes auto;
worker_rlimit_nofile 33282;
events {
use epoll;
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
include conf.d/*.conf;
map $http_upgrade $connection_upgrade {
default "upgrade";
}
upstream springboot {
server 127.0.0.1:8080;
keepalive 1024;
}
server {
listen 80 default_server;
location / {
proxy_pass http://springboot;
proxy_http_version 1.1;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
access_log /var/log/nginx/access.log main;
client_header_timeout 60;
client_body_timeout 60;
keepalive_timeout 60;
gzip off;
gzip_comp_level 4;
# Include the Elastic Beanstalk generated locations
include conf.d/elasticbeanstalk/healthd.conf;
}
}
아직 Nginx에 대해 자세히 알지 못하므로 복사/붙여넣기 수준으로 구성했습니다 ㅎㅎ..
이제 모든 설정이 완료됐고, 실제 애플리케이션 배포 단계가 남아있습니다!
8. 애플리케이션 배포
deploy.yml
에서 main 브랜치에 push됐을때 자동으로 배포 스크립트가 실행되도록 설정했으므로, 실제 main 브랜치에 다음과 같이 merge 합니다.
이후 GitHub Actions를 보면 배포 스크립트가 실행됩니다!
아래 Deploy to EB 과정의 로그들이 실제 Elastic Beanstalk의 로그에도 동일하게 나타납니다!
배포 단계가 완료되고 Elastic Beanstalk을 보게되면 도메인이 존재하는데 해당 도메인을 가지고 있습니다.
Postman을 통해 실제 게시글 생성 API 요청을 보내게 되면 정상적으로 게시글이 생성됨을 알 수 있습니다!!
어려웠던 부분, 시간을 들였던 부분
배포 과정을 진행하면서 IAM 설정 및 권한 설정에 대한 어려움이 있었습니다..
설정 자체는 어렵지 않았지만, Elastic Beanstalk을 설정없이 생성하려 했던 삽질의 시간이 정말 길었습니다..
또한 참고한 레퍼런스와 실제 내 프로젝트의 디렉토리 구조가 다르다 보니 그런 차이점들을 인지하고 변경을 주는 부분에서도 많은 시간이 들었습니다.
많은 삽질이 있었지만, 결론은 정말 간단했던.. 하지만 삽질로 인해 조금 단단해지지 않았을까 생각합니다 ㅎㅎ
간단하게 무중단 배포를 진행하면서 공부해야 할 키워드들도 늘었습니다.
(Nginx
, Linux
, GitHub Actions 스크립트
, Elastic Beanstalk에 대한 전반적인 이해
)
참고 레퍼런스
- Hibernate ORM Docs: best practices logging - Hibernate Docs
- [Spring Boot] 환경 분리하기 - Valog
- [AWS RDS] 프리티어에서 RDS 과금 방지하기 - Velog
- AWS IAM identity Center 시작하기 - AWS Docs
- Elastic Beanstalk environment is not getting created - AWS QnA
- AWS Elastic Beanstalk으로 개발서버를 구축해본 이야기 - Tistory
- IAM 계정 등록하기 - AWS Docs
- EB에 SpringBoot 배포(1) - EB 기본 세팅 - Velog
- 1. Github Action & AWS Beanstalk 배포하기 - Github Action으로 빌드하기 - 향로님 블로그
- 2. Github Action & AWS Beanstalk 배포하기 - profile=local로 배포하기 - 향로님 블로그
3회차 미션은 지금까지 만들었던 익명 게시판을 배포하는 것입니다!
배포 환경은 AWS Elastic Beanstalk 이용합니다.
우선 Elastic Beanstalk은 EC2, RDS, S3 환경을 동시에 제공해줍니다.
더 나아가 프로비저닝, 로드 밸런싱, Auto Scaling과 같은 기능을 Beanstalk가 제공해줍니다.
Elastic Beanstalk은 기본적으로 Nginx를 이용한 리버스 프록싱을 지원해줍니다!
이전시간까지는 단순히 CRDU API와 API DOCS를 만들었습니다.
이번 시간은 실제 배포를 위한 Spring Boot에서의 설정과 배포 시스템을 구성하여 무중단 배포를 할 수 있도록 진행해보겠습니다!
참고로 Elastic Beanstalk을 생성하려면 EC2 인스턴스를 생성하고 키페어를 발급받아야 합니다!
1. Cors 설정하기
React.js를 사용한다면 http://localhost:3000을 사용합니다.
Tomcat 서버는 기본적으로 http://localhost:8080을 사용하므로
Protocol, Host는 동일하지만 Port가 달라지므로 서로 다른 출처 Cross Origin으로 간주됩니다.
브라우저는 이들 중 하나라도 다르면 차단됩니다.
사실 이를 해결하는 방안이 Cross-Origin Resource Sharing으로 Cors라고 합니다. 또한 브라우저는 기본적으로 동일 출러(Same-Origin Policy)를 따르고 있으므로 react에서 톰캣으로 보낸 요청이 막히게 됩니다.
Cors를 적용하기 위해서는 Spring Boot에서의 설정을 많이 이용하는데 아무래도 인터페이스와 메소드 하나만 구현하면 간단하게 적용할 수 있기 때문인것 같습니다!
WebMvcConfigurer
Spring Boot는 WebMvcConfigurer 인터페이스를 제공해주는데 해당 인터페이스에서는 Spring MVC에 대한 설정을 커스텀하게 적용할 수 있습니다.
여기서 void addCorsMappings(CorsRegistry registry)
메소드를 오버라이딩하여 Cors 정책을 적용할 컨트롤러 매핑과 요청을 허용할 클라이언트의 주소 및 허용 HTTP Method등 다양한 설정을 할 수 있습니다.
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
private static final String ALLOWED_METHOD_NAMES = "GET,HEAD,POST,DELETE,TRACE,OPTIONS,PATCH,PUT";
@Override
public void addCorsMappings(final CorsRegistry registry) {
registry.addMapping("/**") (1)
.allowedOrigins("http://localhost:3000") (2)
.allowedMethods(ALLOWED_METHOD_NAMES.split(",")); (3)
}
}
- (1): Cors 정책을 모든 컨트롤러 매핑에 적용합니다.
- (2): React에서 사용되는 3000번 포트를 허용합니다. (별도의 도메인이 있다면 해당 도메인을 적용)
- (3):
ALLOWD_METHOD_NAMES
에 작성한 모든 HTTP Method를 허용합니다.
2. Spring Boot 환경변수 분리하기
배포를 한다면, 기존에 사용하던 로컬 개발 환경이 아닌 배포를 위한 새로운 환경을 구성해야 합니다.
Spring Boot는 application.yml 혹은 properties를 통해 쉽게 개발환경과 배포환경을 분리할 수 있는 기능을 제공합니다!
하나의 yml 파일을 사용할 수 도있지만, 3개의 yml파일을 구성해 각각, 로컬 환경, 개발 환경, 운영 환경으로 구성해보겠습니다.
로컬, 개발, 운영환경 나누기
기존 application.yml은 다음과 같습니다
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/jscode-spring-class?characterEncoding=UTF-8
username: hoseok
password: 1234
jpa:
hibernate:
ddl-auto: create
naming:
physical-strategy: org.hibernate.boot.model.naming.CamelCaseToUnderscoresNamingStrategy
properties:
hibernate:
format_sql: true
jdbc:
time_zone: UTC
database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
logging:
level:
org:
hibernate:
SQL: debug
type: trace
로컬 MySQL DB를 이용하고 있으며 ddl-auto가 create로 배포환경에는 적합하지 않습니다.
운영환경을 적용하려면 몇가지를 적용하거나 변경해주어야 합니다.
spring: datasource: url, username, password
: RDS를 이용하므로 RDS에 맞게 적용시켜줘야 합니다.jpa: hibernate: ddl-auto: none
: 운영환경에서는 절대 DB 테이블이 초기화되면 안됩니다!!
application.yml: Spring Boot가 제일 먼저 읽고 어떤 profile을 읽을지 설정한다. prod로 설정했으므로 application-prod.yml 파일을 이용해 Spring Boot가 시작됩니다!
spring:
profiles:
active: prod
application-local.yml: 로컬 환경에서 사용될 설정입니다.
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/jscode-spring-class?characterEncoding=UTF-8
username: hoseok
password: 1234
jpa:
hibernate:
ddl-auto: create
naming:
physical-strategy: org.hibernate.boot.model.naming.CamelCaseToUnderscoresNamingStrategy
properties:
hibernate:
format_sql: true
jdbc:
time_zone: UTC
database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
logging:
level:
org:
hibernate:
SQL: debug
type: trace
application-dev.yml: 개발 환경에서 사용됩니다.(현재 상황에서는 나누는것의 의미가 거의 없고, 연습을 위해 나눴습니다!)
spring:
datasource:
url: jdbc:h2:mem:testdb;MODE=MYSQL
username: sa
password:
jpa:
hibernate:
ddl-auto: none
naming:
physical-strategy: org.hibernate.boot.model.naming.CamelCaseToUnderscoresNamingStrategy
properties:
hibernate:
format_sql: true
jdbc:
time_zone: Asia/Seoul
database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
logging:
level:
org:
hibernate:
SQL: debug
type: trace
application-prod.yml: 배포시 운영환경에서 사용될 설정입니다. Elastic Beanstalk에서 설정한 key, value 값을 입력하기 위해서 민감한 정보에 대해서는 노출시키지 않습니다! 배포환경에 민감 정보에 대한 관리 방법에 대한 자세한 내용은 다음 블로그를 참고하시면 좋습니다!
spring:
datasource:
url: jdbc:mysql://${rds.endpoint}:${rds.port}/${rds.schema}?characterEncoding=UTF-8
username: ${rds.username}
password: ${rds.password}
jpa:
hibernate:
ddl-auto: none
naming:
physical-strategy: org.hibernate.boot.model.naming.CamelCaseToUnderscoresNamingStrategy
properties:
hibernate:
format_sql: true
jdbc:
time_zone: Asia/Seoul
database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
logging:
level:
org:
hibernate:
SQL: debug
type: trace
3. IAM 계정 등록 및 Elastic Beanstalk을 위한 권한 설정
IAM 계정 등록
Elastic Beanstalk을 통해 배포를 하려면 IAM 계정을 등록하고 권한을 설정해야 합니다!
해당 과정은 AWS 공식문서에서 자세히 설명하고 있으므로 다음 과정을 착실히 따라가면 생성할 수 있습니다!
https://docs.aws.amazon.com/ko_kr/singlesignon/latest/userguide/getting-started.html
Elastic Beanstalk에 사용할 권한 설정
IAM 설정에 들어가서 역할 탭의 역할 만들기
를 통해 역할!
을 생성한다.
Elastic Beanstalk가 자동 설정해주는 EC2에 적용하기 위해 EC2를 선택한다.
beanstalk를 검색해서 상위 3개의 정책을 선택하고 다음을 누른다. 이후 이름을 설정하고 생성을 완료하면 된다.
4. RDS, Elastic Beanstalk 생성하기
Elastic Beanstalk을 이용하면 RDS까지 통합적으로 생성할 수 있지만, 개인적으로는 분리하는 편이 관리하기가 쉽다고 느껴져서 RDS와 Elastic Beanstalk을 분리했습니다!
RDS 생성
우선 RDS를 생성하는 과정은 워낙 간단하므로, 따로 설명하진 않겠습니다!
RDS도 AWS 프리티어 기간에서 무료로 이용할 수 있지만, 과금을 방지하기 위해 몇가지 해야할 설정이 있습니다! 해당 설정을 고려한 RDS 생성 글이 존재하므로 다음 글을 참고하시면 좋을것 같습니다!
AWS RDS(mySql) 프리티어 생성하기
Elastic Beanstalk 생성
웹 서버 환경으로 설정하고, 애플리케이션 이름을 작성합니다.
플랫폼은 Java이며, Java11을 선택합니다. (현재 프로젝트 기준)
프리셋은 사용자 지정 구성으로 설정해야 무중단 배포를 위한 로드 밸런서를 설정할 수 있습니다.
Elastic Beanstalk을 처음 생성하면 새 서비스 역할 생성 및 사용
을 선택하여 등록하고 사전에 생성한 EC2 인스턴스의 키페어를 등록합니다. EC2 인스턴스 프로파일은 위에서 만들었던 역할 권한
을 선택하고 다음을 누릅니다!
3단계에서는 네트워킹 및 DB를 설정합니다. 우리는 별도의 RDS를 구성했으므로 건너뛰어도 무관합니다!
루트 볼륨은 기본값을 사용하고 보안 그룹은 현재 애플리케이션에서 이용하는 호스트에 대해 인바운드 아웃바운드 규칙을 적용한 보안 그룹을 이용합니다!
오토 스케일링 그룹의 환경 유형은 밸런싱된 로드
를 선택합니다.
로드 밸런서는 애플리케이션 로드 밸런서(ALB)를 이용합니다.
로드 밸런서에 대해 자세한 내용은 알지 못하지만, 예정된 이벤트가 아닌 갑작스런 트래픽에 대응하기에 유용합니다. 로드 밸런서에 대한 리스너를 활성화 합니다.
또한 배포 정책으로 추가 배치를 사용한 롤링을 이용합니다. 따라서 배포시에 신규 인스턴스에 신규 버전을 올리고, 해당 인스턴스가 문제가 없다면 기존 인스턴스를 죽이는 방식이다. 1개의 인스턴이며 배치 크기가 100프로 이므로 해당 설정을 사용합니다!
하단에 환경속성이 존재하는데, 여기서 RDS에 대한 설정을 key, value로 등록할 수 있습니다. 애플리케이션을 배포하게 되면 여기서 등록한 환경속성은 application-prod.yml
에서 ${}
와 설정한 내용을 비교하여 적절하게 매핑해줍니다! 이를 통해 민감한 속성을 GitHub에 노출하지 않을 수 있습니다!
생성을 완료하면 5 ~ 10분의 시간동안 Elastic Beanstalk 애플리케이션 및 환경을 구성합니다!
5. IAM 인증키를 받아서 GitHub에 등록하기
IAM 인증키 생성하기
Beanstalk 설정이 완료됐다면 GitHub Actions에서 Elastic Beanstalk에 접근할 수 있도록 인증키를 발급받아야 합니다.
인증키를 발급 받기 위해선 IAM에서 별도의 사용자를 생성해야 합니다! 아래 화면에서 사용자 추가를 누르고 사용자 이름을 생성합니다! (aws-eb-admin은 본인이 배포를 진행하면서 미리 만들어 둔 사용자 입니다!)
권한 설정에서 직접 정책 연결을 통해 AdministratorAccess-AWSElasticBeanstalk
권한을 부여 합니다.
생성한 사용자를 구분할 수 있도록 Name
태그를 추가하고 사용자를 생성합니다.
사용자 목록에서 우리가 생성한 사용자를 클릭하여 보안 자격 증명
탭을 클릭하여 하단에 액세스 키
항목에서 액세스 키 만들기
를 클릭합니다.
이후 AWS 컴퓨팅 서비스에서 실행되는 애플리케이션
항목을 선택합니다.
설명 태그 값에 대한 입력을 완료하고 액세스 키를 만들면 액세스 키와 value가 생성된것을 확인할 수 있습니다!
GitHub Actions에 등록하기
위에서 생성한 액세스 키와 밸류를 GitHub Actions에 등록하려면 우선 리포지토리의 Settings
의 Secrets and variables
를 들어갑니다.
이곳에서 AWS_ACCESS_KEY_ID
로 생성한 액세스 키의 id를 입력하고, AWS_SECRET_ACCESS_KEY
에 실제 키 값을 입력하여 등록합니다. 이렇게 함으로써 GitHub Actions에서 배포동작시 해당 값을 이용해 Elastic Beanstalk에 접근할 수 있습니다.
6. GitHub Actions 스크립트 파일 작성
브랜치, Java, 빌드 설정
우선 프로젝트 리포지토리에서 최상단 디렉토리에 .github/workflows/deploy.yml
생성을 하고 아래의 기본 스크립트를 추가한다.
name: anonymous-board
on:
push:
branches:
- main # (1) 트리거 브랜치 설정: 해당 브랜치에 push되면 스크립트 실행됨
paths: 'anonymous-board/**' # 해당 디렉토리 하위에 gradlew가 존재하므로
workflow_dispatch: # (2) 수동 실행: main 브랜치 push외에도 수동으로 해당 스크립트를 실행가능하도록 한다.
defaults:
run:
working-directory: anonymous-board # 해당 디렉토리 하위에 gradlew가 존재하므로 시작 디렉토리를 조정한다.
jobs:
build:
runs-on: ubuntu-latest # (3) Github Action 스크립트가 작동될 OS 환경 지정
steps:
- name: Checkout
uses: actions/checkout@v2 # (4) 프로젝트 코드 체크아웃
- name: Set up JDK 11
uses: actions/setup-java@v1 # (5) GitHub Action이 실행될 OS에 Java 설치
with:
java-version: 11
- name: Grant execute permission for gradlew
run: chmod +x ./gradlew # (6) gradle wrapper를 실행할 수 있도록 실행권한 줌
shell: bash
- name: Build with Gradle
run: ./gradlew clean build # (7) gradle wrapper를 통해 해당 프로젝트를 build함
shell: bash
- name: Get current time
uses: 1466587594/get-current-time@v2
id: current-time
with:
format: YYYY-MM-DDTHH-mm-ss # (8) action은 기존의 Momentjs를 지원하므로 동일한 포맷을 사용함
utcOffset: "+09:00" # (9) UTC기준 +9시간이 한국시간 KST가 된다.
번호 순서대로 읽어보면 위의 스크립트가 어떤 동작을 하는지 이해가 갈 것 입니다!
빌드된 jar 파일을 Beanstalk에 배포하기 위한 zip파일로 만들기
- name: Generate deployment package # (1)
run: |
mkdir -p deploy
cp build/libs/*.jar deploy/application.jar
cp Procfile deploy/Procfile
cp -r .ebextensions deploy/.ebextensions
cp -r .platform deploy/.platform
cd deploy && zip -r deploy.zip .
Gradle Build를 통해 만들어진 jar파일을 Beanstalk에 배포하기 위해 deploy.zip파일로 만들어주는 스크립트 입니다.
빌드가 끝나면 → Jar파일명을 application.jar로 변경
(매 빌드마다 jar의 파일명이 버전과 타임스탬프로 파일명이 교체됨, 따라서 매번 달라질 파일명을 찾기보다는 하나로 통일해 사용)
build/libs/*.jar
는 해당 디렉토리에 존재하는 빌드된 jar 파일을 deploy/application.jar
로 변경한다. 이때 주의점이 있는데 Spring Boot 2.5 버전 이상부터는 빌드를 하게 되면 ~plain.jar
라는 jar 파일이 하나 더 생성되므로 다음 설정을 build.gradle에 추가해 생성을 방지한다.
jar {
enabled = false
}
추가되는 스크립트에서 이용되는 Procfile, .ebextensions, .platform은 이후에 좀 더 자세히 설명하겠습니다!
Beanstalk Deploy 플러그인을 통해 Elastic Beanstalk 배포 설정 스크립트 작성
Beanstalk Deploy는 GitHub Actions를 통해 Beanstalk 배포를 편리하게 도와주는 플러그인 입니다! 이를 이용하면 편하게 배포 코드를 작성할 수 있습니다. 따라서 다음 스크립트를 추가해줍니다!
- name: Deploy to EB # (2)
uses: einaregilsson/beanstalk-deploy@v14
with:
aws_access_key: ${{ secrets.AWS_ACCESS_KEY_ID }} # 우리가 Secret 키로 설정한 값들
aws_secret_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
application_name: MyApplicationName # Beanstalk에서 생성한 애플리케이션의 이름
environment_name: MyApplication-Environment # Beanstalk에서 생성한 환경의 이름
version_label: github-action-${{steps.current-time.outputs.formattedTime}}
region: ap-northeast-2
deployment_package: anonymous-board/deploy/deploy.zip
Beanstalk 플러그인을 사용하는데 이때 생성한 IAM 인증키가 이곳에서 사용됩니다.
Beanstalk가 플러그인을 통해 배포될때마다 유니크한 버전을 갖기 위해 시간을 추가했습니다.
한가지 주의해야 하는 부분은
deployment_package
입니다. 현재 프로젝트는 anonymous-board라는 디렉토리 하위에 실제 프로젝트 코드들이 존재합니다. 따라서 초기 deploy.yml 설정에서working-directory: anonymous-board # 해당 디렉토리 하위에 gradlew가 존재하므로 시작
과 같이 실제 동작 디렉토리를 설정해주었습니다.하지만 Beanstalk 플러그인을 사용하는 부분에서는 해당 설정이 적용되지 않으므로 정확한 프로젝트 경로(anonymous-board 디렉토리가 포함)를 작성해야 합니다.
완성된 deploy.yml
name: anonymous-board
on:
push:
branches:
- main # (1) 실습하시는분들은 master로 하시면 됩니다. (저는 별도 브랜치로 지정)
paths: 'anonymous-board/**'
workflow_dispatch: # (2) 수동 실행
defaults:
run:
working-directory: anonymous-board
jobs:
build:
runs-on: ubuntu-latest # (3)
steps:
- name: Checkout
uses: actions/checkout@v2 # (4)
- name: Set up JDK 11
uses: actions/setup-java@v1 # (5)
with:
java-version: 11
- name: Grant execute permission for gradlew
run: chmod +x ./gradlew # (6)
shell: bash
- name: Build with Gradle
run: ./gradlew clean build # (7)
shell: bash
- name: Get current time
uses: 1466587594/get-current-time@v2
id: current-time
with:
format: YYYY-MM-DDTHH-mm-ss # (1)
utcOffset: "+09:00"
- name: Generate deployment package # (1)
run: |
mkdir -p deploy
cp build/libs/*.jar deploy/application.jar
cp Procfile deploy/Procfile
cp -r .ebextensions deploy/.ebextensions
cp -r .platform deploy/.platform
cd deploy && zip -r deploy.zip .
- name: Deploy to EB
uses: einaregilsson/beanstalk-deploy@v21
with:
aws_access_key: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws_secret_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
application_name: my-eb-server-final
environment_name: anonymous-board
version_label: github-action-${{steps.current-time.outputs.formattedTime}}
region: ap-northeast-2
deployment_package: anonymous-board/deploy/deploy.zip
7. Beanstalk 애플리케이션 구성
위의 name: Genereate deployment package
작업에서 언급되었던 Prockfile
, .platform/nginx/nginx.conf
, .ebextensions/00-makeFiles.config
에 대해서 애플리케이션을 구성해봅시다!
다른 부분도 잘 모르지만 특히 현재 진행할 부분은 추가 공부가 필요합니다. 단순히 해당 코드가 어떤 역할이겠다는 어림짐작은 있지만, 정확한 의미는 잘 알지 못합니다 ㅠ
우선 위의 3개의 파일은 프로젝트에서 아래와 같이 위치하고 있습니다!
.ebextensions
Beanstalk는 시스템의 대부분을 AWS에서 자동 구성을 해주므로 EC2에서 직접 설치할때 처럼 사용할 수 없습니다.
따라서 Custom하게 사용할 수 있도록 설정하려면 .ebextensions
디렉토리를 이용합니다.
해당 디렉토리에 .config
파일 확장 명을 가진 YAML 혹은 JSON 형태의 설정 코드를 두면 그에 맞춰 Beanstalk 배포시/환경 재구성시 사용됩니다.
현재 만들고자 하는 Custom 기능은 애플리케이션 실행 스크립트(java -jar application.jar
)를 생성하는 것입니다.
조금더 구체적으로 Beanstalk이 GitHub Actions로 전달 받은 zip파일(배포파일)이 압축이 풀리고 난후 내부의 특정 파일을 어떤 파라미터로 설정하는지 설정하는 스크립트 입니다!
.ebextension/00-makeFiles.config
files:
"/sbin/appstart" :
mode: "000755"
owner: webapp
group: webapp
content: |
#!/usr/bin/env bash
JAR_PATH=/var/app/current/application.jar
# run app
killall java
java -Dfile.encoding=UTF-8 -jar $JAR_PATH
/sbin
아래에 스크립트 파일을 두면 전역에서 실행 가능합니다.- 따라서 해당 디렉토리 아래 appstart라는 스크립트 파일을 생성하고
- 권한은 755(소유자만 모든 것(쓰기, 읽기, 실행)이 가능하고 그 외 사용자의 경우는 읽기, 실행은 가능하나 쓰기는 불가능)를 주고 사용자는
webapp
으로 하여content
내용을 가진 스크립트 파일이 생성됩니다. - 이곳에서 만들어진
/sbin/appstart
스크립트 파일은Procfile
에서 실행됩니다.
Procfile
Beanstalk 입장에선 배포 애플리케이션의 실행은 Procfile의 실행을 의미합니다.
이미 실행 스크립트는 위의 00-makeFiles.config
에서 생성한 sbin/appstart
스크립트를 실행하기만 하면 됩니다.
따라서 다음과 같이 추가합니다.
Procfile
web: appstart
.platform/nginx/nginx.conf
해당 파일은 Elastic Beanstalk에서 리버스 프록시를 담당하는 Nginx에 대한 설정을 합니다.
이미 ALB(Application Load Balancer)를 통해 무중단 배포를 하도록 구성했습니다.
따라서 여기서 설정하는 Nginx는 무중단 배포를 위한 것이 아닙니다.
Nginx는 임베디드 톰캣으로 클라이언트의 요청을 보내는 역할만을 합니다.
.platform/nginx/nginx.conf
user nginx;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
worker_processes auto;
worker_rlimit_nofile 33282;
events {
use epoll;
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
include conf.d/*.conf;
map $http_upgrade $connection_upgrade {
default "upgrade";
}
upstream springboot {
server 127.0.0.1:8080;
keepalive 1024;
}
server {
listen 80 default_server;
location / {
proxy_pass http://springboot;
proxy_http_version 1.1;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
access_log /var/log/nginx/access.log main;
client_header_timeout 60;
client_body_timeout 60;
keepalive_timeout 60;
gzip off;
gzip_comp_level 4;
# Include the Elastic Beanstalk generated locations
include conf.d/elasticbeanstalk/healthd.conf;
}
}
아직 Nginx에 대해 자세히 알지 못하므로 복사/붙여넣기 수준으로 구성했습니다 ㅎㅎ..
이제 모든 설정이 완료됐고, 실제 애플리케이션 배포 단계가 남아있습니다!
8. 애플리케이션 배포
deploy.yml
에서 main 브랜치에 push됐을때 자동으로 배포 스크립트가 실행되도록 설정했으므로, 실제 main 브랜치에 다음과 같이 merge 합니다.
이후 GitHub Actions를 보면 배포 스크립트가 실행됩니다!
아래 Deploy to EB 과정의 로그들이 실제 Elastic Beanstalk의 로그에도 동일하게 나타납니다!
배포 단계가 완료되고 Elastic Beanstalk을 보게되면 도메인이 존재하는데 해당 도메인을 가지고 있습니다.
Postman을 통해 실제 게시글 생성 API 요청을 보내게 되면 정상적으로 게시글이 생성됨을 알 수 있습니다!!
어려웠던 부분, 시간을 들였던 부분
배포 과정을 진행하면서 IAM 설정 및 권한 설정에 대한 어려움이 있었습니다..
설정 자체는 어렵지 않았지만, Elastic Beanstalk을 설정없이 생성하려 했던 삽질의 시간이 정말 길었습니다..
또한 참고한 레퍼런스와 실제 내 프로젝트의 디렉토리 구조가 다르다 보니 그런 차이점들을 인지하고 변경을 주는 부분에서도 많은 시간이 들었습니다.
많은 삽질이 있었지만, 결론은 정말 간단했던.. 하지만 삽질로 인해 조금 단단해지지 않았을까 생각합니다 ㅎㅎ
간단하게 무중단 배포를 진행하면서 공부해야 할 키워드들도 늘었습니다.
(Nginx
, Linux
, GitHub Actions 스크립트
, Elastic Beanstalk에 대한 전반적인 이해
)
참고 레퍼런스
- Hibernate ORM Docs: best practices logging - Hibernate Docs
- [Spring Boot] 환경 분리하기 - Valog
- [AWS RDS] 프리티어에서 RDS 과금 방지하기 - Velog
- AWS IAM identity Center 시작하기 - AWS Docs
- Elastic Beanstalk environment is not getting created - AWS QnA
- AWS Elastic Beanstalk으로 개발서버를 구축해본 이야기 - Tistory
- IAM 계정 등록하기 - AWS Docs
- EB에 SpringBoot 배포(1) - EB 기본 세팅 - Velog
- 1. Github Action & AWS Beanstalk 배포하기 - Github Action으로 빌드하기 - 향로님 블로그
- 2. Github Action & AWS Beanstalk 배포하기 - profile=local로 배포하기 - 향로님 블로그