Git

[GIT&AWS] 깃헙액션으로 CI/CD 배포 자동화 하기!

재원쓰 2023. 2. 27. 13:47

📖 EC2에 프로젝트 빌드하여 올리는 것까지 완료했다. 이제는 CI/CD 배포 자동화를 해볼 차례!

 

실제 배포된 인스턴스는 ubuntu이지만 포스팅이 죄다 linux 인스턴스로 되어있어서 일단 연습할 겸 새 인스턴스는 linux 기반으로 생성했다. 연습은 linux대로 하고 실제 적용할 땐 ubuntu 기준으로 살짝만 변경해주면 될 것이다.

1. ec2 인스턴스에서 자동배포를 위해 필요한 codedeploy를 설치해줘야 한다.

# 패키지 매니저 업데이트, ruby 설치
sudo yum update
sudo yum install ruby
sudo yum install wget

# 서울 리전에 있는 CodeDeploy 리소스 키트 파일 다운로드
cd /home/ec2-user
wget https://aws-codedeploy-ap-northeast-2.s3.ap-northeast-2.amazonaws.com/latest/install

# 설치 파일에 실행 권한 부여
chmod +x ./install

# 설치 진행 및 Agent 상태 확인
sudo ./install auto
sudo service codedeploy-agent status

Agent 상태 확인을 했을 때 위와 같이 나오면다면 성공이다.

 

2. 깃허브 액션에서 new workflow를 들어간다. 우리는 springboot를 사용했고, 이 프로젝트를 서버에 배포할 것이기 때문에 'Java with Gradle' 으로 선택한다.

 

3. gradle.yml 파일에 아래 내용으로 넣어준다. 설명은 아래에서 차근차근 살펴보도록 하자.

# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
# This workflow will build a Java project with Gradle and cache/restore any dependencies to improve the workflow execution time
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-gradle

name: Java CI with Gradle

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

permissions:
  contents: read

jobs:
  build:

    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v3
    - name: Set up JDK 17
      uses: actions/setup-java@v3
      with:
        java-version: '17'
        distribution: 'temurin'
#     - name: Build with Gradle
#       uses: gradle/gradle-build-action@67421db6bd0bf253fb4bd25b31ebb98943c375e1
#       with:
#         arguments: build
    - uses : actions/checkout@v3
    #1
    # 해당 부분은 상당히 중요함 (글에서 부가설명)
    # application.properties는 외부에 노출되면 안되므로 Actions가 빌드될때마다 해당 Repository의 Secret 설정을
    # 이용하여서 설정 파일을 생성해줌 (github에 commit 되는게 아님!)
    - run : touch ./src/main/resources/application.yml
    - run : echo "${{ secrets.APPLICATION }}" > ./src/main/resources/application.yml
    - run : cat ./src/main/resources/application.yml
    
    # gradlew에 권한 부여
    - name: Grant execute permission for gradlew
      run: chmod +x gradlew
    
    # gradlew 빌드
    - name: Build with Gradle
      run: ./gradlew clean build

    # 이름은 run 에서 설정 가능
    # 빌드를 성공하면 해당 프로젝트를 zip로 만듬
    - name: Make zip file
      run: zip -r ./<자신이 만든 ZIP 파일 이름>.zip .
      shell: bash

    #2
    # AWS 계정 설정
    - name: Configure AWS credentials
      uses: aws-actions/configure-aws-credentials@v1
      with:
      # 깃허브 Secret에 넣어둔 Access key
        aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
      # 깃허브 Secret에 넣어둔 Secret key
        aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
      # 깃허브 Secret에 넣어둔 Region
        aws-region: ${{ secrets.AWS_REGION }}

    #3
    # 만들어 놓은 S3에 해당 zip 파일 저장
    - name: Upload to S3
      run: aws s3 cp --region ${{ secrets.AWS_REGION }} ./<자신이 만든 ZIP 파일 이름>.zip s3://<만들어 놓은 버킷 이름>/<자신이 만든 ZIP 파일 이름>.zip
    
    #4
    # AWS CodeDeploy에 배포
    - 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 <AWS codeDeploy 애플리케이션 이름> \
        --deployment-group-name <codeDeploy group 이름> \
        --file-exists-behavior OVERWRITE \
        --s3-location bucket=<만들어 놓은 버킷 이름>,bundleType=zip,key=<자신이 만든 ZIP 파일 이름>.zip \
        --region ${{ secrets.AWS_REGION }}

