CheerUp_Cheers
스프링 부트 - (9) 코드가 푸시되면 자동배포(Travis CI 배포 자동화) 본문
스프링 부트 - (9) 코드가 푸시되면 자동배포(Travis CI 배포 자동화)
meorimori 2020. 4. 24. 12:56#앞에서의 방식의 문제점
- 수동실행되는 Test
본인의 코드가 다른 개발자 코드에 영향 없는지 전체 테스트 수행.
현재 상태는 항상 개발자가 작업을 하고, 수동으로 전체 테스트 수행
- 수동 Build
다른 사람이 작성한 브랜치와 본인이 작성한 브랜치가 합쳐졌을 때(Merge) 이상없는지는 빌드를 수행해야 암.
이를 매번 개발자가 직접 실행
=> 깃허브에 푸시하면 자동으로 Test & Builde & Deploy를 진행되도록 하자!
9.1 CI & CD 소개
- CI(Continuous Intergration - 지속적인 통합)
코드 버전 관리를 하는 VCS 시스팀(Git, SVN)에 푸시 시에
테스트와 빌드가 자동수행 되어 안정적인 배포를 만드는 과정
- CD(Continuouse Deployment - 지속적인 배포)
이 빌드 결과를 자동으로 운영 서버에 무중단 배포까지 진행되는 과정
#CI의 4가지 규칙(마틸 파울러)
- 모든 소스코드가 살아있고, 누구든 현재의 소스에 접근할 수 있는 단일 지점을 유지할것.
- 빌드 프로세스를 자동화해서 누구든 소스로부터 시스템을 빌드하는 단일 명령어를 사용할 수 있게 할것.
- 테스팅을 자동화해서 단일 명령어로 언제든지 시스템에 대한 건전한 테스트 수트를 실행할 것.
- 누구나 현재 실행파일을 얻으면 지금까지 가장 완전한 실행파일을 얻었따는 확인을 하게 할 것.
=> 가장 중요한 것은 테스팅 자동화(완전한 상태임을 보장하기 위한 테스트 코드)
9.2 Travis CI 연동하기
[1] Travis CI
깃허브에서 제공하는 무료 CI서비스(오픈소스 웹 서비스 = 미설치)
- https://travis-ci.org/에서 서 깃허브 계정으로 로그인을 한 뒤, 왼쪽 위에[계정명 -> Settings] 클릭.
- 해당 저장소를 활성화.
[2] 프로젝트 설정
프로젝트의 YML(야믈)파일로 진행.
JSON에서 괄호를 제거한 것
build.gradle과 같은 위치에서 .travis.yml을 생성한후 코드를 추가.
#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:
- wotjd4305@naver.com
- branches
Travis CI를 어느 브랜치가 푸시될 때 수행할지 지정함.
현재는 오직 master 브랜치에 푸시 될 때.
- cache
그레이들을 통해 의존성을 받게 되면 이를 해당 디렉토리에 캐시
같은 의존성은 다음 배포 때부터 다시 받지 않도록 설정.
- script
master 브랜치에 푸시되었을 때 수행하는 명령어.
여기서는 프로젝트 내부에 둔 gradlew을 통해 clean & build를 수행
- notifications
Travis CI 실행 완료 시, 자동으로 알람이 가도록 설정.
#여기 까지 한후, master 브랜치에 커밋과 푸시
Travis CI 저장소 페이지를 확인.
https://travis-ci.com/github/wotjd4305/com.jojodu.book/builds
(!) 오류가 뜸..
권한을 주자.
./travis.yml 에 추가
before_install:
- chmod +x gradlew
9.3 Travis CI와 AWS S3 연동하기
#S3
AWS에서 제공하는 일종의 파일 서버.
이미지 파일을 비롯한 정적인 파일을 관리.
ex) 보통 이미지 업로드를 구현,
=> 필요한 이유? Jar파일을 전달하기 위해서
[1] AWS Key 발급.
일반적으로 AWS 서비스에 외부 서비스가 접근할 수 없다.
-> 접근가능한 권한을 가진 Key를 생성해서 사용.(= IAM 서비스)
- CodeDeploy
AWS의 실제 배포 서비스
- IAM
AWS에서 제공하는 서비스의 접근 방식과 권환을 관리.
IAM을 통해 Travis CI가 AWS의 S3와 CodeDeploy에 접근 할수 있도록 해볼것.
1) AWS 웹콘솔 > IAM 검색 및 이동 > IAM페이지 왼쪽 사이드바[사용자 -> 사용자 추가]
다음 입력.
2) 권환 설정 방식 > 기존 정책 직접 연결
3) 정책검색
S3FULLAccess 권한 추가
CodeDeploy 권한 추가
4) 태그등록
5)Tracvis CI 생성.
엑세스키 생성.
비밀 엑세스키 생성.
[2] Travis CI 키 등록
- TravisCI의 설정 화면으로 이동
https://travis-ci.com/github/wotjd4305
- Setting > Environmet Variables 입력
여기서 등록된 값들은 $AWS_ACCESS_KEY, $AWS_SECRET_KEY로 사용.
이제는 이 키를 관리할 S3 버킷 생성.
[3] S3 버킷 생성
S3는 AWS의 일종의 파일 서버.
- S3 검색 후, 버킷 만들기.
- 버킷 버전 관리(걍 넘어가)
- 버킷의 보안과 권한 설정
모든 차단.
jar파일이 퍼블릭일 경우, 누구나 내려받아 코드의 설정값과 주요키값들이 탈취.
퍼블릭이 아니더라도 우리는 IAM 사용자로 발급받은 키를 사용 -> 접근가능
[4]travis.yml 추가
.travis.yml에 코드를 더 추가.
before_deploy:
- mkdir -p deploy # zip에 포함시킬 파일들을 담을 디렉토리 생성
- zip -r freelec-springboot2-webservice *
- mv freelec-springboot2-webservice.zip deploy/freelec-springboot2-webservice.zip # deploy로 zip파일 이동
deploy:
- provider: s3
access_key_id: $AWS_ACCESS_KEY # Travis repo settings에 설정된 값
secret_access_key: $AWS_SECRET_KEY # Travis repo settings에 설정된 값
bucket: freelect-springboot-build # S3 버킷
region: ap-northeast-2
skip_cleanup: true
acl: private # zip 파일 접근을 private으로
local_dir: deploy # before_deploy에서 생성한 디렉토리
wait-until-deployed: true
- before_deploy
deploy 명령어가 실행되기 전에 수행.
codeDeploy는 jar파일은 인식 못함, JAR+기타 설정 파일들을 모아 압축.
- zip -r freelec-springboot2-webservice
현재 위치의 모든 파일을 freelec-springboot2-webservice 이름으로 압축.
명령어의 마지막 위치는 본인의 프로젝트 이름.
- mv~
freelec-springboot2-webservice.zip파일을 deploy/~으로 이동.
- deploy
S3로 파일 업로드 혹은 CodeDeploy로 배포 등 외부서비스와 연동될 행위들을 선언
- local_dir:deploy
앞에서 생성한 디플로이 디렉토리를 지정.
해당 위치의 파일들만 S3로 전송
[5] 푸시
(!) 오류
uploading "freelec-springboot2-webservice.zip" with {:content_type=>"application/zip", :acl=>"private"}
504Oops, It looks like you tried to write to a bucket that isn't yours or doesn't exist yet. Please create the bucket before trying to write to it.
->라는 오류
bucket: freelec-springboot-build -> bucket: freelect-springboot-build
내가 만든 S3버켓은 철자가 달랏다..
9.4 Travis CI와 AWS S3, CodeDeploy 연동하기
[1]EC2에 CodeDeploy 연동
EC2가 CodeDeploy 연동 받을 수 있게 IAM 역할 생성.
- 역할
AWS 서비스에만 할당할 수 있는 권한.
EC2, CodeDeploy. SQS등
- 사용자
AWS 서비스 외에 사용할 수 있는 권한
로컬PC, IDC 서버등
=> EC2에서 권한을 사용하기 떄문에, 역할로 처리
#AWS서비스 > EC2 > 다음.
다음을 선택, 태그네임 설정
#역할을 EC2 서비스에 등록하기.
- EC2 인스턴스 목록 > 인스턴스 설정(인스턴스 오른쪽 클릭) > IAM 역할 연결/바꾸기
- 적용하기.
- EC2 재부팅!
[2] CodeDeploy 에이전트 설치
EC2 접속해서 다음 명령어 입력
aws s3 cp s3://aws-codedeploy-ap-northeast-2/latest/install . --region ap-northeast-2
chmod +x ./install로 실행권한을 추가
install파일로 설치 진행
chmod +x ./install
sudo ./install auto
Agent가 정상적으로 실행되는지 상태 검사.
sudo service codedeploy-agent status
[3] CodeDeploy를 위한 권한 생성
CodeDeploy에서 EC2에 접근하려면 권한 필요.
AWS서비스이니 IAM역할 생성.
#IAM 역할 생성
IAM > AWS 서비스 > CodeDeploy
아까 처럼 역할 생성.
[4] CodeDeploy 생성
#배포의 삼형제..
- Git Hub
커밋용 서비스.
- Travis CI
빌드용 서비스
- CodeDeploy
배포용 서비스.
#CodeDeploy 만들기
- CodeDeply서비스 > 시작 > 애플리케이션 생성.
입력.
# 배포 그룹 생성.
- 배포 유형
현재 위치 : 한대의 EC2(우리는 한대의 EC2를 사용.)
블루/그린 : 2대이상의 EC2
- 배포 설정
배포 구성 : 한번 배포할 때 몇 대의 서버에 배포할지를 결정.
2대이상이라면 1대씩 배포할 지, 30% 혹은 50%로 나눠서 배포할지
CodeDeployDefault.AllAtoOnce는 한번에 다 배포 한다는 의미.
[5] Travis CI, S3, CodeDeploy 연동
# S3에서 넘겨줄 ZIP 파일을 저장할 디렉토리 생성.
이 디렉토리는 Travis CI가 빌드를 끝내고 만든 zip파일을 풀 장소.
mkdir ~/app/step2 && mkdir ~/app/step2/zip
# Travis CI 설정
.travis.yml로 진행.
코드 추가.
- provider: codedeploy
access_key_id: $AWS_ACCESS_KEY # Travis repo settings에 설정된 값
secret_access_key: $AWS_SECRET_KEY # Travis repo settings에 설정된 값
bucket: freelect-springboot-build # S3 버킷
key: freelec-springboot2-webservice.zip # 빌드 파일을 압축해서 전달
bundle_type: zip
application: freelec-springboot2-webservice # 웹 콘솔에서 등록한 CodeDeploy 어플리케이션
deployment_group: freelec-springboot2-webservice-group # 웹 콘솔에서 등록한 CodeDeploy 배포 그룹
region: ap-northeast-2
wait-until-deployed: true
# AWS CodeDeploy 설정
appspec.yml로 진행
version: 0.0
os: linux
files:
- source : /
destinantion: /home/ec2-user/app/step2/zip/
overwrite: yes
- version
CodeDeploy 버전을 이야기.
프로젝트 버전이 아님으로 다른버전을 사용하면 오류.
- source
CodeDeploy에서 전달 해 준 파일 중 destination으로 이동시킬 대상을 지정.
루트경로(/)를 사용시 전체 파일 이야기.
#Commit 후, EC2에 파일 확인.
cd ~/app/step3/zip
ll
9.5 배포 자동화 구성
이번에는 Jar를 배포하여 실행까지 해보자!
[1] deploy.sh 파일 추가
step2 환경에서 실행될 deploy.sh 생성.
script 디렉토리를 생성 후, 스크립트 생성.
#!/bin/bash
REPOSITORY=/home/ec2-user/app/step2
PROJECT_NAME=freelec-springboot2-webservice
echo "> Build 파일 복사"
cp $REPOSITORY/zip/*.jar $REPOSITORY/
echo "> 현재 구동중인 애플리케이션 pid 확인"
CURRENT_PID=$(pgrep -fl freelec-springboot2-webservice | grep jar | awk '{print $1}')
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 &
- CURRENT_PID
현재 수행 중이 스프링 부트 애플리케이션의 프로세스 ID 찾기.
실행 중이면, 종료
(pgrep -fl freelec-springboot2-webservice | grep jar | awk '{print $1}')
pgrep : freelec~이라는 이름의 프로그램 찾고
awk : 프로세스를 찾은 뒤, 아이디를 찾는다
- $JAR_NAME > $REPOSITORY/nohup.out 2>&1 &
nohup 실행 시, CodeDeploy는 무한대기 -> nohup 파일을 표준 입출력 용도로 사용
이렇게 안하면, nohup파일도 생기지 않고, CodeDeploy로그에 표준 입출력이 출력.
nohup이 끝나기전에 CodeDeploy도 끝나지 않으니 이렇게 해야함.
=>직접 빌드 했던 부분을 제거하고, Jar를 실행하는 단계에서 몇가지 코드가 추가.
[2].travis.yml 파일 수정
zip파일을 만드는데 필요한 것은 Jar, appsepc.yml, 배포를 위한 스크립트.
before_deploy:
- mkdir -p before-deploy # zip에 포함시킬 파일들을 담을 디렉토리 생성
- cp scripts/*.sh before-deploy/
- cp appspec.yml before-deploy/
- cp build/libs/*.jar before-deploy/
- cd before-deploy && zip -r before-deploy * # before-deploy로 이동후 전체 압축
- cd ../ && mkdir -p deploy # 상위 디렉토리로 이동후 deploy 디렉토리 생성
- mv before-deploy/before-deploy.zip deploy/freelec-springboot2-webservice.zip # deploy로 zip파일 이동
- Travis CI는 S3로 특정파일만 업로드가 안됨.
디렉토리 단위로만 업로드할 수 있기 떄문에 deploy 디렉토리를 항상 생성.
- before-deploy에는 zip파일에 포함시킬 파일들을 저장.
- zip - r 명령어를 통해 before-deploy 디렉토리 전체파일을 압축.
[3]appspec.yml 파일 수정
CodeDeploy의 명령을 담당할 appsepc.yml 파일.
appspec.yml 파일에 다음 코드를 추가.
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
- permissions
CodeDeploy에서 EC2 서버로 넘겾둔 파일들을 모두 ec2-user 권한을 갖도록 함.
- hooks
CodeDeploy 배포 단계에서 실행할 명령어를 지정.
Application 실행된 단계에서 deploy.sh를 ec2-user 권한으로 실행하게 합니다.
[4] 실제 배포 과정 체험
#build.gradle 프로젝트 버전 변경
version '1.0.1-SNAPSHOT'
#index.nbs내용 변경
9.6 CodeDeploy 로그 확인
AWS 서비스에서 제공하는 오류는 확인이 어려움.
CodeDeploy의 대부분 로그는 /opt/codedeploy-agent/deployment-root에 있음.
해당 디렉토리로 이동 (cd/opt/codedeploy-agent/deployment-root)
cd/opt/codedeploy-agent/deployment-root
ll
- ef3fe~ef3fe2a1-4b3d-4ad9-9546-5fc4c2450a5f
CodeDeploy ID임.
해당 디렉토리에는 배포한 단위별로 배포 파일들이 있음.
본인의 배포파일이 정상적으로 왔는지 확인.
- deployment-logs
CodeDeploy 로그 파일.
CodeDeploy로 이루어지는 배포 내용 중 표준 입/출력은 모두 여기 담김
작성한 echo도 표기.
=> Master 브랜치에 푸시만 하면 자동으로 EC2에 배포되는 작업이 완료
'서적 공부 > 스프링부트 - [스프링부트와 AWS로 혼자 구현하는 웹서비스]' 카테고리의 다른 글
스프링 부트 - (8) EC2 서버에 프로젝트 배포 (0) | 2020.04.22 |
---|---|
스프링 부트 - (7) AWS RDS (0) | 2020.04.08 |
스프링 부트 - (6) AWS 서버 환경을 만들어 보자 (0) | 2020.04.07 |
스프링 부트 - (5) 스프링 시큐리티와 OAuth 2.0으로 로그인 기능 구현하기 (0) | 2020.03.24 |
스프링 부트 - (4) 머스테치로 화면 구성하기 (0) | 2020.03.23 |