우주먼지
article thumbnail

💡 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

 

CI 성공
S3로 빌드 결과물 자동 전송 완료


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 설치


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

Code Deploy Agent 설치


IAM Role 생성

  • AmazonS3FullAccess
  • AmazonEC2RoleforAWSCodeDeploy
  • AWSCodeDeployRole
  • AmazonSSMFullAccess
  • AmazonEC2FullAccess
  • IAM Role 과 IAM UserGroup의 태그 연결하기

 

추가한 정책 목록

 

신뢰정책에 내 리전의 codedeploy 서비스 추가

 

EC2에 IAM Role 연결


 EC2 < - > RDS 연결

RDS 생성
EC2내에 mariadb 설치 후 RDS Endpoint 연결

 

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
profile

우주먼지

@o귤o

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!

검색 태그