#1 application.yml 설정하기

보안상 이유로 application.yml는 github에 올리지 않는다. 그러면 어떻게 CI를 구축할 수 있을까?

[ Repository > Settings > 좌측에 Secrets and variables > Actions ] 탭을 들어간 뒤 'New repository secret' 을 클릭한다. #1 주석의 ${{ secrets.APPLICATION }}는 secrets의 APPLICATION이라는 이름으로 Secret을 작성해주고, 내용은 application.yml의 내용을 붙여넣는다.

이렇게 해주면 CI가 작동될 때마다 secret에서 코드를 가져와 application.yml을 자체적으로 생성 후 빌드해준다. 결과적으로 yml 파일을 github에 올리지 않더라도 CI를 구축할 수 있다.

 

#2 AWS 계정 설정하기

여기에 있는 ${{ secrets.AWS_ACCESS_KEY_ID }}와 ${{ secrets.AWS_SECRET_ACCESS_KEY }}도 마찬가지로 Secret을 생성해주면 되며, 각각 IAM의 액세스 키와 시크릿 키를 넣어준다. ${{ secrets.AWS_REGION }}은 사용하고 있는 리전 주소를 Secret에 넣어주면 된다. ex) ap-northeast-2

 

#3 CI를 통해 만든 zip 파일을 S3에 저장하기

gradle.yml에 파일에서 자신이 만들 ZIP 파일 이름을 그대로 넣어주고, 자신이 AWS에서 만들어놓은 S3 버킷 이름을 넣어주면 된다.

 

#4 AWS CodeDeploy에 배포하기

${{ secrets.AWS_ACCESS_KEY_ID }}와 ${{ secrets.AWS_SECRET_ACCESS_KEY }}는 앞서 넣어둔 액세스키와 시크릿 키가 들어갈 테고, run 부분에서 주석에 맞게끔 값들을 넣어준다.

 

주의할 점

Gradle.yml이 어떤 브랜치에 있는지에 따라 나뉜다. 작성후 커밋할 때 delvelop 브랜치 쪽으로 머지해주는 과정이 필요하다.

여기까지 완료했으면 이번엔 AWS에서 세팅을 시작해보자.


1. IAM 역할을 생성한다.

[ IAM > 좌측 '역할' > 역할만들기 ] 를 클릭한다.

일반 사용 사례는 EC2를 선택하고 '다음'으로 간다.

위 2개의 정책을 선택하고 넘어간다.

마지막으로 역할 이름을 입력하고 역할 생성을 눌러준다.

 

2. EC2 인스턴스에 생성한 역할을 연결한다.

3. CodeDeploy 역할을 하나 더 만들어준다. 이번엔 'AWSCodeDeployRole' 정책만 추가한다.

4. CodeDeploy 애플리케이션을 생성해준다.

[ AWS > CodeDeploy > 애플리케이션 > 애플리케이션 생성 ]을 클릭한다.

위와 같이 설정하고 생성을 누른다.

 

5. 배포 그룹을 생성해준다.

위 값들을 넣어준다.

나머지 설정은 그대로 두고 로드 밸런싱 활성화 체크는 해제한 뒤 '배포 그룹 생성'을 클릭한다.

 

혹시 위와 같은 에러창이 뜬다면 설정해줄 부분이 있다.

[ IAM > 역할 ]에서 내가 선택한 역할을 들어간 뒤 '신뢰관계' 탭으로 들어간다.

