[Git] GitHub Actions로 AWS에 CI/CD 적용하기

koline·2024년 7월 18일

DevOps

목록 보기
1/3

AWS 시리즈에서 서버에 배포한 프로젝트GitHub Actions를 사용해 CI/CD테스트 자동화를 적용하려고 한다.

1. AWS IAM 계정 생성

배포하려고 하는 서버에 접근할 수 있는 IAM 게정을 생성한다.

참고

2. S3 버킷 생성

빌드된 파일을 업로드할 S3 버킷을 생성한다.

참고

3. Settings > Secrets and variables > Actions

공개되면 안되는 정보 (비밀키 등)를 여기에 입력해준다.

4. IAM 계정 정보 입력

2번에서 발급받은 액세스 키와 비밀 액세스 키를 각각 생성해준다.

5. application.properties 추가

나는 application.properties 내에 포함되어 있는 민감한 정보를 숨기기 위해

.gitignore 파일에 application.properties 파일을 추가해뒀다.

그래서 CI/CD 작업을 위해 build가 실행되기 전에 application.properties 파일을 생성해서 함께 build 될 수 있게 하기 위해 secrets에 함께 작성해줬다.

6. 적용할 repository > Actions

프로젝트에 맞는 항목을 찾아서 configure를 클릭한다.

7. yml 파일 작성

configure를 클릭하면 .github/workflows 디렉토리 하위에 gradle.yml (gradle일 경우) 파일생성 페이지로 넘어가고 기본 구성이 작성되어 있을 것이다.

여기서 이제 필요없는 부분은 지워주고 java 세팅, gradle 세팅, application.properties 파일 생성, 빌드, S3에 업로드 순서로 진행해주면 된다.

    name: Java CI/CD with Gradle
    on:
      push:
        branches: [ "develop", "master" ]
      pull_request:
        branches: [ "develop", "master" ]
    jobs:
      build:
        runs-on: ubuntu-latest
        permissions:
          contents: read

        steps:
        - uses: actions/checkout@v4
        - name: Set up JDK 17
          uses: actions/setup-java@v4
          with:
            java-version: '17'
            distribution: 'temurin'

        - name: Setup Gradle
          uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0

        # application.properties 파일 생성
        - name: Generate Environment Variables File for Production
          run: |
            echo "$APPLICATION_PROPERTIES" >> ./src/main/resources/application.properties
          env:
            APPLICATION_PROPERTIES: ${{ secrets.APPLICATION_PROPERTIES }}

        # gradlew 실행 권한 부여
        - name: Grant execute permission for gradlew
          run: chmod +x gradlew

        # 테스트 Skip 하고 clean build
        - name: Build with Gradle
          run: ./gradlew clean build -x test

        # 디렉토리 생성
        - name: Make Directory
          run: mkdir -p deploy

        # Jar 파일 복사
        - name: Copy Jar
          run: cp ./build/libs/*.jar ./deploy

        # zip 파일 생성
        - name: Make zip file
          run: zip -r ./practice.zip ./deploy
          shell: bash

        # AWS 접근 환경설정
        - 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

        # Amazon S3에 업로드
        - name: Upload to S3
          run: aws s3 cp ./practice.zip s3://버킷이름

작성 후 상단의 Commit Changes 버튼을 눌러준다.

그럼 위 파일에 작성해준대로 develop 브랜치에 push 이벤트가 발생하기 때문에 작성한 프로세스가 실행될 것이다.

성공!

8. CodeDeploy 적용

CodeDeploy 애플리케이션과 배포그룹을 생성해준다.

프로젝트의 루트디렉토리에 appspec.yml을 작성해준다.

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

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

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

ApplicationStart와 ValidateService에 정의해준 deploy.shhealthCheck.sh 파일을 작성해야한다.

루트디렉토리에 scripts 디렉토리를 만들고 안에 파일들을 생성해준다

  • scripts/deploy.sh
#!/bin/bash

export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"

REPOSITORY=/home/practice/app

echo "pm2 실행중인 프로세스 종료"

pm2 kill

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 실행"

cd $REPOSITORY

pm2 start /home/practice/ecosystem.config.js
  • scripts/healthCheck.sh
#!/bin/bash
echo "> Health check 시작"
echo "> curl -s http://localhost:8080/health/check "

for RETRY_COUNT in {1..15}
do
  # RESPONSE body 데이터에 'SUCCESS'이라는 글자가 있다면 성공, 없다면 다시 체크
  RESPONSE=$(curl -s http://localhost:8080/health/check)
  UP_COUNT=$(echo $RESPONSE | grep 'SUCCESS' | wc -l)

  if [ $UP_COUNT -ge 1 ]
  then # $up_count >= 1 ("UP" 문자열이 있는지 검증)
      echo "> Health check 성공"
      break
  else
      echo "> Health check의 응답을 알 수 없거나 혹은 status가 UP이 아닙니다."
      echo "> Health check: ${RESPONSE}"
  fi

  if [ $RETRY_COUNT -eq 10 ]
  then
    echo "> Health check 실패. "
    exit 1
  fi

  echo "> Health check 연결 실패. 재시도..."
  sleep 10
done
exit 0

healthCheck.sh 파일에 작성한 /health/check 엔드포인트는 spring boot 애플리케이션 내에 health check용 엔드포인트를 작성해줬다

@Tag(name = "AWS Health 검사를 위한 API")
@RequestMapping("/health")
@RestController
public class HealthController {

    @Operation(summary = "AWS Health 검사 API", description = "AWS Health 검사 API")
    @ResponseStatus(HttpStatus.OK)
    @GetMapping("/check")
    public String healthCheck() {
        return "SUCCESS";
    }
}

9. gradle.yml 파일 수정

위에서 작성했던 gradle.yml파일의 제일 뒤에 아래 코드를 추가해준다.

    # CodeDeploy 실행
    - name: Execute CodeDeploy
      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 CodeDeploy_애플리케이션_이름 \
          --deployment-group-name CodeDeploy_배포그룹_이름 \
          --file-exists-behavior OVERWRITE \
          --s3-location bucket=버킷이름,bundleType=zip,key=zip_파일이름.zip \
          --region ap-northeast-2

profile
개발공부를해보자

0개의 댓글