반응형
CI & CD
- CI (Continuous Integration) - 지속적 통합
- CI를 통해 운영 서버에 무중단 배포까지 진행되는 과정을 CD (Continuous Deployment) - 지속적 배포라고 한다.
- CI,CD 를 이용하여 코드 병합, 배포를 자동화하여 생산성을 높일 수 있다.
CI 4원칙
- 모든 소스코드가 실행되고 누구든 접근할 수 있는 단일 지점 유지
- 빌드 프로세스를 자동화해서 누구든 소스로부터 시스템을 빌드하는 단일 명령어 사용 가능하게 할 것
- 테스팅 자동화로 단일 명령어로 시스템에 대한 테스트 수트를 실행할 수 있게 할 것
- 누구나 실행파일을 얻으면 가장 완전한 실행 파일을 얻었다는 확신을 하게 할 것
Travis CI 연동
- GitHub에서 제공하는 무료 CI 서비스 (젠킨스는 설치형으로 인스턴스가 하나 더 필요)
- https://travis-ci.com/ 에서 깃허브 계정으로 로그인
- 계정 - Settings -레포지토리 activate - 해당 화면이 나오면 설정 끝
프로젝트 설정
- .travis.yml 생성
language: java
jdk:
- openjdk8
branches:
only:
- master
before_install:
- chmod +x gradlew
# Travis CI 서버의 Home
cache:
directories:
- '$HOME/.m2/repository'
- '$HOME/.gradle'
script: "./gradlew clean build"
# CI 실행 완료시 메일로 알람
notifications:
email:
recipients:
- sasca37@naver.com
- .travis.yml에 메일정보 입력
- 커밋 성공시 해당 화면과 성공메일을 확인할 수 있다.
Travis CI 와 AWS S3 연동
- S3는 AWS에서 제공하는 파일 서버이다.
- 이미지 같은 정적 파일이나 배포 파일 등을 관리하는 기능 지원
- 다음과 같은 구조를 갖는다.
- 실제 배포는 AWS Code Deploy라는 서비스를 이용
- Code Deploy는 저장 기능이 없기 때문에 jar를 보관할 수 있는 S3 이용
- S3 없이 Code Deploy로 빌드와 배포를 할 수 있지만 모두 해야하므로 확장성이 떨어진다.
AWS Key 발급
- 일반적으로 AWS 서비스에 외부 서비스가 접근 할 수 없다.
- 접근 가능한 권한을 가진 Key를 생성하자. (IAM 서비스 : Identity and Access Management)
- IAM에 접속하여 사용자를 추가하자.
- 사용자이름, 프로그래밍 방식 엑세스 선택
- 기존 정책 직접 연결 - S3FullAccess 와 CodeDeployFullAccess 체크
- 태그 추가 (선택)
- 최종 설정 화면 - 다음 화면에서 키와 비밀 액세스키가 발급 된다.
Travis CI 키 등록
- Travis CI - Settings - Environment Variables 에 발급 받은 키값들을 넣는다.
- 이 키 값들은 .travis.yml에서 $AWS_ACCESS_KEY 와 같이 사용할 수 있다.
S3 버킷 생성
- s3 검색 - 버킷 만들기
- 퍼블릭 액세스를 모두 차단한다.
- 실제 서비스의 경우 Jar 파일이 퍼블릭일 경우 누구나 내려받을 수 있어서 보안상 위험하다.
.travis.yml 추가
language: java
jdk:
- openjdk8
branches:
only:
- master
before_install:
- chmod +x gradlew
# Travis CI 서버의 Home
cache:
directories:
- '$HOME/.m2/repository'
- '$HOME/.gradle'
script: "./gradlew clean build"
before_deploy:
- zip -r crawler-web * # 현재 위치의 모든 파일을 해당이름으로 압축
- mkdir -p deploy
- mv crawler-web.zip deploy/crawler-web.zip
deploy:
- provider: s3
access_key_id: $AWS_ACCESS_KEY # Travis repo settings에 설정된 값
secret_access_key: $AWS_SECRET_KEY # Travis repo settings에 설정된 값
bucket: crawler-springboot-build # 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:
- sasca37@naver.com
- before_deploy, deploy를 추가 후 깃 푸쉬
- Travis CI 에서 위와 같은 로그가 나오면 정상 실행
- S3 버킷도 정상 생성된 것을 확인
Travis CI, S3, CodeDeploy 연동
EC2 IAM 추가
- CodeDeploy를 이용하기 전에 EC2가 CodeDeploy를 연동 받을 수 잇게 IAM 역할 생성
- IAM - 액세스 관리 - 역할 - 역할 만들기 (역할은 AWS 서비스에서만 할당할 수 있는 권한(EC2, CodeDeploy, SQS 등)을 말한다.)
- AWS 서비스 - EC2 선택
- EC2RoleforAWSCodeDeploy 정책 선택
- 태그는 자유롭게 지정
- 최종 결과 화면
- EC2 이동 - 인스턴스 - 보안 - IAM 역할 수정 및 저장- 적용을 위해 재부팅
CodeDeploy 에이전트 설치
wget https://aws-codedeploy-ap-northeast-2.s3.ap-northeast-2.amazonaws.com/latest/install
chmod +x ./install
sudo yum install ruby
sudo ./install auto
sudo service codedeploy-agent status
- EC2에 접속한 후 다음 명령어를 입력
- 해당 결과가 출력되면 정상 동작
CodeDeploy 권한 생성
- IAM - 역할 생성 - CodeDeploy 선택
- 자유롭게 태그 생성 (선택)
- 최종 선택 화면
CodeDeploy 생성
- AWS 배포 삼형제
- Code Commit : 깃허브와 같은 코드 저장소 역할 - GitHub 대체
- Code Build : Travis CI와 같은 빌드용 서비스 - Travis CI 대체
- CodeDeploy : 배포용 서비스 (대체재가 없다.)
- CodeDeploy 검색 후 어플리케이션 생성 선택
- 생성 화면
- 해당 설정을 하고 마지막에 로드 밸런싱 활성화를 꺼주고 배포 그룹을 생성한다.
- 배포 구성은 몇 퍼센트씩 나눠서 배포할지 여부지만 1대를 사용하므로 기본값으로 가져가면 된다.
CI, S3, CodeDeploy 연동
mkdir ~/app/step2 && mkdir ~/app/step2/zip
- EC2 서버에 디렉토리 생성
- Travis CI에서 빌드가 끝나면 S3에 zip파일이 전송되고, 이 zip은 app/step2/zip으로 복사되어 압축을 푼다.
- Travis CI 설정은 .travis.yml로 진행
- CodeDeploy 설정은 appspec.yml로 진행
version: 0.0
os: linux
files:
- source: /
destination: /home/ec2-user/app/step2/zip/
overwrite: yes
- appspec.yml 정보
- version : 프로젝트 버전이 아니므로 0.0 버전 사용
- source : 지정된 파일을 받을 위치 , 이후 jar 실행하는 동안에는 destination에서 옮긴 파일들로 진행
- overwrite : 기존 파일 덮어씀
language: java
jdk:
- openjdk8
branches:
only:
- master
before_install:
- chmod +x gradlew
# Travis CI 서버의 Home
cache:
directories:
- '$HOME/.m2/repository'
- '$HOME/.gradle'
script: "./gradlew clean build"
before_deploy:
- zip -r crawler-web * # 현재 위치의 모든 파일을 해당이름으로 압축
- mkdir -p deploy
- mv crawler-web.zip deploy/crawler-web.zip
deploy:
- provider: s3
access_key_id: $AWS_ACCESS_KEY # Travis repo settings에 설정된 값
secret_access_key: $AWS_SECRET_KEY # Travis repo settings에 설정된 값
bucket: crawler-springboot-build
region: ap-northeast-2
skip_cleanup: true
acl: private # zip 파일 접근을 private으로
local_dir: deploy # before_deploy에서 생성한 디렉토리
wait-until-deployed: true
- provider: codedeploy
access_key_id: $AWS_ACCESS_KEY # Travis repo settings에 설정된 값
secret_access_key: $AWS_SECRET_KEY # Travis repo settings에 설정된 값
bucket: crawler-springboot-build
key: crawler-web.zip
bundle_type: zip
application: crawler-webservice
deployment_group: crawler-webservice-group # 웹 콘솔에서 등록한 CodeDeploy 배포 그룹
region: ap-northeast-2
wait-until-deployed: true
# CI 실행 완료시 메일로 알람
notifications:
email:
recipients:
- sasca37@naver.com
- .travis.yml 수정 (오타나면 골치 아프다.. )
- Travis CI 성공 화면
- CodeDeploy 배포 성공 화면
- EC2에서 cd /home/ec2-user/app/step2/zip 으로 프로젝트 최상단 파일이 있는지도 확인해주자.
배포 자동화
- step2 환경에서 실행될 deploy.sh 를 해당 경로에 생성
#!/bin/bash
REPOSITORY=/home/ec2-user/app/step2
PROJECT_NAME=crawler-web
echo "> Build 파일 복사"
cp $REPOSITORY/zip/*.jar $REPOSITORY/
echo "> 현재 구동중인 애플리케이션 pid 확인"
CURRENT_PID=$(pgrep -fl crawler-service | grep java | 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 &
- deploy.sh
language: java
jdk:
- openjdk8
branches:
only:
- master
before_install:
- chmod +x gradlew
# Travis CI 서버의 Home
cache:
directories:
- '$HOME/.m2/repository'
- '$HOME/.gradle'
script: "./gradlew clean build"
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/crawler-web.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: crawler-springboot-build
region: ap-northeast-2
skip_cleanup: true
acl: private # zip 파일 접근을 private으로
local_dir: deploy # before_deploy에서 생성한 디렉토리
wait-until-deployed: true
- provider: codedeploy
access_key_id: $AWS_ACCESS_KEY # Travis repo settings에 설정된 값
secret_access_key: $AWS_SECRET_KEY # Travis repo settings에 설정된 값
bucket: crawler-springboot-build
key: crawler-web.zip
bundle_type: zip
application: crawler-webservice
deployment_group: crawler-webservice-group # 웹 콘솔에서 등록한 CodeDeploy 배포 그룹
region: ap-northeast-2
wait-until-deployed: true
# CI 실행 완료시 메일로 알람
notifications:
email:
recipients:
- sasca37@naver.com
- .travis.yml 에 before_deploy 수정
- 배포에 필요한 파일들만 설정
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 # 엔진엑스와 연결되어 있지 않은 Port로 새 버전의 스프링 부트를 시작합니다.
timeout: 60
runas: ec2-user
- appspec.yml 파일 수정
- 깃 푸쉬 후 Travis CI 정상 실행 화면
- CodeDeploy 에서도 정상 배포 확인
- nohup.out 파일에서 정상 실행 확인 (여기까지 성공 시 배포자동화 완료)
테스트 방법
- IDE의 build.gradle, 화면 수정 -> 깃 푸쉬 -> Travis CI 정상 실행 확인 -> CodeDeploy 정상 배포 확인 -> 배포 자동화 화면 확인
- CodeDeploy에서 배포파일은 만들었지만 자동화 무반응 또는 whitelabel 발생 시
- CodeDeploy 로그 찾는 방법 : cd /opt/codedeploy-agent/deployment-root 로 찾아가서 오류 내용 확인
본 포스팅은 프리렉-이동욱님의 '스프링 부트와 AWS로 혼자 구현하는 웹 서비스' 책을 참고하였습니다.
반응형