신뢰 정책 편집에 들어가서 위에 박스친 부분처럼 수정해준다.

 

6. IAM 사용자를 추가한다. 기존에 사용자가 있다면 'AWSCodeDeployFullAccess' 권한을 추가해준다.

이 사용자의 Access Key와 Secret Access Key는 당연하겠지만 잘 보관해두자.

 

7. Github secret에 환경변수를 추가해준다.

위 화면에선 이미 다 추가한 모습이 있는데, 위와 같이 하나씩 추가해주면 된다.

 

이번엔 코드로 돌아가서 좀더 세팅을 해보자


1. 프로젝트 내부 최상단에 appspec.yml 파일을 만들어준다.

version: 0.0
os: linux
files:
  - source: /
    destination: /home/ec2-user/app/deploy

hooks:
  AfterInstall:
    - location: scripts/stop.sh
      timeout: 60
      runas: ec2-user
  ApplicationStart:
    - location: scripts/start.sh
      timeout: 60
      runas: ec2-user

destination의 경우 EC2내부에 저장 될 경로이다. 그리고 hooks를 통해 쉘 스크립트를 실행해줄 것인데 location으로 해당 쉘의 위치를 잡아 주고 실행줄 것이다. 

 

2. 프로젝트 최상단에 scripts 폴더를 만들어 start.sh와 stop.sh를 만들어준다.

start.sh

#!/usr/bin/env bash

PROJECT_ROOT="/home/ec2-user/app/deploy"
JAR_FILE="$PROJECT_ROOT/build/libs/sparta-0.0.1-SNAPSHOT.jar"

APP_LOG="$PROJECT_ROOT/application.log"
ERROR_LOG="$PROJECT_ROOT/error.log"
DEPLOY_LOG="$PROJECT_ROOT/deploy.log"

TIME_NOW=$(date +%c)

