본문 바로가기
Spring Boot

[SpringBoot] Github Action으로 AWS EC2 자동 빌드/배포하기(CI/CD)

by 디토20 2022. 5. 4.
반응형

 

 

 

[SpringBoot] Github Action으로 AWS EC2 자동 빌드/배포하기(CI/CD)

 

 

빗썸테크아카데미의 강의가 끝나고

팀프로젝트가 시작되었는데, 개발에 앞서 우선 aws에 배포해서

Hello world를 먼저 찍어보고 개발을 하기로 했다.

 

저번에 CI/CD의 아름다움을 맛본 나는

이번 프로젝트에서 미리 구축해놓고 사용하기로 했다.

 

 

지난번에는 Jenkins를 이용해 springboot를 로컬에 자동 빌드, 배포를 해보았는데

이번에는 Github Action을 이용해 AWS에 CI/CD를 해보려고 한다.

 

Github Action도, AWS도 전부 처음이라 두근두근해

 

 

spring boot의 jar 파일은 aws에 바로 올릴수 없기 때문에,

zip으로 압축해서 aws의 s3에 올린 후,

ec2에서 s3에 있는 zip 파일을 가져다가 압축해제하고 자동 배포를 하는

파이프라인을 구축해보자.

 

 

 

 

 


 

 

1. 깃허브 액션 생성

helloworld가 출력되는 가벼운 spring boot 프로젝트를 만들어

깃허브 리파지토리와 연동한 후,

해당 리파지토리의 set up a workflow yourself를 눌러서

main.yml 파일을 생성한다.

 

 

 

main.yml

name: coinTalk chatRoom server CI/CD

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

env:
  S3_BUCKET_NAME: cointalk-deploy

jobs:
  build:

    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v2
    
    - name: Set up JDK 11
      uses: actions/setup-java@v2
      with:
        java-version: '11'
        distribution: 'temurin'
        
    - name: Grant execute permission for gradlew
      run: chmod +x gradlew
    
    - name: Build with Gradle
      run: ./gradlew clean build

main.yml에 위의 코드를 입력 후 커밋

 

 

 

 

약 1분 30초 후 Actions에서 성공적으로 build 한 것을 확인 할 수 있다.

github actions를 이용한 자동빌드 성공!

 

 

혹시 몰라 코드를 수정하고 push 해보았다.

성공한 결과를 확인!

 

 

 

 

 

 

 

 

 

2. IAM 사용자 생성

IAM 사용자 - 사용자 추가를 클릭

 

 

사용자의 이름을 지정한 뒤, 액세스 유형을 선택하고 다음 클릭

 

기존 정책 직접 연결을 체크하고

 

AmazonEC2FullAccess

AmazonS3FullAccess

AWSCodeDeployFullAccess

 

세가지를 추가

 

 

 

그 다음 확인을 계속 진행하면

위와 같은 액세스 키 ID비밀 액세스 키를 얻을 수 있다.

(처음에 사용자가 ID고, 액세스 키 ID가 비밀번호인줄 알고 삽질함)

 

 

 

그 후 깃허브 - 리파지토리 - Settings - Secrets - Actions

New repository secret을 눌러

아래와 같이 추가

 

AWS_ACCESS_KEY_ID : 위에서 얻은 액세스 키 ID

AWS_SECRET_ACCESS_KEY : 위에서 얻은 비밀 액세스 키

 

 

 

 

 

 

 

3. S3 생성

 

버킷 이름을 적고

우리는 IAM에서 만든 사용자로 S3FullAccess를 얻을 수 있기 때문에

 보안을 위해 모든 퍼블릭 액세스를 차단한 후 생성

 

그 후 main.yml을 수정

 

 

main.yml

name: coinTalk chatRoom server CI/CD

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

env:
  S3_BUCKET_NAME: cointalk-deploy

