Spring Boot + Github Action + CodeDeploy (CI / Cd)

이진석·2022년 11월 14일
0

개발 환경

먼저 Spring boot 2.7.5, 서버는 AWS EC2 ubuntu 20.04를 사용했고 AWS S3, Codedeploy 통해서 CI / CD를 구현했다.
간단하게 설명하자면 github action에서 설정한 작업, 즉 메인에 푸쉬되거나 메인에 대한 PR이 발생하면 S3 버켓으로 프로젝트 파일을 전달하고 action에 의해서 CodeDeploy가 실행되면서 해당 버켓의 파일을 가져오고 연결된 EC2 서버로 Deploy 하게 된다.

Github Action

Github repository로 이동하여 action 탭에 들어가면 아래와 같이 현재 사용하는 언어를 감지하여 제안을 해준다. 기본적으로 Spring boot & Gradle 환경이기 때문에 Java with Gradle을 선택하면 되지만 이번에는 위쪽에 파란색으로 있는 set up workflow yourself를 클릭하여 아예 비어있는 workflow를 만들었다.

yml 파일에 아래와 같이 작성

name: wef server CI/CD

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

env:
  S3_BUCKET_NAME: test332-bucket

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'

        ## application.properties 파일 생성
    - name: make application.properties
      run: |
        echo ">> mkdir & touch"
        mkdir -p ./src/main/resources
        cd ./src/main/resources
        touch ./application.properties
        echo ">> copy application.properties"
        echo "${{ secrets.PROPERTIES }}" >> ./application.properties


    - name: Grant execute permission for gradlew
      run: chmod +x gradlew
      shell: bash

    - name: Build with Gradle
      run: ./gradlew build
      shell: bash

    - name: Make zip file
      run: zip -r ./wef.zip .
      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 ./wef.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 wef
        --deployment-group-name wef-group
        --file-exists-behavior OVERWRITE 
        --s3-location bucket=test332-bucket,bundleType=zip,key=wef.zip
        --region ap-northeast-2

주의할 점은 application.properties를 repo에 올리지 않기 때문에 secret에서 따로 입력해주어야 한다. 마찬가지로 AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY도 secret에서 관리하는데 어떤 값을 넣어야하는지는 아래에서 설명.

workflow를 작성했다면 다음으로 빌드된 파일을 저장할 AWS S3 버켓 연동이 필요하다.

먼저 AWS IAM으로 이동하여 사용자 추가를 진행한다.

위와 같이 임의의 사용자 이름을 입력하고 아래 엑세스 키 - 프로그래밍 방식 엑세스에 체크한 다음 권한 부분으로 넘어간다.

권한 설정에서는 위와 같이 기존 정책 직접 연결을 클릭한 다음 AmazonS3FullAccess, AWSCodeDeployFullAccess를 선택한 다음 태그 설정으로 넘어간다.

태그 부분은 선택 사항으로 입력하지 않고 넘어가도 된다.

그러면 위와 같이 사용자가 만들어지는데 여기에서 엑세스 키 ID를 repository secret의 AWS_ACCESS_KEY_ID, 비밀 엑세스 키를 AWS_SECRET_KEY에 입력하면 된다.

그럼 다음으로 실제 파일이 저장될 S3 버켓을 만들어야한다.

사용할 버켓의 이름을 입력해주는데 버켓 이름은 버켓 이름 지정 규칙에 따라서 정해준다.

그리고 버켓의 퍼블릭 엑세스 차단 설정 같은 경우에는 우리가 IAM을 통해 엑세스하기 때문에 그 외에 다른 모든 엑세스는 차단해준다.

참고로 버켓 이름은 workflow에서 S3_BUCKET_NAME : 이부분에 입력한다.

이제 S3에 파일 업로드하는 부분까지 진행되었으며 다음으로는 CodeDeploy를 통해 EC2 서버에 배포하는 작업을 진행해보자.

먼저 CodeDeploy와 EC2를 연동하기 위해서는 AWS 내부에서의 접근 관련된 역할을 만들어주어야 한다.

