조급하면 모래성이 될뿐

CodeDeploy 적용기 본문

TroubleShooting/데브코스

CodeDeploy 적용기

Pawer0223 2022. 7. 26. 13:20

Why?


  • 처음 프런트팀과 협업을 하기 전 완료된 API를 실시간으로 공유하고 싶었다. 
  • 완료된 API를 프론트에서도 바로 호출해볼 수 있으면 문제도 더 빨리 잡을 수 있고, 서로 생산성도 높일 수 있다고 생각했다.

 

HOW?


  • CI는 GithubActions를 사용했고, CD방식은 크게 2가지 중에 고민했다.

1. Docker 이미지를 만들고, EC2에서 이미지를 받아와서 실행.

 

2. S3에 Jar파일을 올리고, AWS의 CodeDeploy를 통해 배포한다.

  • 결과적으로 2번을 선택했다. 두 방식의 장, 단점을 찾아보았을 때 모두 하지 마라!.. 또는 이건 쓰면 안 된다! 이런 내용은 딱히 못 찾았고, Docker에 익숙하지 않았기 때문에 2번을 선택했다.
    • 간단하게 찾아보았을 때 1번 방식은 별도의 메모리 공간(S3)이 필요하지 않다는 장점이 있지만, 외부 시스템(Docker)을 사용하기 때문에 2번보다 속도적인 측면은 떨어진다고 한다.
    • 참조
  • 추가적으로 Beanstalk를 사용하지 않은 이유는, 팀원들과 논의하면서 좀 더 low 하게 배포 환경을 구성하자는 의견이 많았고, 지금 단계에서는 불편함을 경험해보는 것도 좋을 것 같았다.

 

적용 과정


  • 큰 흐름은 아래와 같다.
  • GithubActions에서 스크립트가 수행된다.
name: Tenwonmoa CI-CD with Gradle

on:
  push:
    branches: [ "main", "develop" ]
  pull_request:
    branches: [ "main", "develop" ]

# 변수 설정
env:
  S3_BUCKET_NAME: tenwonmoa-cd
  CODE_DEPLOY_APPLICATION_NAME: tenwonmoa-app
  CODE_DEPLOY_DEPLOYMENT_GROUP_NAME: tenwonmoa-deploy-group
  DEPLOY_ZIP_FILE: tenwonmoa-boot-service.zip

permissions:
  contents: read

jobs:
  tenwonmoa-ci-cd:

    runs-on: ubuntu-latest

    steps:
      - name: Checkout repository and submodules
        uses: actions/checkout@v2
        with:
          token: ${{ secrets.CI_ACCESS_TOKEN }}
          submodules: true

      - uses: actions/checkout@v3
      - name: Set up JDK 11
        uses: actions/setup-java@v3
        with:
          java-version: '11'
          distribution: 'temurin'

      - name: build docker-compose
        run: docker-compose up -d

      - name: Build with Gradle
        uses: gradle/gradle-build-action@67421db6bd0bf253fb4bd25b31ebb98943c375e1
        with:
          arguments: build

      - name: Make zip file
        run: |
          mkdir -p before-deploy/
          cp appspec.yml before-deploy/
          cp scripts/*.sh before-deploy/
          cp build/libs/*.jar before-deploy/
          cp docker-compose-dev.yml before-deploy/
          cd before-deploy && zip -r before-deploy *
          cd ../ && mkdir -p deploy
          mv before-deploy/before-deploy.zip deploy/$DEPLOY_ZIP_FILE

      - 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_ID }}
          aws-region: ${{ secrets.AWS_REGION }}

      - name: Upload to S3
        run: aws s3 cp --region ${{ secrets.AWS_REGION }} ./deploy/$DEPLOY_ZIP_FILE s3://$S3_BUCKET_NAME/$DEPLOY_ZIP_FILE

      - name: Code Deploy
        run: |
          aws deploy create-deployment \
          --deployment-config-name CodeDeployDefault.AllAtOnce \
          --application-name ${{ env.CODE_DEPLOY_APPLICATION_NAME }} \
          --deployment-group-name ${{ env.CODE_DEPLOY_DEPLOYMENT_GROUP_NAME }} \
          --s3-location bucket=$S3_BUCKET_NAME,bundleType=zip,key=$DEPLOY_ZIP_FILE
  • submodule위해 checkout
  • build
  • jar파일과 배포를 위한 파일을 zip 파일로 묶는다
    • deploy.sh:  애플리케이션 수행을 위한 스크립트
    • appspec.yml: AWS CodeDeploy에서 읽고 처리하기 위한 파일, 크게 배포될 위치(destination)와 실행될 스크립트를 지정한다.
  • zip 파일을 S3로 업로드한다.
    • 이때, S3접속을 위한 IAM계정 정보는 github에서 Repository secrets에 등록해주어야 한다.
    • IAM계정은 업로드될 S3에 접근할 수 있는 권한이 필요하다.

  • CodeDeploy의 새로운 배포를 생성.

 

이후에는 CodeDeploy에서 appspec.yml 파일을 해석하여 배포를 진행한다. 배포가 진행되면서 deploy.sh 스크립트가 수행된다.

 

deploy.sh은 아래와 같다.

#!/bin/bash

REPOSITORY="/home/ubuntu/app"
PROJECT_NAME="tenwonmoa"

echo "> Build 파일 복사"

cp $REPOSITORY/zip/*.jar $REPOSITORY/

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

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

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/*.jar | tail -n 1)

echo "> JAR Name: $JAR_NAME"

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

sudo chmod +x $JAR_NAME

echo "> $JAR_NAME 실행"

## docker 실행해야 함.

nohup java -jar -Dspring.profiles.active=dev $JAR_NAME --server.port=8080 \
$JAR_NAME > $REPOSITORY/nohup.out 2>&1 &

 

A~Z 설명보다는 큰 그림으로 기록했다.

 

CodeDeploy를 적용하면서 아래 블로그와 스프링 부트와 AWS로 혼자 구현하는 웹 서비스 책을 많이 참조했다 !

참조

반응형