프로젝트를 aws 에서 제공하는 ec2 에 배포하기 위해서는 상당히 복잡한(귀찮은) 과정이 필요하다. 따라서 이번 포스트에서 보다 쉬운 배포를 위해 git actions를 사용한 CI/CD 셋업을 소개하겠다.
위의 링크에서 자세히 알 수 있다. 요약을 하자면 다음과 같다.
CI (Continuous Integration)
CI는 지속적 통합이라는 뜻으로 개발을 진행하면서도 품질을 관리할 수 있도록 하는 것으로 여러 명이 하나의 코드에 대해서 수정을 진행해도 지속적으로 통합하면서 관리할 수 있음을 의미한다.
CI가 나오기 전까지는 위와 같이 개발을 끝마치고 배포가 되어야만 코드에 오류는 없는지, 올바르게 동작하는지를 검증하며 코드 품질을 관리할 수 있었다.
CI를 적용하게 되면 각자의 개발자가 자신의 구현해야 할 기능을 구현하면 된다. 이후 완성이 되면 main 브랜치와 통합하고 코드가 잘 빌드되는지 보고, 올바르게 동작하는지 테스트하며 코드에 버그가 있다면 해결한다.
하지만 개발자가 직접 코드를 병합하고 빌드, 테스트를 검증하는 것은 시간이 많이 소요될 뿐만 아니라 귀찮고 그 양도 프로젝트의 크기가 커질수록 많아질 수밖에 없다.
CD(Continuous Deployment)
이제 지속적 통합을 거친 코드에 대해서 신뢰할 수 있고 바로 배포할 수 있다.
CD는 지속적 배포로 소프트웨어가 항상 신뢰 가능한 수준에서 배포될 수 있도록 관리하자는 개념으로 지속적 제공(Continuous Delivery)로 사용되기도 한다.
지속적 제공은 CI를 통해서 새로운 소스코드의 빌드와 테스트 병합까지 성공적으로 진행되었다면, 빌드와 테스트를 거쳐 github과 같은 저장소에 업로드하는 것을 의미한다.
지속적 배포는 이렇게 성공적으로 병합된 내역을 저장소뿐만 아니라 사용자가 사용할 수 있는 배포환경까지 릴리즈하는 것을 의미한다.
지속적 배포에서는 지속적 통합을 통해 빌드한 소스코드를 테스트 가능한 알파나 베타 버전으로 만든다. 이 버전에서 테스트를 수행해 문제가 발생하면 수정한 뒤 정식 버전으로 배포를 진행한다.
위와 같은 방식은 매우 귀찮다..
CI/CD 적용 전과 달리 수정 사항이 생길 경우 커밋 후 원격 저장소에 push 를 하기만 하면 작성한 yml 파일에 따라 실행되며 통합 및 배포가 실행된다.(yml 파일 작성 및 ci/cd 셋업은 밑에서 자세히 설명하겠다.)
위의 블로그에서 자세한 내용에 대해 확인할 수 있다.
아래의 블로그를 보며 차근차근 따라하면 된다.
github action과 aws code deploy를 이용하여 spring boot 배포하기
본인도 위 블로그를 보며 햇갈린 부분이 있어 파일별 용도와 작성한 스크립트에 대해 설명을 하도록하겠다.
프로젝트 최상단에 .github/workflows/*.yml, appspec.yml, deploy.sh 파일이 필요하다.
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들을 정의하는 파일이다.
꼭 폴더구조를 위의 사진과 같이 하여야한다
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 는 밑에서 확인하겟다.
#!/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를 실행해준다고 생각하면된다.
원격 저장소의 master 브랜치에 push 후 Actions 로 들어가면 git-actions 가 실행되는 것을 확인할 수 있으며, 성공 시 아래와 같은 화면이다.
CI/CD 를 사용할 경우 위의 사진과 같이 git-actions 에서 gradlew build 까지 되는 것을 확인할 수 있다.
이제 커밋 후 master 에 push 만 해도 서버 배포가 되는 것을 확인할 수 있다.
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)/