# build 파일 복사
echo "$TIME_NOW > $JAR_FILE 파일 복사" >> $DEPLOY_LOG
cp $PROJECT_ROOT/build/libs/*.jar $JAR_FILE

# jar 파일 실행
echo "$TIME_NOW > $JAR_FILE 파일 실행" >> $DEPLOY_LOG
nohup java -jar $JAR_FILE > $APP_LOG 2> $ERROR_LOG &

CURRENT_PID=$(pgrep -f $JAR_FILE)
echo "$TIME_NOW > 실행된 프로세스 아이디 $CURRENT_PID 입니다." >> $DEPLOY_LOG

stop.sh

#!/usr/bin/env bash

PROJECT_ROOT="/home/ec2-user/app/deploy"
JAR_FILE="$PROJECT_ROOT/build/libs/sparta-0.0.1-SNAPSHOT.jar"

DEPLOY_LOG="$PROJECT_ROOT/deploy.log"

TIME_NOW=$(date +%c)

# 현재 구동 중인 애플리케이션 pid 확인
CURRENT_PID=$(pgrep -f $JAR_FILE)

# 프로세스가 켜져 있으면 종료
if [ -z $CURRENT_PID ]; then
  echo "$TIME_NOW > 현재 실행중인 애플리케이션이 없습니다" >> $DEPLOY_LOG
else
  echo "$TIME_NOW > 실행중인 $CURRENT_PID 애플리케이션 종료 " >> $DEPLOY_LOG
  kill -15 $CURRENT_PID
fi

여기까지가 끝이다. 이제 develop 브랜치에서 푸시하여 CI/CD를 작동시켜보자.

 

 


[ AWS > CodeDeploy ]로 들어가면 배포그룹에 현재 진행중인 것을 볼 수 있다.

 


https://zzang9ha.tistory.com/404

 

GitHub-Actions로 CI/CD 구축하기(AWS, Docker, SpringBoot)

GitHub-Actions로 CI/CD 구축하기(AWS, Docker, SpringBoot) 안녕하세요, 이번 시간에는 GitHub-Actions로 CI/CD를 구축하는 방법에 대해 알아보겠습니다. 해당 포스팅이 CI/CD를 전체적으로 포함하고 있기는 하지만

zzang9ha.tistory.com

 

https://velog.io/@server30sopt/Github-Actions-AWS-CodeDeploy%EB%A5%BC-%ED%99%9C%EC%9A%A9%ED%95%9C-CICD-Node.js2

 

Github Actions, AWS CodeDeploy를 활용한 CI/CD - Node.js(2)

📌 Node.js 프로젝트를 Github Actions, AWS CodeDeploy를 활용하여 CI/CD 하는 과정을 다룹니다.

velog.io

 

https://velog.io/@hwsa1004/Github-Action-AWS-CodeDeploy-Spring-Boot-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EC%9E%90%EB%8F%99-%EB%B0%B0%ED%8F%AC%ED%95%98%EA%B8%B0

 

[Github Action + AWS CodeDeploy] Spring Boot 서버 자동 배포 및 실행하기

이번 글은 공유하기도 위함이지만 내가 프로젝트를 진행할때마다 잊지않기 위함이 더 크긴하다. 글대로 따라온다면 큰 문제없이 자신의 프로젝트를 Github Action과 AWS CodeDeploy를 통해 자동으로 서

velog.io

https://docs.aws.amazon.com/ko_kr/codedeploy/latest/userguide/codedeploy-agent-operations-install-ubuntu.html

 

Ubuntu Server용 CodeDeploy 에이전트 설치 - AWS CodeDeploy

출력을 임시 로그 파일에 쓰는 것은 Ubuntu 20.04에서 install 스크립트를 사용하여 알려진 버그를 해결하는 동안 사용해야 하는 해결 방법입니다.

docs.aws.amazon.com

 

https://jane514.tistory.com/4

 

Github Action 으로 CI workflow 생성해보기(w/ Spring Boot)

안녕하세요! 제인입니다 :) 최근 진행하고 있는 사이드 프로젝트에서 CI를 어떤 툴로 적용을 해볼건지에 대한 논의가 있었는데요, 기존에 익숙하게 사용하던 Jenkins를 택하지 않고 새롭게 Github Act

jane514.tistory.com

 

https://velog.io/@vector13/Springboot-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-Github-Action%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%B4%EC%84%9C-%EB%B0%B0%ED%8F%AC-%EC%9E%90%EB%8F%99%ED%99%94%ED%95%98%EA%B8%B0

 

https://dnight.tistory.com/entry/GitHub-Actions-%ED%99%98%EA%B2%BD%EB%B3%80%EC%88%98-%EB%93%B1%EB%A1%9D-%EB%B0%A9%EB%B2%95

 

GitHub Actions - 환경변수 등록 방법

github actions환경변수 등록하기 1. 상단 탭의 Settings 로 이동합니다. 2. 좌측 Secrets 항목으로 이동합니다. 3. "Add a New secret" 항목 클릭 4. Name , Value 를 작성합니다. 5. "Add secret" 클릭 6. 등록된 Name 을 복

dnight.tistory.com

 

 

https://zzang9ha.tistory.com/404

 

GitHub-Actions로 CI/CD 구축하기(AWS, Docker, SpringBoot)

GitHub-Actions로 CI/CD 구축하기(AWS, Docker, SpringBoot) 안녕하세요, 이번 시간에는 GitHub-Actions로 CI/CD를 구축하는 방법에 대해 알아보겠습니다. 해당 포스팅이 CI/CD를 전체적으로 포함하고 있기는 하지만

zzang9ha.tistory.com

 

디버깅

https://velog.io/@16fekim/AWS-CodeDeploy-%EA%B7%B8%EB%A3%B9-%EC%83%9D%EC%84%B1-%EC%97%AD%ED%95%A0-%EC%97%90%EB%9F%AC

 

AWS CodeDeploy 그룹 생성, 역할 에러

디버깅

velog.io