camp-us 캠핑장 커뮤니티 프로젝트-6(aws와 git actions를 사용한 CI/CD 설정)

김상운(개발둥이)·2022년 3월 1일
0

camp-us

목록 보기
6/6
post-thumbnail

개요

프로젝트를 aws 에서 제공하는 ec2 에 배포하기 위해서는 상당히 복잡한(귀찮은) 과정이 필요하다. 따라서 이번 포스트에서 보다 쉬운 배포를 위해 git actions를 사용한 CI/CD 셋업을 소개하겠다.

CI/CD 란

CI/CD 설명 - redhat
CI/CD 설명 - java 예시

위의 링크에서 자세히 알 수 있다. 요약을 하자면 다음과 같다.

CI

CI (Continuous Integration)
CI는 지속적 통합이라는 뜻으로 개발을 진행하면서도 품질을 관리할 수 있도록 하는 것으로 여러 명이 하나의 코드에 대해서 수정을 진행해도 지속적으로 통합하면서 관리할 수 있음을 의미한다.

CI가 나오기 전까지는 위와 같이 개발을 끝마치고 배포가 되어야만 코드에 오류는 없는지, 올바르게 동작하는지를 검증하며 코드 품질을 관리할 수 있었다.

CI를 적용하게 되면 각자의 개발자가 자신의 구현해야 할 기능을 구현하면 된다. 이후 완성이 되면 main 브랜치와 통합하고 코드가 잘 빌드되는지 보고, 올바르게 동작하는지 테스트하며 코드에 버그가 있다면 해결한다.

하지만 개발자가 직접 코드를 병합하고 빌드, 테스트를 검증하는 것은 시간이 많이 소요될 뿐만 아니라 귀찮고 그 양도 프로젝트의 크기가 커질수록 많아질 수밖에 없다.

CD

CD(Continuous Deployment)
이제 지속적 통합을 거친 코드에 대해서 신뢰할 수 있고 바로 배포할 수 있다.

CD는 지속적 배포로 소프트웨어가 항상 신뢰 가능한 수준에서 배포될 수 있도록 관리하자는 개념으로 지속적 제공(Continuous Delivery)로 사용되기도 한다.

지속적 제공은 CI를 통해서 새로운 소스코드의 빌드와 테스트 병합까지 성공적으로 진행되었다면, 빌드와 테스트를 거쳐 github과 같은 저장소에 업로드하는 것을 의미한다.

지속적 배포는 이렇게 성공적으로 병합된 내역을 저장소뿐만 아니라 사용자가 사용할 수 있는 배포환경까지 릴리즈하는 것을 의미한다.

지속적 배포에서는 지속적 통합을 통해 빌드한 소스코드를 테스트 가능한 알파나 베타 버전으로 만든다. 이 버전에서 테스트를 수행해 문제가 발생하면 수정한 뒤 정식 버전으로 배포를 진행한다.

CI/CD 적용 전 배포 방식

  1. 수정사항이 생길 경우 수정 후 커밋메시지를 남긴다.
  2. 수정사항을 프로젝트명.jar 배포 파일로 만들기 위해 터미널에서 gradlew build 를 입력하여 프로젝트를 빌드한다. (*주의 intellij 에 .gradle 폴더가 있을 경우 정상적으로 빌드가 되지 않기 때문에 반드시 삭제후 빌드하여야 한다.)
  3. 빌드 후 커밋메시지를 남긴 후 원격 저장소에 푸쉬를 한다.
  4. aws 의 ec2 에서 git clone 을 하여 원격 저장소의 폴더를 다운 받는다.
  5. ec2 의 터미널이 종료되도 백그라운드에서 돌아갈 수 있게 screen 을 활용하여 직접 폴더에 접근하여 java -jar 프로젝트명.jar 로 스프링 프로젝트를 시작 후 screen 나가기

위와 같은 방식은 매우 귀찮다..

CI/CD 적용 후 배포 방식

  1. 수정사항이 생길 경우 수정 후 커밋메시지를 남긴다.
  2. 원격 저장소에 master 브랜치에 푸쉬를 한다.
  3. ec2 에서 정상적으로 배포가 되었는지 확인

CI/CD 적용 전과 달리 수정 사항이 생길 경우 커밋 후 원격 저장소에 push 를 하기만 하면 작성한 yml 파일에 따라 실행되며 통합 및 배포가 실행된다.(yml 파일 작성 및 ci/cd 셋업은 밑에서 자세히 설명하겠다.)

git-actions란

깃헙 액션즈 알아보기

위의 블로그에서 자세한 내용에 대해 확인할 수 있다.

CI/CD 셋업

아래의 블로그를 보며 차근차근 따라하면 된다.

github action과 aws code deploy를 이용하여 spring boot 배포하기

본인도 위 블로그를 보며 햇갈린 부분이 있어 파일별 용도와 작성한 스크립트에 대해 설명을 하도록하겠다.

프로젝트 폴더구조

