EC2가 CodeDeploy를 연동 받을 수 있게 IAM 역할을 생성
마찬가지로 CodeDeploy에서 EC2에 접근하기위해서도 역할 생성
AWS 서비스 외에 사용할 수 있는 권한을 주고싶다면 IAM의 '사용자'를 사용하고
AWS 서비스에서만 할당할 수 있는 권한을 주고 싶다면 IAM의 '역할' 을 사용
때문에 이전에 travis CI 에게 권한을 주기위해서는 IAM의 사용자를 사용
먼저 EC2가 CodeDeploy를 연동 받을 수 있게 역할을 만들어주고
EC2를 접속해서 CodeDeploy 에이전트를 설치해줍니다.
명령어와 코드 등은 제가 이전에 공부하고 있다고한 블로그에 있습니다
CodeDeploy 에이전트를 성공적으로 설치해주었다면 권한을 생성합니다.
이때 마찬가지로 CodeDeploy에서 EC2에 접근하기위해서도 역할 생성
AWS에는 배포 삼형제가 있다
AWS로 이동해서 CodeDeploy를 생성한다.
deploy를 생성했다면 이제 만들어진 CodeDeploy를 Travis CI와 연동한다
이렇게 되면 Travis CI, S3, CodeDeploy 이렇게 세가지가 연동하게된다
Travis CI 설정은 .travis.yml로 진행했다면
CodeDeploy의 설정은 appspec.yml 로 진행한다.
appspec.yml
version: 0.0
os: linux
files:
- source: /
destination: /home/ec2-user/app/travis/build/
.travis.yml 도 CodeDeploy에 대한 설정을 추가해야되기때문에 수정
language: java
jdk:
- openjdk8
branches:
only:
- master
# Travis CI 서버의 Home
cache:
directories:
- '$HOME/.m2/repository'
- '$HOME/.gradle'
script: "./gradlew clean build"
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-deploy # S3 버킷
region: ap-northeast-2
skip_cleanup: true
acl: public_read
local_dir: deploy # before_deploy에서 생성한 디렉토리
wait-until-deployed: true
on:
repo: jojoldu/springboot-webservice
branch: master
#추가부분
- provider: codedeploy
access_key_id: $AWS_ACCESS_KEY # Travis repo settings에 설정된 값
secret_access_key: $AWS_SECRET_KEY # Travis repo settings에 설정된 값
bucket: springboot-webservice-deploy # S3 버킷
key: springboot-webservice.zip # S3 버킷에 저장된 springboot-webservice.zip 파일을 EC2로 배포
bundle_type: zip
application: springboot-webservice # 웹 콘솔에서 등록한 CodeDeploy 어플리케이션
deployment_group: springboot-webservice-group # 웹 콘솔에서 등록한 CodeDeploy 배포 그룹
region: ap-northeast-2
wait-until-deployed: true
on:
branch: main
notifications:
email:
recipients:
- qkrtprjs456@naver.com
즉! travis가 빌드를 시킨후에 S3의 버킷에게 빌드한 결과를 압축해서 저장한다.
CodeDeploy는 S3버킷에 저장된 파일을 확인하고 해당 압축파일을 EC2로 전달한다.
S3에 빌드된 파일을 압축해서 저장하는 것은 성공했으나 이 파일을 CodeDeploy가 갖고와서 EC2로 전달하는 과정에서 오류 발생
상세보기
오류 발생
각각의 상황들을 확인해봤다.
vim /var/log/aws/codedeploy-agent/codedeploy-agent.log 확인
처음으로 발생한
Error polling for host commands::Aws::CodeDeployCommand::Errors::AccessDeniedException
를 알아보았다
알아보던중블로그를 발견했는데 여기서' 인스턴스에 기존 AWS 자격 증명 파일이 저장되어있어 IAM 정보를 제대로 못 가져오는 현상이 있을 수 있다고 합니다.'라고 알려주었고 따라서
# AWS 자격증명 파일 삭제
$ sudo rm -rf /root/.aws/credentials
# codedeploy-agent 재시작
$ sudo systemctl restart codedeploy-agent
진행해보니
travis CI 이상 없고
S3 정상적으로 압출 파일 저장
CodeDeploy에서도 오류 없이 정상적으로 배포 성공
이제 EC2에 들어가서 정상적으로 CodeDeploy가 파일을 전달해주었는지 확인해보자!!
EC2에 정상적으로 파일들이 전달이 되었다!
- Travis CI 는 S3에게 jar 파일을 전달
- S3는 AWS CodeDeploy에게 jar 파일을 전달
- Travis CI 는 AWS CodeDeploy에게 배포 요청
- AWS CodeDeploy가 AWS EC2에게 배포
이 모든 과정이 해결되었고 성공했다. 감사합니다!
Travis CI, S3, CodeDeploy 연동 까지 완료했기때문에 이것을 기반으로 실제 Jar를 배포해서
실행해보자!
먼저 이전에 만들었던 것 처럼 deploy.sh 를 생성
이전에는 쉘 스크립트로 pull하고 build 를 직접 해줘서 진행했던것을 이제는 travis가 해주기때문에 제거 하고 Jar를 실행하는데에 몇가지 코드를 추가했다.
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 -fl springboot-webservice | grep jar | awk '{print $1}')
#pgrep -fl springboot-webservice | grep jar -> 애플리케이션 이름으로된 jar 프로그램 찾기
#awk '{print $1}' -> 해당 ID를 찾는다.
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 설정은 모든 파일을 zip 파일로 만들어서 S3에게 전달했지만 실제로 필요한 파일 외에도 많은 필요하지않는 파일들도 같이 보내지게된다 이를 꼭 필요한 파일들만 묶어서 보내도록 수정한다.
.travis.yml 수정
- zip -r springboot-webservice *
- mkdir -p deploy
- mv springboot-webservice.zip deploy/springboot-webservice.zip
에서
before_deploy:
- mkdir -p before-deploy # travis에서 S3로 특정파일만 업로드는 불가하기때문에 항상 디렉토리 생성 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/springboot-webservice.zip # deploy로 zip파일 이동 #만들어놓은 deploy폴더로 before-deploy/before-deploy.zip파일 이동
appspec.yml 수정
version: 0.0
os: linux
files:
- source: /
destination: /home/ec2-user/app/step3/zip/
overwrite: yes
#CodeDeploy에서 EC2 서버로 넘겨준 파일들 모두 ec2-user 권한을 갖도록 한다
permissions:
- object: /
pattern: "**"
owner: ec2-user
group: ec2-user
#CodeDeploy 배포 단계에서 실행할 명령어 지정 -> CodeDeploy가 jar 파일을 실행시키기위함 즉 deploy.sh 를 실행시키기위함
hooks:
ApplicationStart:
- location: deploy.sh
timeout: 60
runas: ec2-user
모두 수정했으면 이제 Travis CI 가 빌드해서 S3에게 빌드한 파일중에 CodeDeploy가 필요한 파일을 골라서 S3에게 넘겨주고 CodeDeploy가 S3에 저장된 파일을 읽고 deploy.sh라는 쉘스크립트 파일을 읽어서 빌드파일을 복사하고 jar 파일을 제대로 실행시켜서 애플리케이션을 실행시키는지 확인하자
->빌드와 테스트, 배포 모두 이상없이 진행되었지만 EC2의 퍼블릭 도메인 주소로 접속하면
에러가 발생했다 다음 게시글에서 해결해보자.