[ CI/CD ] Github Actions + AWS CodeDeploy 를 활용한 CI/CD (feat. SpringBoot)

2024. 8. 16. 15:32· 개발자 공부/인프라 - AWS
목차
  1. 개발 환경
  2. CI/CD?
  3. CI/CD!
  4. GithubActions - 아키텍처 및 구성 요소
  5. Workflow
  6. Event
  7. Jobs
  8. Secrets
  9. GithubActions - CI/CD 구축
  10. CodeDeploy
728x90

개발 환경

⚙️ [ Java17, Gradle, Spring 3.3.1 ], [ Github, GithubActions ], [ AWS, EC2 - ubuntu, S3, CodeDeploy ]

 

CI/CD?

CI/CD는 지속적 통합(Continuous Integration)과 지속적 배포 (Continuous Deployment)의 약자입니다.

 

CI는 지속적으로 코드를 통합하고 자동화된 테스트를 거치는 것을 의미합니다. 이로 인해서 버그가 줄어들고, 코드의 변경사항이 생길 때 마다 수동으로 테스트하지 오류가 줄어듭니다. 또한 개발자들 끼리 서로 코드가 충돌(conflict)날 수 있는데, 이를 잡아줄 수 있습니다.

 

CD는 CI된 코드를 자동적으로 배포하는 것을 의미합니다. 배포 과정을 자동화하여 사람이 낼 수 있는 실수를 없앨 수 있고, 자주 배포하여 사용자에게 빠르게 제공합니다.

 

CI/CD!

CI/CD를 도와주는 툴로는 GithubActions, Jenkins, Travis CI, CircleCI 등이 있습니다. 저는 이번에 GithubActions를 이용해서 CI/CD를 구축할 것인데, 보다 큰 규모의 프로젝트에서는 Jenkins를 주로 씁니다.

 

CI/CD를 쓰는 이유로는 여러가지가 있습니다. 주로 비용 감소, 개발 품질 향상 2가지를 뽑을 수 있습니다.

 

먼저,비용 감소는 통합과 배포에 쓰는 비용을 줄여서 개발자가 온전히 개발에만 시간을 투자할 수 있게 해줍니다. 개발 품질 향상은 수정 사항이나 버그픽스에 대해서 바로바로 반영될 수 있게 해줍니다.

 

GithubActions - 아키텍처 및 구성 요소

GithubActions를 이용한 CI/CD 과정은 다음과 같습니다. GithubActions에서 S3에 업로드하면 CodeDeploy가 EC2에 S3에 있는 파일을 다운로드하고 스크립트를 EC2에서 실행합니다. 스크립트는 저희가 수동으로 해주는 과정을 미리 적어놓고 자동으로 실행되게 해준다고 보시면 됩니다.

 

GithubActions의 구성 요소는 대표적으로 Workflow, Event, Jobs, Secrets등이 있습니다. 아래 설명을 보시고 ci.yml 코드를 보시면 보다 쉽게 이해하실 수 있습니다.

 

Workflow

  • 정의: 작업의 자동화된 프로세스를 정의한 YAML 파일입니다. .github/workflows 디렉토리에 저장됩니다.
  • 구조: 워크플로우는 이벤트, 작업(job), 스텝(step)으로 구성됩니다.

 

Event

  • 정의: 워크플로우가 실행되는 트리거입니다.
  • 예시:
    push: 브랜치에 코드가 푸시될 때
    pull_request: 풀 리퀘스트가 열리거나 업데이트될 때

 

Jobs

  • 정의: 워크플로우 내에서 병렬 또는 순차적으로 실행되는 단위입니다.
  • 특징: 각 작업은 독립적인 가상 환경에서 실행됩니다.
  • 구성 요소: runs-on: 작업이 실행될 환경을 지정 (예: ubuntu-latest, windows-latest)

 

Secrets

  • 정의: 민감한 정보를 안전하게 저장하고 워크플로우에서 사용할 수 있도록 합니다.
  • 예시: API 키, 토큰 등

 

GithubActions - CI/CD 구축

우선 actions에 가면, 아래와 같이 나오는데, 자신의 설정에 맞는 ci.yml파일을 찾을 수 있습니다. 저는 여기서 배포할 branch 설정과 dependency-submission을 지우는 것 정도만 수정했습니다. configure를 누르시면, repository/.github/workflows/ 위치에 ci.yml 파일을 자동생성해줍니다.

 

 

 

제가 사용한 ci.yml 파일입니다.