jobs:
  build:

    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v2
    
    - name: Set up JDK 11
      uses: actions/setup-java@v2
      with:
        java-version: '11'
        distribution: 'temurin'
        
    - name: Grant execute permission for gradlew
      run: chmod +x gradlew
    
    - name: Build with Gradle
      run: ./gradlew clean build
      
    # 디렉토리 생성
    - name: Make Directory
      run: mkdir -p deploy
        
    # Jar 파일 복사
    - name: Copy Jar
      run: cp ./build/libs/*.jar ./deploy

    - name: Make zip file
      run: zip -r ./coinTalk.zip ./deploy
      shell: bash

    - name: Configure AWS credentials
      uses: aws-actions/configure-aws-credentials@v1
      with:
        aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
        aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
        aws-region: ap-northeast-2

    - name: Upload to S3
      run: aws s3 cp --region ap-northeast-2 ./coinTalk.zip s3://$S3_BUCKET_NAME/

파일을 압축하고, s3에 업로드 하는 내용을 추가 및 커밋

 

 

 

약 2분 후에 S3에 zip 파일이 잘 올라간 것을 확인 할 수 있다.

 

 

 

 

 

 

 

 

 

4. IAM 역할 생성

1) EC2용 역할

Deploy를 위해 IAM 역할을 만들어 준다.

IAM로 들어가서 역할 - 역할만들기를 클릭

 

 

 

aws 서비스 - EC2 선택

 

 

 

권한 정책에서 아래 2가지를 검색해 체크해서 추가

AmazonS3FullAccess

AWSCodeDeployFullAccess

 

 

 

역할 이름을 부여해주고, 권한이 추가된 것을 확인 한 후 역할을 생성

 

 

 

 

2) 애플리케이션 그룹용 역할

 

IAM로 들어가서 역할 - 역할만들기를 클릭

 

 

 

사용사례를 CodeDeploy로 선택해 준 후

다른 부분은 건드리지 않고,

역할 이름을 정한 후 역할을 생성

 

 

처음에 애플리케이션 그룹에 서비스 역할이 안떠서

삽질을 많이 했었는데...

저는 그 당시 다른 방법으로 수정을 했지만

찾아보니 이 방법이 훨씬 깔끔해보여 작성 :)

 

 

 

 

5. EC2 생성

우측 상단 지역을 서울로 클릭하고, 인스턴스 시작을 클릭

 

 

 

인스턴스의 이름을 정하고, 아래에서 ubuntu를 선택해 준 뒤

(ubuntu 20.04 추천. 22.04 사용시 ec2에서 여러 ruby 호환 에러 남)

 

인스턴스 유형은 t2.micro를 선택하고, 새 키페어를 생성

 

 

키페어의 이름을 입력하고 키페어 생성. 키페어 생성시 다운로드 된 pem키는 잘 보관해 둔다.

인스턴스를 생성

 

 

 

인스턴스에서 오른쪽 버튼 클릭 후 보안 - IAM 역할 수정

 

 

아까 만들어둔 ec2용 역할을 선택한 후 저장

 

 

 

 

 

6. EC2 접속 후 셋팅

아까 저장해두었던 pem 키를 이용해 EC2인스턴스에 접속

나는 윈도우 사용자라 아래 링크를 참고해서 진행했다.

 

 

https://wookim789.tistory.com/34

 

 

 

ssh로 ec2에 잘 접속했다면

EC2 에서 /home/ubuntu에 app 디렉토리를 하나 생성

 

 

 

그후 아래 커맨드 입력

sudo apt update
sudo apt install ruby-full
sudo apt install wget

cd /home/ubuntu

sudo apt install awscli
aws s3 cp s3://aws-codedeploy-ap-northeast-2/latest/install . --region ap-northeast-2

chmod +x ./install
sudo ./install auto

# 아래 코드로 설치 확인
sudo service codedeploy-agent status

 

설치가 잘된 경우 

다음과 같은 코드를 볼수있다.

 

처음에 아무생각 없이 ubuntu 최신 버전으로 ec2를 생성했다가 ruby 호환 오류가 나서 열심히 삽질하다가

지우고 새로 까는게 빠르다고 판단되어 결국 ec2 지우고 ubuntu 버전 한단계 내려서 설치했다.

 

 

그 다음 jdk 설치

# jdk 11버전 설치
sudo apt-get install openjdk-11-jdk

# java 설치 확인
java

각자 프로젝트 버전에 맞는 jdk를 설치해주면 된다.

 

 

 

 

 

7. CodeDeploy

 

CodeDeploy - 애플리케이션 - 애플리케이션 생성

 

 

 

 

 

배포그룹 이름을 입력하고

서비스 역할에서

위에서 생성한

애플리케이션 그룹용 역할을 클릭

 

 

환경구성에서 EC2 인스턴스 클릭 후 

배포할 EC2 선택

그룹을 생성

 

 

 

8. 자동 배포를 위한 스크립트 추가

1) appspec.yml 설정

version: 0.0
os: linux
files:
  - source: /
    destination: /home/ubuntu/app/
    overwrite: yes

permissions:
  - object: /
    pattern: "**"
    owner: ubuntu
    group: ubuntu

hooks:
  ApplicationStart:
    - location: deploy.sh
      timeout: 60
      runas: ubuntu

root 바로 아래 (build.gradle과 같은 위치)에 appspec.yml을 생성하고 위의 코드를 작성

 

2) deploy.sh 생성

#!/usr/bin/env bash

REPOSITORY=/home/ubuntu/app

echo "> 현재 구동 중인 애플리케이션 pid 확인"

CURRENT_PID=$(pgrep -fla java | grep hayan | awk '{print $1}')

echo "현재 구동 중인 애플리케이션 pid: $CURRENT_PID"

if [ -z "$CURRENT_PID" ]; then
  echo "현재 구동 중인 애플리케이션이 없으므로 종료하지 않습니다."
else
  echo "> kill -15 $CURRENT_PID"
  kill -15 $CURRENT_PID
  sleep 5
fi

echo "> 새 애플리케이션 배포"

JAR_NAME=$(ls -tr $REPOSITORY/*SNAPSHOT.jar | tail -n 1)

echo "> JAR NAME: $JAR_NAME"

echo "> $JAR_NAME 에 실행권한 추가"

chmod +x $JAR_NAME

echo "> $JAR_NAME 실행"

nohup java -jar -Duser.timezone=Asia/Seoul $JAR_NAME >> $REPOSITORY/nohup.out 2>&1 &

 

root 바로 아래 (build.gradle과 같은 위치)에 scripts/deploy.sh를 생성하고 위의 코드를 작성

 

 

 

3) main.yml 수정

name: coinTalk chatRoom server CI/CD

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

env:
  S3_BUCKET_NAME: cointalk-deploy

jobs:
  build:

    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v2
    
    - name: Set up JDK 11
      uses: actions/setup-java@v2
      with:
        java-version: '11'
        distribution: 'temurin'
        
    - name: Grant execute permission for gradlew
      run: chmod +x gradlew
    
    - name: Build with Gradle
      run: ./gradlew clean build
      
    # 디렉토리 생성
    - name: Make Directory
      run: mkdir -p deploy
        
    # Jar 파일 복사
    - name: Copy Jar
      run: cp ./build/libs/*.jar ./deploy
      
    # appspec.yml 파일 복사
    - name: Copy appspec.yml
      run: cp appspec.yml ./deploy


    # script files 복사
    - name: Copy script
      run: cp ./scripts/*.sh ./deploy

    - name: Make zip file
      run: zip -r ./coinTalk.zip ./deploy
      shell: bash

    - name: Configure AWS credentials
      uses: aws-actions/configure-aws-credentials@v1
      with:
        aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
        aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
        aws-region: ap-northeast-2

    - name: Upload to S3
      run: aws s3 cp --region ap-northeast-2 ./coinTalk.zip s3://$S3_BUCKET_NAME/



    # Deploy
    - name: Deploy
      env:
        AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
        AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
      run: |
        aws deploy create-deployment \
        --application-name coinTalk[만든 애플리케이션 이름] \
        --deployment-group-name coinTalk-group[만든 애플리케이션 그룹 이름] \
        --file-exists-behavior OVERWRITE \
        --s3-location bucket=cointalk-deploy[S3버킷이름],bundleType=zip,key=coinTalk.zip[S3버킷 속 압축파일] \ 
        --region ap-northeast-2

 

위와 같이 수정하고 커밋

 

 

 

 

 

9. 포트열기

외부에서 EC2로 접근할 수 있도록 포트를 열어줘야 한다.

 

EC2 -> 인스턴스를 클릭 후 아래에서 보안 - 보안그룹을 눌러준다.

 

 

사진은 내가 미리 추가해두었는데, 처음에는 SSH 하나만 보인다.

인바운드 규칙 - 인바운드 규칙 편집

 

 

위와같이 내가 쓰고자 하는 포트를 열어준다 (나는 8080)

 

 

 

저장 후

깃에 test commit을 해주고 난 뒤

EC2 -> 인스턴스 클릭 -> 퍼블릭 IPv4:port 로 접속하면

 

헬로 월드를 만날수 있다!!

 

 

퍼블릭 IP:port

퍼블릭주소:port

둘다 가능

 

 

팀원들한테 자랑하러가야지 ~.~

728x90
반응형

댓글