💡 Auto Deployment
준비사항
1. Github Actions 생성
2. S3 버킷 & 정적 웹 호스팅 비활성화 & Public Access 차단 해제
3. AWS Code Deploy
4. EC2 & t2.micro Free Tier Memory 증설( https://root-ca.tistory.com/235 )
5. RDS
Github Actions 생성 & 설정
- java with gradle -> start commit
- repo -> settings - secrets/actions -> new repository secret
- AWS_ACCESS_KEY, AWS_SECRET_ACCESS_KEY 등록
gradle.yml 수정
- Build with Gradle 부분을 설정하여 직접 빌드 방식으로 빌드 진행
- application.yml & data.sql 을 전부 github actions secret으로 넣는 방식으로 진행
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
# This workflow will build a Java project with Gradle and cache/restore any dependencies to improve the workflow execution time
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-gradle
name: Java CI with Gradle
on:
push:
branches: [ "main" ]
permissions:
contents: read
env:
S3_BUCKET_NAME: deploy011-bucket-replicaset
jobs:
build:
defaults:
run:
working-directory: ./server
runs-on: ubuntu-latest
steps:
# 1. Set-Up JDK
- uses: actions/checkout@v3
- name: Set up JDK 11
uses: actions/setup-java@v3
with:
java-version: '11'
distribution: 'temurin'
# 2. init Data 생성
- uses: actions/checkout@v3
- name: create init data
run: |
touch ./src/main/resources/application.yml
echo "${{ secrets.YML }}" > ./src/main/resources/application.yml
touch ./src/main/resources/data.sql
echo "${{ secrets.INIT_DATA }}" > ./src/main/resources/data.sql
- uses: actions/upload-artifact@v3
with:
name: application.yml
path: ./src/main/resources/application.yml
- uses: actions/upload-artifact@v3
with:
name: data.sql
path: ./src/main/resources/data.sql
- name: Run chmod to make gradlew executable
run: chmod +x ./gradlew
working-directory: ./server
# - name: Test Build
# run: ./gradlew test -i
# working-directory: ./server
- name: Build with Gradle
run: ./gradlew build
working-directory: ./server
# - name: Build with Gradle
# uses: gradle/gradle-build-action@67421db6bd0bf253fb4bd25b31ebb98943c375e1
# with:
# arguments: build
- name: Make zip file
run: zip -r ./main.zip .
shell: bash
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_KEY }}
aws-region: ap-northeast-2
- name: Upload to S3
run: aws s3 cp --region ap-northeast-2 ./main.zip s3://$S3_BUCKET_NAME/main.zip
- name: Code Deploy
run: >
aws deploy create-deployment --application-name main
--deployment-config-name CodeDeployDefault.AllAtOnce
--deployment-group-name main-group
--s3-location bucket=$S3_BUCKET_NAME,bundleType=zip,key=main.zip
AWS CodeDeploy & 배포그룹 생성
- --- CodeDeploy --- (인스턴스 내에 CodeDeploy-Agent 설치가 되어있어야함)
- 어플리케이션 - 생성 - 배포그룹 생성
- IAM & Instance Tag 지정, LoadBalancer 비활성화
appspec.yml & deploy.sh 작성
# appspec.yml
version: 0.0
os: linux
files:
- source: /
destination: /root
overwrite: yes
permissions:
- object: /
pattern: "**"
owner: root
group: root
hooks:
ApplicationStart:
- location: scripts/deploy.sh
timeout: 60
runas: root
#!/bin/bash
# deploy.sh
BUILD_JAR=$(ls /root/main/back/build/libs/main-SNAPSHOT.jar)
JAR_NAME=main
# basename = 확장자,경로 전부 삭제하고 파일명만 반환하므로 주석처리
echo "> 현재 시간: $(date)" >> /root/main/back/log/deploy.log
echo "> build 파일명: $JAR_NAME" >> /root/main/back/log/deploy.log
echo "> build 파일 복사" >> /root/main/back/log/deploy.log
DEPLOY_PATH=/root/main/back/build/libs
cp $BUILD_JAR $DEPLOY_PATH
echo "> 현재 실행중인 애플리케이션 pid 확인" >> /root/main/back/log/deploy.log
CURRENT_PID=$(pgrep -f $JAR_NAME)
if [ -z $CURRENT_PID ]
then
echo "> 현재 구동중인 애플리케이션이 없으므로 종료하지 않습니다." >> /root/main/back/log/deploy.log
else
echo "> kill -9 $CURRENT_PID" >> /root/main/back/log/deploy.log
sudo kill -9 $CURRENT_PID
sleep 5
fi
DEPLOY_JAR=$BUILD_JAR
echo "> DEPLOY_JAR 배포" >> /root/main/back/log/deploy.log
cd /root/main/back/log/build/libs
sudo nohup java -jar $DEPLOY_JAR >> /root/main/back/log/deploy.log 2>/root/main/back/log/deploy_err.log &
EC2 인스턴스 생성 (Elastic IP 설정)
보안그룹 포트 오픈
- 3306 - DB Connection Endpoint (Dual Stack 까지 오픈)
- 3000 - React Connection Endpoint 1
- 3001 - React Connection Endpoint 2
- 8080 - Spring Boot Endpoint
- 22 - SSH Endpoint
- 6379 - RDS Endpoint
- 5000 - Docker Private Registry Endpoint
Github SSH Key 등록
EC2 내부 패키지 설치
JDK 설치
- amazon-linux-extra install -y openjdk11
GIT 설치
- yum -y install git
AWS CLI 설치
- curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
- unzip awscliv2.zip
- sudo ./aws/install
CodeDeploy Agent 설치
- yum -y update
- yum -y install gcc (C Compiler)
gpg2 --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB- curl -sSL https://rvm.io/pkuczynski.asc | gpg2 --import - -> import gpg key
- curl -sSL https://get.rvm.io | bash -s stable (rvm 설치 스크립트)
- source /etc/profile.d/rvm.sh (시스템 환경변수 & rvm 정보 업데이트)
- rvm reload
- rvm requirements run (rvm 의존성 패키지 설치)
- rvm list known
- rvm install [version] (2.7)
- rvm list
- rvm use [version] --default
- ruby -v
- gem install aws-sdk (Ruby용 sdk 설치)
- wget https://aws-codedeploy-ap-northeast-2.s3.ap-northeast-2.amazonaws.com/latest/install
- chmod +x install
- ./install auto > /tmp/logfile
- service codedeploy-agent status
IAM Role 생성
- AmazonS3FullAccess
- AmazonEC2RoleforAWSCodeDeploy
- AWSCodeDeployRole
- AmazonSSMFullAccess
- AmazonEC2FullAccess
- IAM Role 과 IAM UserGroup의 태그 연결하기
EC2 < - > RDS 연결
- -- Mysql 설치 ---
- yum localinstall https://dev.mysql.com/get/mysql80-community-release-el7-3.noarch.rpm
- rpm --import https://repo.mysql.com/RPM-GPG-KEY-mysql-2022
- yum -y update
- yum install mysql-community-server
- cat /var/log/mysqld.log | grep 'temporary password’ (임시 root PW 확인)
- mysql -u root --host [RDS-Endpoint] -P [port] -p
Application Settings
- build.gradle
runtimeOnly 'com.mysql:mysql-connector-j'
- application.yml
- 첫 배포시 ddl-auto = create & sql.init.mode = always
- 이후 ddl-auto = none & sql.init.mode = never
server:
port: 8080
servlet:
context-path: /
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://{RDS-endpoint}:3306/{database-name}?serverTimezone=UTC&characterEncoding=UTF-8
username: root
password: pw
data: classpath:data.sql
# url: jdbc:h2:tcp://localhost/~/test
# username: sa
# password:
# driver-class-name: org.h2.Driver
# h2:
# console:
# enabled: true
# path: /h2
jpa:
hibernate:
ddl-auto: create # 애플리케이션 실행 시 기존 테이블 삭제 후 테이블 새로 생성
# 추후 validate나 none으로 변경할 것
show-sql: true # 콘솔창에 sql 출력
properties:
hibernate:
format_sql: true # sql 예쁘게 출력
default_batch_fetch_size: 500 # 일대다 컬렉션 조회 시 성능 최적화
# 쿼리에서 조건문 in절로 수행하게됨, n번 쿼리 수행 -> 1번 쿼리에서 수행(n개를 파라미터로 넣어줌)
# DB와 애플리케이션 부하를 고려해서 개수를 설정할 것
# oracle의 경우 최대 1000개
# dialect: org.hibernate.dialect.MySQLDialect
open-in-view: true
# 영속성 컨텍스트의 생존 범위를 트랜잭션 범위로 한정
# 기본값 true -> View 랜더링 또는 API 요청일 경우 클라이언트 응답까지 영속성 컨텍스트 생존
# false 설정 시 -> 생존 범위가 트랜잭션 범위로 줄어들게 됨
# -> 컨트롤러에서 지연로딩으로 연관된 엔티티를 가져오려고 하면 에러 발생
# 영속성 컨텍스트를 오래 유지하면 DB Connection도 오래 갖고 있으므로 DB Connection이 부족할 수 있음
# -> 실시간 트래픽이 중요한 API 애플리케이션에서는 false로 유지할 것
defer-datasource-initialization: true # 스프링부트 2.5버전 이상 사용 시 data.sql 사용
database: mysql
database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
sql:
init:
mode: never # 모든 데이터베이스에 sql 스크립트를 동작
data-locations: classpath:data.sql
servlet:
multipart:
max-file-size: 10MB # 파일 업로드 요청 시 하나의 파일 크기를 10MB 제한
max-request-size: 100MB # 파일 업로드 요청 시 모든 파일 크기합을 100MB 제한
mvc:
pathmatch:
matching-strategy: ant_path_matcher
# swagger 사용을 위한 설정
logging:
level:
org.hibernate.type: debug # 콘솔창에 조건에 바인딩되는 값 및 조회 결과 출력
package com.server.seb41_main_11: debug # todo 패키지 수정
# spring cloud openfeign(외부 API 호출을 쉽게 할 수 있도록 도와줌)
# 의 로그를 보기 위해서 프로젝트 루트 패키지 기준으로 debug 설정
feign:
client:
config:
default:
connectTimeout: 5000
readTimeout: 5000
# 3-way-handshake 과정의 시간 설정(5초)
# 연결은 됐는데 요청한 서버에서 응답이 5초내로 오지 않으면 에러 발생(readTimeout)
배포 성공 및 Postman 테스트 완료
'Project > Main Project' 카테고리의 다른 글
💻 기능 개발 - 결제 (0) | 2023.01.27 |
---|---|
💻 기능 개발 - 프로그램 (0) | 2023.01.27 |
💻 기능 개발 - 상담사 (0) | 2023.01.27 |
💻 기능 개발 - 공지사항 (0) | 2023.01.26 |
💻 기능 개발 - 게시물 (0) | 2023.01.26 |