name: Java CI with Gradle

on:
  # main이라는 브렌치에 push라는 이벤트가 발생했을 때, CI가 진행되게 해줍니다.
  push:
    branches:
      - "main"
#      - "develop"

  # pr을 보냈을 때, 테스트를 하기 위해 추가적으로 작성함. 지우셔도 됩니다.
  pull_request:
    branches:
      - "main"
#      - "develop"

# jobs에는 CI가 어떻게 진행될지 적습니다.
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

      - name: Grant execute permission for gradlew
          run: chmod +x gradlew
        # 저희 프로젝트가 Backend라는 repo안에 project가 존재하기 때문에, 한 단계 들어가야해서 이런식으로 적었습니다.
        # run: chmod +x projectname/gradlew

      - name: Build with Gradle Wrapper
          run: ./gradlew clean build --no-daemon -x test
        # run: cd projectname && ./gradlew clean build --no-daemon -x test

 

 

 

ci.yml 파일을 actions에서 만드셨다면, API 키, 토큰 등 중요한 정보를 Setting에 들어가셔서 아래 Secrets and variables를 클릭합니다. 그러면 토글에 Actions가 나오는데, 클릭해줍니다.

 

 

 

그러면 아래와 같이 나오는데, New repository secrets를 누르셔서 API 키, 토큰 등 노출되면 안되는 정보들을 넣어줍니다. cd.yml에 applicatios.properties를 생성하실 수 있으니 properties파일을 통째로 넣으셔도 됩니다.(이 때, github에 properties 파일은 삭제해주시고 올려주시면 됩니다.)

 

 

 

위에서 보았던 CI/CD 과정에서 이제 cd.yml은 S3에 업로드 및 CodeDeploy가 실행되게 해줘야 합니다. 쉽게 말해서 AWS에서 수행될 내용을 적어준다고 생각하면 됩니다. 제가 사용한 cd.yml은 아래와 같습니다. secrets.은 actions에서 설정한 내용이 불러와 지는 것이고, env.은 cd 파일에 환경설정한 부분들이 불러와지는 것입니다.

name: Deploy to Amazon EC2

on:
  push:
    branches:
      - "main"
#      - "develop"

# 본인의 aws 설정을 넣어주시면 됩니다. 직접 넣으셔도, actions에 넣으셔도 상관없습니다.
env:
  AWS_REGION: ${secrets.region}
  S3_BUCKET_NAME: ${secrets.bucket_name}
  CODE_DEPLOY_APPLICATION_NAME: ${secrets.code_deploy_application_name}
  CODE_DEPLOY_DEPLOYMENT_GROUP_NAME: ${secrets.code_deploy_application_group_name}

permissions:
  contents: read

# AWS에서 작동할 내용들입니다.
jobs:
  deploy:
    name: Deploy
    runs-on: ubuntu-latest
    environment: production
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Set up JDK 17
        uses: actions/setup-java@v3
        with:
          distribution: 'temurin'
          java-version: '17'
          cache: 'gradle'

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

      # 앞서 말한 application.properties를 생성하는 부분입니다.
      - name: Create application.properties
        run: echo "${{ secrets.APPLICATION_PROPERTIES }}" > [ root ]/src/main/resources/application.properties

      - name: Build with gradle
        run: ./gradlew clean build --no-daemon -x test

      - name: Create zip file
        run: zip -r ${{ github.sha }}.zip [ root ]/build/libs/

      - 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: 'your region'

      - name: Upload to AWS S3
        run: |
          aws deploy push \
            --application-name ${{ env.CODE_DEPLOY_APPLICATION_NAME }} \
            --ignore-hidden-files \
            --s3-location s3://${{env.S3_BUCKET_NAME}}/${{ github.sha }}.zip \
            --source .

      # 배포 그룹에서 배포를 시작하는데, 여기서 스크립트 파일을 읽어 EC2를 실행하게 됩니다.
      - name: Deploy to AWS EC2 from S3
        run: |
          aws deploy create-deployment \
            --application-name ${{ env.CODE_DEPLOY_APPLICATION_NAME }} \
            --deployment-config-name CodeDeployDefault.AllAtOnce \
            --deployment-group-name ${{ env.CODE_DEPLOY_DEPLOYMENT_GROUP_NAME }} \
            --s3-location bucket=${{ env.S3_BUCKET_NAME }},key=${{ github.sha }}.zip,bundleType=zip

 

 

 

 

CodeDeploy

