코딩하는 문과생
[Spring boot] CI/CD - CI(지속적통합)(step2) 본문
※ 해당 글은 튜토리얼이 아닌 헷갈리거나 중요한 개념 위주로 정리한 글입니다.
[CI - 지속적 통합]
- CI: 지속적 통합, 개발한 코드가 버전관리 시스템(SVN, GIT)에 push가 되면 자동으로 테스트, 빌드가 이루어져 안정적인 배포파일을 만드는 과정
- CD: 지속적 배포, 빌드파일을 자동으로 운영 서버에 무중단 배포까지 진행하는 과정
[CI의 4대규칙]
- 누구든 현재 소스에 접근할 수 있는 단일지점을 유지할 것
- 누구든 시스템을 빌드하는 단일 명령어 사용할 수 있게 할 것
- 단일 명령어로 건전한 테스트 실행할 수 있게 할 것
- 누구나 현재 실행파일이 완전한 실행파일이게 확신하게 할 것
[Travis CI]
: CI툴, 깃허브와 연동되어 사용된다.
- 프로젝트 전체 흐름
* 빌드(2, 3, 4)는 Travis CI가, 배포(5)는 AWS CodeDeploy가 한다.
- 흐름
1. 프로젝트 설정
:Travis CI웹사이트 설정 + .travis.yml 파일(json에서 괄호를 제거한 것) 작성
language: java
jdk:
- openjdk8
branches:
only:
- master
# Travis CI 서버의 홈
cache: # 같은 의존성은 다음 배포 때부터 안 받는다.
directories:
- '$HOME/.m2/repository'
- '$HOME/.gradle'
script: "./gradlew clean build" # 브랜치 푸시시 수행하는 명령어
# CI 실행 완료 시 메일로 알림
notifications:
email:
recipients:
- sijune0525@gmail.com
* git push후 travis에 찍히는 빌드성공 로그를 확인한다.
2. Travis CI와 AWS S3연동
: AWS에 외부 서비스(Travis CI)가 접근하기 위해서는 AWS IAM이 필요
* IAM(Identity and Access Management): AWS 서비스의 접근 방식과 권한을 관리
* S3역할: aws의 파일 서버, Jar파일(빌드파일) 저장
- S3와 CodeDeploy에 접근할 수 있는 IAM를 생성한다.
- 발급받은 액세스키와 비밀키를 travis CI에 등록한다.(AWS_ACCESS_KEY, AWS_SECRET_KEY)
- 저장된 변수를 .travis.yml에서 사용이 가능하다.
- S3버킷 생성(모든 퍼블릭 액세스 차단, 외부에서 IAM을 사용해 접근 가능)
- .travis.yml 수정(S3에 빌드파일 올리는 코드 추가)
- git commit, push를 진행하면 빌드파일이 자동으로 생성되어 S3에 저장된다.
language: java
jdk:
- openjdk8
branches:
only:
- master
# Travis CI 서버의 홈
cache: # 같은 의존성은 다음 배포 때부터 안 받는다.
directories:
- '$HOME/.m2/repository'
- '$HOME/.gradle'
script: "./gradlew clean build" # 브랜치 푸시시 수행하는 명령어
before_deploy:
- zip -r blogProject * # 현재 경로 모든 파일 압축
- mkdir -p deploy # 현재 travis CI가 실행중인 위치에서 생성
- mv blogProject.zip deploy/blogProject.zip
deploy:
- provider: s3
access_key_id: $AWS_ACCESS_KEY
secret_access_key: $AWS_SECRET_KEY
bucket: blogproject-build
region: ap-northeast-2
skip_cleanup: true
acl: private # zip파일 접근을 private하게
local_dir: deploy # 해당위치만 S3로 전달
wait-until-deployed: true
# CI 실행 완료 시 메일로 알림
notifications:
email:
recipients:
- sijune0525@gmail.com
* travis-ci.org 는 2020년을 마지막으로 서비스를 중단하고, travis-ci.com 에서 똑같이 CI서비스 이용이 가능하다
* git push후 s3버킷 확인 완료
3. Travis와 aws s3, aws codedeploy 연동
- EC2가 codedeploy와 연동될 수 있게 EC2를 위한 IAM를 하나 더 생성한다.(AmazonEC2RoleforAWSCodeDeploy)
- 등록된 역할을 EC2에 등록한 후 재부팅을 한다.
- EC2내 Codedeploy Agent 설치 및 실행확인
- codedeploy에 사용할 IAM를 생성한다.(AWSCodeDeployRole)
- codedeploy생성, 이 때, 생성된 IAM를 부여하고, 배포그룹(EC2)을 연결시킨다.
- codedeploy에서 넘겨받은 파일을 저장할 폴더 생성(app/step2/zip)
- CodeDeploy의 설정 진행(appspec.yml): 저장할 폴더(app/step2/zip)를 지정
- .travis.yml에 codedeploy에 대한 설정 추가
- git push후 app/step2/zip폴더 내 파일 확인
* IAM: 외부서비스의 접근을 위한 "사용자"와 AWS 내부서비스 접근을 위한 "역할"로 분리된다.
* travis의 접근은 IAM사용자로 생성, codedeploy와 ec2간의 접근은 IAM역할로 생성한다.
-codedeploy 클라이언트 설치
$ aws s3 cp s3://aws-codedeploy-ap-northeast-2/latest/install . --region ap-northeast-2
$ chmod +x ./install
$ sudo ./install auto
$ sudo service codedeploy-agent statussudo service codedeploy-agent status
//서비스가 잘돌아가는 지 체크
- appspec.yml
version: 0.0
os: linux
files:
- source: /
destination: /home/ec2-user/app/step2/zip/
overwrite: yes
* source: codedeploy에서 전달해준 파일 중 destination으로 전달할 대상 지정, destination: 압축을 풀 위치
-.travis.yml
language: java
jdk:
- openjdk8
branches:
only:
- master
# Travis CI 서버의 홈
cache: # 같은 의존성은 다음 배포 때부터 안 받는다.
directories:
- '$HOME/.m2/repository'
- '$HOME/.gradle'
script: "./gradlew clean build" # 브랜치 푸시시 수행하는 명령어
before_deploy:
- zip -r blogProject * # 현재 경로 모든 파일 압축
- mkdir -p deploy # 현재 travis CI가 실행중인 위치에서 생성
- mv blogProject.zip deploy/blogProject.zip
deploy:
- provider: s3
access_key_id: $AWS_ACCESS_KEY
secret_access_key: $AWS_SECRET_KEY
bucket: blogproject-build
region: ap-northeast-2
skip_cleanup: true
acl: private
local_dir: deploy
wait-until-deployed: true
- provider: codedeploy
access_key_id: $AWS_ACCESS_KEY
secret_access_key: $AWS_SECRET_KEY
bucket: blogproject-build
key: blogProject.zip
bundle_type: zip
application: blogProject # codedeploy에 등록한 애플리케이션
deployment_group: blogProject-group # codedeploy에 등록한 배포그룹
region: ap-northeast-2
wati-until-deployed: true
# CI 실행 완료 시 메일로 알림
notifications:
email:
recipients:
- sijune0525@gmail.com
4. 배포자동화
: git push 시 자동으로 배포까지 진행
- step2 환경에서 실행될 deploy.sh 생성(프로젝트 내 scripts/deploy.sh), 그리고 git push
- .travis.yml 수정: jar파일, scripts파일만 압축되도록 수정
- appspec.yml 추가: 배포 주체 및 배포파일(ec2-user, deploy.sh) 추가
-deploy.sh
#!/bin/bash
REPOSITORY=/home/ec2-user/app/step2
PROJECT_NAME=blogProject
echo "> 빌드 파일 복사"
cp $REPOSITORY/zip/*.jar $REPOSITORY
echo "> 현재 구동중인 애플리케이션 pid확인"
CURRENT_PID=$(pgrep -fl blogProject | 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 &
-.travis.yml
language: java
jdk:
- openjdk8
branches:
only:
- master
# Travis CI 서버의 홈
cache: # 같은 의존성은 다음 배포 때부터 안 받는다.
directories:
- '$HOME/.m2/repository'
- '$HOME/.gradle'
script: "./gradlew clean build" # 브랜치 푸시시 수행하는 명령어
before_deploy:
# - zip -r blogProject * # 현재 경로 모든 파일 압축
# - mkdir -p deploy # 현재 travis CI가 실행중인 위치에서 생성
# - mv blogProject.zip deploy/blogProject.zip
- mkdir -p before-deploy
- cp scripts/*.sh before-deploy/
- cp appspec.yml before-deploy/
- cp build/libs/*.jar before-deploy/
- cd before-deploy && zip -r before-deploy *
- cd ../ && mkdir -p deploy
- mv before-deploy/before-deploy.zip deploy/blogProject.zip
deploy:
- provider: s3
access_key_id: $AWS_ACCESS_KEY
secret_access_key: $AWS_SECRET_KEY
bucket: blogproject-build
region: ap-northeast-2
skip_cleanup: true
acl: private
local_dir: deploy
wait-until-deployed: true
- provider: codedeploy
access_key_id: $AWS_ACCESS_KEY
secret_access_key: $AWS_SECRET_KEY
bucket: blogproject-build
key: blogProject.zip
bundle_type: zip
application: blogProject
deployment_group: blogProject-group
region: ap-northeast-2
wati-until-deployed: true
# CI 실행 완료 시 메일로 알림
notifications:
email:
recipients:
- sijune0525@gmail.com
-appspec.yml
version: 0.0
os: linux
files:
- source: /
destination: /home/ec2-user/app/step2/zip/
overwrite: yes
permissions: # codedeploy에서 ec2로 넘어온 모든파일에 권한 부여
- object:
pattern: "**"
owner: ec2-user
group: ec2-user
hooks:
ApplicationStart: # ec2-user권한으로 deploy.sh실행
- location: deploy.sh
timeout: 60
runas: ec2-user
그러나, 지속적통합 후 배포시 서비스가 중단되는 상황 발생 -> 무중단배포 필요
-codedeploy 참고사항
americanopeople.tistory.com/283
AWS CodeDeploy와 AWS CodeDeploy Agent (1) - 1. CodeDeploy
요즘 AWS CodeDeploy Agent 오픈소스 커미터되기 스터디를 하고 있다. AWS CodeDeploy Agent 코드를 분석하면서 알게 된 내용들을 틈틈이 정리해보고자 한다 👩🎓 1. CodeDeploy CodeDeploy의 기본적인 구..
americanopeople.tistory.com
※ 해당 글은 "스프링 부트와 AWS로 혼자 구현하는 웹 서비스(이동욱 저)"를 참고해 작성하였습니다.
'웹 프로그래밍 > Spring Boot' 카테고리의 다른 글
[Spring Boot] Spring Data JPA (0) | 2021.05.01 |
---|---|
[Spring Boot] CI/CD - CD(지속적 배포)(step3) (0) | 2020.12.13 |
[Spring boot] 프로젝트 AWS에 올리기(step1) (0) | 2020.12.10 |
[Spring Boot] AWS 아키텍처(+ HotSpot으로 연결 시 여러 이슈들) (0) | 2020.12.06 |
[Spring Boot] Spring Security (0) | 2020.12.06 |