프로젝트 최상단에 .github/workflows/*.yml, appspec.yml, deploy.sh 파일이 필요하다.

main.yml

name: CI

on:
  push:
    branches:
      - master

jobs:
  backend:
    name: CI with Gradle
    runs-on: ubuntu-18.04

    steps:
      - name: 체크아웃 Github-Action
        uses: actions/checkout@v2

      - name: 자바 JDK 11 설치
        uses: actions/setup-java@v1
        with:
          java-version: 11

      - name: gradlew 권한 부여
        run: chmod +x ./gradlew

      - name: Gradle 빌드
        run: ./gradlew build
        shell: bash

      - name: Make zip file
        run: zip -r ./$GITHUB_SHA.zip .
        shell: bash

      - name: AWS 설정
        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 ./$GITHUB_SHA.zip s3://camp-us/$GITHUB_SHA.zip

      - name: Code Deploy
        run: aws deploy create-deployment --application-name camp-deploy-app-new --deployment-config-name CodeDeployDefault.OneAtATime --deployment-group-name dev --s3-location bucket=camp-us,bundleType=zip,key=$GITHUB_SHA.zip

해당 yml 파일은 action에서 실행할 job들을 정의하는 파일이다.
꼭 폴더구조를 위의 사진과 같이 하여야한다

  • name : CI
    • 워크플로우 이름을 설정합니다. 여기서는 “CI”라고 정해봅니다
  • on :
    • 트리거
    • 해당 워크플로우가 실행되는 트리거를 지정합니다.
    • push 는 push가 발생했을때
    • pull_request 는 pull_request 가 발생했을 때 트리깅합니다.
    • wokflow_dispatch 는 버튼을 클릭해서 수동으로 이벤트를 시작시킬 수 있습니다.
  • jobs
    • 워크플로우에서 실행되는 모든 작업을 그룹화
  • build:
    • build라는 이름의 작업을 정의합니다.
  • runs-on: ubuntu-latest
    • 최신 버전의 Ubuntu Linux 실행기에서 실행되도록 작업을 구성합니다.
    • Github에서 호스팅하는 가상머신에서 실행됨을 의미합니다.
    • ubuntu, window, mac 등을 사용할 수 있다.
  • steps:
    • 작업에서 실행되는 모든 단계를 함께 그룹화합니다.
  • uses: actions/checkout@v2
    • 해당 step에서 사용할 액션. Github 마켓플레이스에 올라온 action들을 사용할 수 있다.
    • checkout 은 git 관련된 명령등을 수행할 수 있게 해준다

appspec.yml

version: 0.0
os: linux

files:
  - source: /
    destination: /home/ubuntu/camp_us
permissions:
  - object: /home/ubuntu/camp_us
    owner: ubuntu
    group: ubuntu
    mode: 755
hooks:
  AfterInstall:
    # location은 프로젝트의 root경로를 기준
    - location: deploy.sh
      timeout: 60
      runas: root

배포가 실행되면 ec2에 설치된 CodeDeploy agent에서 해당 파일을보고, 받아온 프로젝트를 어디에 저장할지 그리고 무엇을 실행할지를 정한다.

즉, codeDeploy 에서 appspec.yml 파일을 보고 어느 경로에 어떤 이름으로 저장할 것인지를 적는 파일이다.

또한 밑의 AfterInstall 을 보면 저장 후 deploy.sh 라는 쉘스크립트를 시작하는 것을 볼 수 있다. deploy.sh 는 밑에서 확인하겟다.

deploy.sh

#!/usr/bin/env bash

REPOSITORY=/home/ubuntu/camp_us
cd $REPOSITORY

APP_NAME=camping
JAR_NAME=$(ls $REPOSITORY/build/libs/ | grep '.jar' | tail -n 1)
JAR_PATH=$REPOSITORY/build/libs/$JAR_NAME

CURRENT_PID=$(pgrep -f $APP_NAME)

if [ -z $CURRENT_PID ]
then
  echo "> 종료할것 없음."
else
  echo "> kill -9 $CURRENT_PID"
  kill -15 $CURRENT_PID
  sleep 5
fi

echo "> $JAR_PATH 배포"

#23412
nohup java -jar $JAR_PATH --spring.profiles.active=prod /dev/null 2> /dev/null < /dev/null &

deploy.sh 생성
appspec.yml에서 사용된 location: deploy.sh 구문으로 인해 deploy.sh 파일을 실행하는 쉘스크립트다.

해당파일에서 jar를 실행해준다고 생각하면된다.

git-actions

원격 저장소의 master 브랜치에 push 후 Actions 로 들어가면 git-actions 가 실행되는 것을 확인할 수 있으며, 성공 시 아래와 같은 화면이다.

CI/CD 를 사용할 경우 위의 사진과 같이 git-actions 에서 gradlew build 까지 되는 것을 확인할 수 있다.

정리

이제 커밋 후 master 에 push 만 해도 서버 배포가 되는 것을 확인할 수 있다.

깃허브: https://github.com/Couch-Coders/6th-camp_us-be

참고 사이트

https://www.redhat.com/ko/topics/devops/what-is-ci-cd https://tecoble.techcourse.co.kr/post/2021-08-14-ci-cd/ https://velog.io/@whaleshark/%EA%B9%83%ED%97%99-%EC%95%A1%EC%85%98%EC%A6%88-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0 https://isntyet.github.io/deploy/github-action%EA%B3%BC-aws-code-deploy%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%98%EC%97%AC-spring-boot-%EB%B0%B0%ED%8F%AC%ED%95%98%EA%B8%B0(1)/

profile
공부한 것을 잊지 않기 위해, 고민했던 흔적을 남겨 성장하기 위해 글을 씁니다.

0개의 댓글