[CI/CD] Github Actions를 이용한 배포 자동화

bagt13·2022년 12월 11일
6

AWS

목록 보기
2/4

GitHub Actions란?

Github가 공식적으로 제공하는 빌드, 테스트 및 배포 파이프라인을 자동화할 수 있는 CI/CD 플랫폼

repository에서 PR이나 push 같은 이벤트(event)를 트리거(trigger)로 github 작업 workflow를 구성할 수 있다. workflow는 하나 이상의 작업이 실행되는 자동화 프로세스로, 각 작업은 자체 가상 머신 또는 컨테이너 내부에서 실행된다.

workflow는 yml파일에 의해 구성되며, 테스트, 배포 등 기능에 따라 여러 개의 workflow도 만들 수 있다. 생성된 workflow는 .github/workflows 디렉토리 이하에 위치한다.


배포 Flow

  • 설정 파일(.yml)에 명시된 main branch로의 push를 trigger로 Github Actions가 실행되도록 구성한다.

주의 사항

  • Pulbic Repository여야 무료로 사용할 수 있다.
  • AWS CLICode Deploy Agent가 EC2에 설치되어 있어야 한다.
  • S3 버킷이 생성되어 있어야 한다.

리소스 설정하기

Github Actions 생성하기

  1. 프로젝트 repository -> Actions로 이동해 workflow를 설정한다.

set up a workflow yourself 를 클릭하여 빈 yml 설정파일로 workflow를 설정할 수 있고, 추천 workflow 구성(Java with Gradle 등)을 선택하여 진행할 수 있다.

  1. Start Commit으로 workflow를 생성하면, gradle.yml 파일이 생성됨과 동시에 workflow에 작성되어있는 trigger(main으로 push)로 인해 Github Actions가 실행된다.

Actions 탭에서 생성된 워크플로의 각 단계별 진행 상황을 확인할 수 있으며, 진행/성공/실패 여부는 repository에서 최근 commit 내역과 함께 표시된다.


Github Actions 수정

이번엔 생성한 S3 버킷에 프로젝트 빌드 결과물을 전송해야 한다.

Github Actions에서 workflow를 실행하는 과정에서 access key가 필요하지만, 공개되면 보안 이슈가 발생할 수 있다. 따라서 Github Secret을 이용해 access key 값을 저장한 후 사용한다.

1. Github Secret 등록하기

1-1. Repository -> Settings > Secrets > Actions 탭으로 이동한 후 New repository secret를 클릭한다.

1-2. Name-Value에 IAM User 생성 시 볼 수 있는 Access Key ID 값과, 비밀 access key 값을 각각 저장합니다.

  • 이는 gradle.yml에서 secret 변수를 불러오는 부분과 연결된다.

2. Github Action 설정 파일 수정하기

설정한 Secret을 반영하기 위해 기존의 gradle.yml 파일에 하단에 다음 코드를 추가한다.

gradle.yml

name: Java CI with Gradle

on:
  push:
    branches: [ "main" ]

permissions:
  contents: read

jobs:
  build:

    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v3
    - name: Set up JDK 11
      uses: actions/setup-java@v3
      with:
        java-version: '11'
        distribution: 'temurin'
    - name: Build with Gradle
      uses: gradle/gradle-build-action@67421db6bd0bf253fb4bd25b31ebb98943c375e1
      with:
        arguments: build
    
    # build한 후 프로젝트를 압축한다.
    - name: Make zip file
      run: zip -r ./practice-deploy.zip .
      shell: bash
    
    =========================추가된 부분=============================
    
    # Access Key와 Secret Access Key를 통해 권한을 확인한다.
    # 아래 코드에 Access Key와 Secret Key를 직접 작성하지 않는다.
    - name: Configure AWS credentials
      uses: aws-actions/configure-aws-credentials@v1
      with:
        aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY }} # 등록한 Github Secret이 자동으로 불려온다.
        aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} # 등록한 Github Secret이 자동으로 불려온다.
        aws-region: ap-northeast-2
    

3. build 파일을 S3에 전달하기 위한 설정

  • 상단에 아래 코드 추가
env:
  S3_BUCKET_NAME: be-0-name
  • 하단에 아래 코드 추가
    # 압축한 프로젝트를 S3로 전송한다.
    - name: Upload to S3
      run: aws s3 cp --region ap-northeast-2 ./practice-deploy.zip s3://$S3_BUCKET_NAME/practice-deploy.zip

변경 사항을 commit-push 하면, workflow가 진행되고, S3 버킷에 압축 파일이 전송되었음을 확인할 수 있다.


build 파일 배포 및 실행

프로젝트의 빌드 결과를 S3 버킷에 저장하는데 까지 진행했고, 이제 저장된 빌드 결과물을 EC2로 배포하는 과정을 진행한다.