이제 CodeDeploy 에서 사용할 스크립트와 appspec.yml에 대해서 알아봅시다. 현재는 비용문제로 배포한 사이트를 모두 내려놔서 없지만, 아래 파일을 보면 file을 설치할 경로와 권한 마지막으로 hooks가 있는데, hooks는 오른쪽 순서대로 진행됩니다. 자세한 설명은 다른 블로그 혹은 공식 사이트에서 봐주시면 좋겠습니다. 우선 ApplicationStart를 통해서 location에 위치한 스크립트 파일을 ec2에서 실행해준다고 생각하시면 됩니다.

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

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

hooks:
  ApplicationStart:
    - location: scripts/deploy.sh
      timeout: 60
      runas: ubuntu

 

 

 

다음으로는 실행한 스크립트 파일입니다. 현재 배포된 서버를 다운시키고, 새롭게 배포하는 방식입니다. project에 본인의 프로젝트 이름을 넣어주시고, 저는 java를 사용하여 jar파일을 이용해서 배포했습니다.

PROJECT_ROOT="/home/ubuntu/app/project"
JAR_FILE="$PROJECT_ROOT/project-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)

# 현재 실행 중인 애플리케이션 찾기
CURRENT_PID=$(pgrep -f $JAR_FILE)

# 실행 중인 애플리케이션이 있다면 종료
if [ -z "$CURRENT_PID" ]; then
  echo "$TIME_NOW : No application running" >> $DEPLOY_LOG
else
  echo "$TIME_NOW : Kill process $CURRENT_PID" >> $DEPLOY_LOG
  kill -9 $CURRENT_PID
fi

# 애플리케이션 복제
echo "$TIME_NOW : copy $JAR_FILE" >> $DEPLOY_LOG
cp $PROJECT_ROOT/build/libs/*.jar $PROJECT_ROOT

# 애플리케이션 권한부여 및 백그라운드 실행
echo "$TIME_NOW : run $JAR_FILE" >> $DEPLOY_LOG
chmod +x $JAR_FILE
nohup java -jar $JAR_FILE > $APP_LOG 2> $ERROR_LOG &

# 새로운 프로세스 아이디를 로그에 기록
NEW_PID=$(pgrep -f $JAR_FILE)
echo "$TIME_NOW : New process id is $NEW_PID" >> $DEPLOY_LOG

 

 

마지막으로 실제로 서버가 실행됐는지 확인해주시면 됩니다. 만약, 제대로 실행되지 않았다면, error_log에 들어가셔서 봐주시면 됩니다. 한 번에 쓴 글이 아니라 중간에 빠진 내용도 있을 수도 있을 것 같은데, 혹시 제대로 안되신다면 댓글에 남겨주시면 감사하겠습니다.

728x90

'개발자 공부 > 인프라 - AWS' 카테고리의 다른 글

[ AWS ] EC2 인스턴스에 HTTPS 적용하기 (feat. Route53, ALB, 프로젝트)  (0) 2024.08.07
  1. 개발 환경
  2. CI/CD?
  3. CI/CD!
  4. GithubActions - 아키텍처 및 구성 요소
  5. Workflow
  6. Event
  7. Jobs
  8. Secrets
  9. GithubActions - CI/CD 구축
  10. CodeDeploy
'개발자 공부/인프라 - AWS' 카테고리의 다른 글
  • [ AWS ] EC2 인스턴스에 HTTPS 적용하기 (feat. Route53, ALB, 프로젝트)
RealTone
RealTone
풀스택 개발자되기 기원 1년차
RealTone
개발공부 블로그
RealTone
전체
오늘
어제
  • 분류 전체보기 (81)
    • 개발자 공부 (5)
      • 인프라 - AWS (2)
      • Frontend - React (1)
    • 구름톤트레이닝 (1)
      • 강의 후기 (0)
    • 문제풀이 (74)
      • 알고리즘 문제 풀이 (62)
      • SQL 문제 풀이 (12)
    • 개인 (0)
      • 멕북초기화세팅 (0)

블로그 메뉴

  • 홈
  • 태그
  • GitHub
  • 방명록

태그

  • AWS
  • baekjoon
  • CI/CD
  • codedeploy
  • ec2
  • G2
  • G3
  • G4
  • G5
  • git/github

최근 글

hELLO · Designed By 정상우.v4.2.2
RealTone
[ CI/CD ] Github Actions + AWS CodeDeploy 를 활용한 CI/CD (feat. SpringBoot)
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.