위와 같이 IAM에서 역할 탭으로 들어가 역할 만들기를 클릭한다.

AWS 서비스를 선택하고 아래에 EC2를 선택한 후 다음 버튼을 누른다.

권한 부분에서 위와 같이 AmazonEC2RoleforAWSCodeDeploy를 선택한 후 다음 버튼을 누른다.

다음으로 역할 이름을 입력한 후 역할 생성 버튼을 누른다.

이제 생성한 역할을 EC2 서버에 등록해야 하기 때문에 먼저 해당 EC2 인스턴스로 이동한 다음 인스턴스에 체크한 후 상단 작업에서 보안 -> IAM 역할 수정을 클릭한다.

위와 같이 생성한 역할을 EC2 인스턴스에 등록한 다음 아래 역할 업데이트 버튼을 클릭한다.

이제 EC2 서버에 CodeDeploy를 설치해야 하는데 먼저 EC2 인스턴스에 접속하여 아래 명령어를 실행해준다. (ubuntu 16.04 이상)

sudo apt update

sudo apt install ruby-full

sudo apt install wget

설치가 다 되면 cd /home/ubuntu 명령어 사용하여 ubuntu 디렉토리로 이동한 다음 아래 명령어를 차례대로 실행한다.

aws s3 cp s3://aws-codedeploy-ap-northeast-2/latest/install . --region ap-northeast-2
chmod +x ./install
sudo ./install auto > /tmp/logfile (ubuntu 20.04 version)

여기까지 진행한 다음 정상적으로 CodeDeploy가 설치되었는지 확인한다.

sudo service codedeploy-agent status

정상적으로 실행되었다면 위와 같이 active(running) 화면이 나타난다. 만약 실행중이지 않다는 메시지가 나올 경우에는

sudo service codedeploy-agent start 명령어를 실행한다.

이제 다음으로 CodeDeploy를 설정할 차례이다.

AWS CodeDeploy로 이동하여 애플리케이션 생성 버튼을 누른 다음 위와 같은 화면이 나오면 임의의 애플리케이션 이름을 입력한 다음 컴퓨팅 플랫폼을 EC2/온프레미스로 선택한 후 애플리케이션 생성 버튼을 누른다.

다음으로는 배포 그룹 생성을 바로 이어서 진행한다.

위와 같이 EC2 인스턴스를 체크한 다음 키 값에 인스턴스 이름을 선택해준다.

기존에 생성한 로드밸런서 그룹이 있다면 활성화하지만 일단 없기 때문에 활성화하지 않고 넘어간다.

다음으로는 프로젝트에 appspec.yml 파일을 아래와 같이 정의해준다.

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

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

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

마지막으로 ApplicationStart 이벤트에서 실행될 deploy.sh 스크립트를 만들어준다.

#!/usr/bin/env bash

JAR_REPOSITORY=/home/ubuntu/app/build/libs
REPOSITORY=/home/ubuntu/app/
JAR_NAME=$(ls -tr $JAR_REPOSITORY/Backend-0.0.1-SNAPSHOT.jar | tail -n 1)

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

CURRENT_PID=$(pgrep -f $JAR_NAME)

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

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

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

echo "> JAR NAME: $JAR_NAME"

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

chmod +x $JAR_NAME

echo "> $JAR_NAME 실행"
# -Duser.timezone=Asia/Seoul
nohup java -jar $JAR_NAME >> $REPOSITORY/nohup.out 2>&1 &

이후에 메인에 푸쉬되거나 PR이 올 때마다 Github Action이 수행되고 배포까지 되는 것을 확인할 수 있다.

참고자료

  1. https://docs.aws.amazon.com/ko_kr/codedeploy/latest/userguide/codedeploy-agent-operations-install-ubuntu.html
  2. https://stalker5217.netlify.app/devops/github-action-aws-ci-cd-3/
profile
고양이 두마리의 집사이자 행복 코딩을 추구하는 주니어 개발자입니다!

0개의 댓글

관련 채용 정보