[springboot-webserivce] Travis CI, S3, CodeDeploy 를 통한 배포 자동화
Updated:
[2020.12.28] 부터 스프링 부트와 AWS로 혼자 구현하는 웹 서비스 책을 통해 스프링 공부를 시작했다.
공부한 내용을 글로 정리하려고 한다.
그래야 나중에 다시 찾아보며 공부 할 수 있을테니까 !!
🍟 Travis CI 설정
서비스를 배포하기 위한 모든 준비가 끝났다.
이제 깃허브에 푸시만 하면 자동으로 테스트, 빌드를 거쳐 서버에 배포까지 해주는 시스템을 구축하려고 한다.
먼저 푸시가 이루어지면 자동으로 테스트, 빌드를 해주는 작업을 하려고 한다.
이 과정을 CI (Continuous Integration) 라고 한다.
여러가지 CI 툴이 있지만 깃허브에서 제공하는 무료 툴인 Travis CI 를 사용하려고 한다.
Travis CI 로 이동해 깃허브 아이디로 로그인을 한 뒤 Setting 을 눌러 레파지토리를 연결해 준다.
웹 사이트에서의 설정은 이것이 끝이고 프로젝트에서 나머지 설정을 해주어야 한다.
Travis 는 yml 파일을 통해 설정을 할 수 있다.
build.gradle 파일과 같은 위치에 .travis.yml 파일을 생성 한다.
language: java
jdk:
- openjdk8
branches:
only:
- master
# Travis CI 서버의 Home
cache:
directories:
- '$HOME/.m2/repository'
- '$HOME/.gradle'
script: "./gradlew clean build"
# CI 실행 완료 시 메일로 알람
notifications:
email:
recipients:
nkb7714@naver.com
그리고 master 브랜치에 커밋과 푸시를 하게 되면 Travis 가 자동으로 테스트와 빌드를 수행하고 결과를 메일로 보내준다.
빌드가 성공하면 프로젝트와 Travis CI 간의 연결은 끝이다.
🌮 Travis CI AWS 에 접근하기
빌드 과정까지 자동으로 만들었으니 이제 배포도 자동으로 하게 만들어야 한다.
배포를 자동으로 하기 위해서는 AWS S3 와 AWS CodeDeploy 서비스가 필요하다.
S3 는 파일을 저장하는 서버이고 CodeDeploy 는 배포를 담당한다.
즉 Travis 가 빌드를 한 뒤 jar 파일을 S3 에 저장을 하고 CodeDeploy 가 S3에 있는 jar 파일을 서버에 배포한다.
그러나 AWS 는 기본적으로 외부 서비스가 접근하지 못하게 해두었다.
따라서 접근 할 수 있게 하도록 키를 발급 받아야 한다.
AWS 웹 콘솔로 들어가 IAM 사용자를 만들고 S3, CodeDeploy 권한을 추가 한다.
생성이 완료되면 엑세스 키와 비밀 엑세스 키가 발급되는데 이 키를 가지고 Travis 가 AWS 서비스에 접근 할 수 있다.
Travis 레파지토리 설정으로 들어가 AWS_ACCESS_KEY, AWS_SECRET_KEY 에 발급받은 키를 넣어주면 된다.
이제 Travis 가 키를 통해 AWS 서비스에 접근 할 수 있게 되었다.
🥘 S3 에 jar 파일 저장하기
Travis 가 빌드를 마친 뒤 실행 파일을 저장할 S3 버킷을 생성한다.
IAM 키를 이용하여 S3 버킷에 접근할 수 있으니 퍼블릭 엑세스는 차단하고 버킷을 생성한다.
그리고 .travis.yml 파일을 수정하면 된다.
...
before_deploy:
- zip -r springboot-webservice *
- mkdir -p deploy
- mv springboot-webservice.zip deploy/springboot-webservice.zip
deploy:
- provider: s3
access_key_id: $AWS_ACCESS_KEY # Travis repo settings 에 설정된 값
secret_access_key: $AWS_SECRET_KEY # Travis repo settings 에 설정된 값
bucket: springboot-webservice-build-zip # S3 버킷
region: ap-northeast-2
skip_cleanup: true
acl: private # zip 파일 접근을 private 으로
local_dir: deploy # before_deploy 에서 생성한 디렉토리
wait-until-deployed: true
# CI 실행 완료 시 메일로 알람
notifications:
email:
recipients:
nkb7714@naver.com
before-deploy 는 deploy 명령을 수행하기 전에 하는 작업이다.
우선 현재 위치에 있는 모든 파일을 springboot-webservice.zip 으로 압축한다.
그리고 deploy 폴더를 만들어 그 곳으로 이동시킨다.
deploy 는 빌드 후 어떤 작업을 할지 명령을 내리는 곳 이다.
springboot-webservice-build-zip 버킷에 키를 가지고 접속해 deploy 폴더에 있는 파일을 전부 전송하게 된다.
수정을 완료하고 커밋, 푸시를 하게 되면 S3 버킷에 zip 파일이 있는 것을 볼 수 있다.
🍣 CodeDeploy 를 통해 배포하기
S3 버킷에 jar 파일을 저장하는 것 까지 완료를 했으니 이제 CodeDeploy 가 파일을 가져와 EC2에 배포만 하면 된다.
그 전에 EC2 와 CodeDeploy 간 연동을 위해 IAM 역할을 추가해야 하는데 이 과정은
6) 스프링부트로 웹 서비스 출시하기 - 6. TravisCI & AWS CodeDeploy로 배포 자동화 구축하기
내가 실습하고 있는 책의 저자인 이동욱 님의 글을 보면 자세히 설명이 되어있다.
설정을 마치고 CodeDeploy 인스턴스를 생성했으면 EC2 서버에 CodeDeploy 에이전트를 설치해야 한다.
EC2 서버에 접속해 $ aws s3 cp s3://aws-codedeploy-ap-northeast2/latest/install . --region ap-northeast-2 를 입력하자
$ chmod +x install 을 통해 install 파일에 실행권한을 주고 $ sudo install auto 설치한다.
만약 폴더의 위치를 찾지 못하는 에러가 발생한다면 $ sudo yum install ruby 루비를 설치하고 진행하면 된다.
이제 Travis CI, S3, CodeDeploy 를 연동 할 시간이다.
CodeDeploy 는 appspec.yml 파일로 설정을 하는데 .travis.yml 파일과 같은 위치에 생성한다.
version: 0.0
os: linux
files:
- source: /
destination: /home/ec2-user/app/step2/zip/
overwrite: yes
source 는 가져올 파일, destination 은 가져올 위치를 의미한다.
루트를 입력하면 모든 파일을 가져온다.
즉 zip 파일을 /home/ec2-user/app/step2/zip/ 위치로 가져와 압축을 풀 것이다.
이 요청을 수행하기 위해 .travis.yml 파일을 수정한다.
...
deploy:
...
- provider: codedeploy
access_key_id: $AWS_ACCESS_KEY # Travis repo settings 에 설정된 값
secret_access_key: $AWS_SECRET_KEY # Travis repo settings 에 설정된 값
bucket: springboot-webservice-build-zip # S3 버킷
key: springboot-webservice.zip # 빌드 파일을 압축해서 전달
bundle_type: zip
application: springboot-webservice # 웹 콘솔에서 등록한 CodeDeploy 어플리케이션
deployment_group: springboot-webservice-group # 웹 콘솔에서 등록한 CodeDeploy 배포 그룹
region: ap-northeast-2
wait-until-deployed: true
...
이 과정까지 마치면 Travis CI, S3, CodeDeploy 의 연동이 끝난다.
🥘 배포 자동화
연동이 모두 끝났으니 배포까지 자동으로 해야한다.
서버에 두었던 deploy.sh 파일을 깃허브에 올려 CodeDeploy 가 스크립트를 실행하게 하려고 한다.
그렇게 되면 배포까지 자동으로 완료가 된다.
배포 스크립드 외에 다른 스크립트 파일을 만들 수도 있으니 scripts/deploy.sh 를 생성한다.
#!/bin/bash
REPOSITORY=/home/ec2-user/app/step2
PROJECT_NAME=springboot-webservice
echo "> Build 파일 복사"
cp $REPOSITORY/zip/*.jar $REPOSITORY/
echo "> 현재 구동중인 애플리케이션 pid 확인"
CURRENT_PID=$(pgrep -f ${PROJECT_NAME}.*.jar)
echo "현재 구동중인 어플리케이션 pid: $CURRENT_PID"
if [ -z "$CURRENT_PID" ]; then
echo "> 현재 구동중인 애플리케이션이 없으므로 종료하지 않습니다."
else
echo "> kill -15 $CURRENT_PID"
kill -15 $CURRENT_PID
sleep 5
fi
echo "> 새 어플리케이션 배포"
JAR_NAME=$(ls -tr $REPOSITORY/*.jar | tail -n 1)
echo "> JAR Name: $JAR_NAME"
echo "> $JAR_NAME 에 실행권한 추가"
chmod +x $JAR_NAME
echo "> $JAR_NAME 실행"
nohup java -jar \
-Dspring.config.location=classpath:/application.properties,classpath:/application-real.properties,/home/ec2-user/app/application-oauth.properties,/home/ec2-user/app/application-real-db.properties \
-Dspring.profiles.active=real \
$JAR_NAME > $REPOSITORY/nohup.out 2>&1 &
기존의 배포 스크립트와 거의 달라진 점은 없다.
이제 appspec.yml 을 수정 해 CodeDeploy 가 해당 스크립트를 실행하게 해야한다.
version: 0.0
os: linux
files:
- source: /
destination: /home/ec2-user/app/step2/zip/
overwrite: yes
permissions:
- object: /
pattern: "**"
owner: ec2-user
group: ec2-user
hooks:
ApplicationStart:
- location: deploy.sh
timeout: 60
runas: ec2-user
이렇게 하면 S3 에서 가져온 파일 중 deploy.sh 를 실행하게 된다.
deploy.sh 는 jar 파일을 실행시키는 스크립트였기 때문에 EC2 서버에서 스프링부트 프로젝트가 돌아가게 된다.
다시 한 번 자동 배포 과정을 정리하자면
코드 수정 후 푸시 → Travis CI 가 테스트 후 빌드 → 빌드 성공 시 파일을 압축 후 S3 버킷에 저장 → CodeDeploy 가 S3 버킷에 저장되어 있는 파일을 EC2 서버로 복사 → 복사 후 deploy.sh 스크립트 실행
배포 스크립트를 마지막으로 Travis CI, S3, CodeDeploy 를 통해 자동 배포 환경을 구축하였다.
자동 배포 환경이 잘 적용 되었는지 확인하기 위해 index.mustach 파일을 수정 하고 커밋, 푸시를 해보면 알 수 있다.
또 CodeDeploy 웹 콘솔로 접속하면 배포 상태와 에러가 발생했을시 에러 로그까지 볼 수 있으니 꼭 확인하자.
⛺️정리
푸시 후 자동 배포까지 구축을 하였다.
이렇게 스프링 부트와 AWS로 혼자 구현하는 웹 서비스 실습을 마치게 되었다.
웹 서비스를 어떻게 만들고 배포하는지 몰랐었는데 전체적인 과정을 알게되어 아주 재미있었다.
역시 모르더라도 한 번 따라서 해보는게 이해하는데는 가장 좋은 방법인 것 같다.
Leave a comment