CodeDeploy 설정

  1. CodeDeploy -> 배포 -> 애플리케이션 생성을 클릭한다.

  2. 애플리케이션 이름을 작성하고, 컴퓨팅 플랫폼은 EC2/온프레미스를 선택한다.

    애플리케이션 이름의 경우 Github Actions workflow에 작성할 것이기 때문에 규칙에 맞게 작성해야 한다.

  3. 생성 완료 후, 배포 그룹을 생성한다.

    배포 그룹은 방금 전 생성한 애플리케이션에 생성되어야 하며, 배포 그룹 이름 역시 Github Actions workflow에 작성이 필요하기 때문에, 애플리케이션과 구분할 수 있도록 규칙에 맞게 이름을 작성해야 한다.

    CodeDeploy 의 권한 부여를 위한 IAM 역할을 생성되어있다면 선택하면 되고, 없다면 생성 후 선택한다.

  4. 환경 구성 파트에서는 EC2 인스턴스 태그를 이용해 배포 그룹 환경을 구성한다.


.yml 파일 설정

  1. 프로젝트 디렉토리 root 경로appspec.yml 파일을 생성한다. (Code Deploy의 작동과 연결)

appspec.yml

version: 0.0
os: linux
files:
  - source:  /
    destination: /home/ubuntu/action  # 이 디렉토리 내에 배포가 진행된다
    overwrite: yes

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

hooks:
  ApplicationStart:
    - location: scripts/deploy.sh  #최상위 디렉토리의 script 폴더 내의 shell script가 실행된다.
      timeout: 60
      runas: ubuntu
  1. 마찬가지로 root 경로에 scripts 디렉토리를 생성한 후 디렉토리 내부에 deploy.sh 파일을 생성한다. (EC2 배포 진행 상황 별 로그를 기록하고 새로 배포된 빌드 파일을 실행한다)

deploy.sh

!/bin/bash
BUILD_JAR=$(ls /home/ubuntu/action/build/libs/practice-githubAction-deploy-0.0.1-SNAPSHOT.jar)
JAR_NAME=$(basename $BUILD_JAR)

echo "> 현재 시간: $(date)" >> /home/ubuntu/action/deploy.log

echo "> build 파일명: $JAR_NAME" >> /home/ubuntu/action/deploy.log

echo "> build 파일 복사" >> /home/ubuntu/action/deploy.log
DEPLOY_PATH=/home/ubuntu/action/
cp $BUILD_JAR $DEPLOY_PATH

echo "> 현재 실행중인 애플리케이션 pid 확인" >> /home/ubuntu/action/deploy.log
CURRENT_PID=$(pgrep -f $JAR_NAME)

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


DEPLOY_JAR=$DEPLOY_PATH$JAR_NAME
echo "> DEPLOY_JAR 배포"    >> /home/ubuntu/action/deploy.log
sudo nohup java -jar $DEPLOY_JAR >> /home/ubuntu/deploy.log 2>/home/ubuntu/action/deploy_err.log &

Github Actions - Code Deploy 연결하기

이제 모든 환경 세팅이 완료되었고, Github Actions workflow를 수정하여 배포 자동화를 구성한다. gradle.yml 하단에 Code Deploy 배포 명령을 추가하면 된다.

gradle.yml 추가

  # CodeDeploy에게 배포 명령을 내린다.
    - name: Code Deploy
      run: >
        aws deploy create-deployment --application-name [Code Deploy 애플리케이션 이름]
        --deployment-config-name CodeDeployDefault.AllAtOnce
        --deployment-group-name [Code Deploy 배포 그룹 이름]
        --s3-location bucket=$S3_BUCKET_NAME,bundleType=zip,key=practice-deploy.zip

CodeDeploy 설정하며 작성한 애플리케이션의 이름, 배포 그룹의 이름을 표시된 곳에 각각 작성한다.

수정을 마치고 repository에 push 하면 Github Actions가 실행된다.


배포 결과 및 로그 확인하기

1. 배포 결과 확인하기

EC2의 주소로 접속해 배포가 성공되었는지 확인한다.

또한 EC2 터미널을 통해 appspec.yml과 deploy.sh에 작성한대로 action 디렉토리 내에 빌드 파일이 이동했고, ps -ef | grep java로 해당 빌드 파일이 실행 중인지 확인할 수 있다.

2. 배포 로그 확인하기

이전에 생성한 deploy.sh에는 배포가 진행될 때마다 상황을 기록하도록 작성 되어있다.

배포를 마치면 action 디렉토리 내에 두 개의 로그 파일이 생성된다.

EC2 인스턴스에서의 빌드 과정은 deploy.log 파일에, 빌드 파일을 정상적으로 실행하지 못한다면 deploy_err.log 파일에 기록된다.

profile
주니어 백엔드 개발자입니다😄

0개의 댓글