스프링부트로 웹 서비스 출시하기 5일차

박세건·2023년 8월 21일
0

IAM 역할 생성

EC2가 CodeDeploy를 연동 받을 수 있게 IAM 역할을 생성
마찬가지로 CodeDeploy에서 EC2에 접근하기위해서도 역할 생성

IAM의 역할과 사용자 차이

AWS 서비스 외에 사용할 수 있는 권한을 주고싶다면 IAM의 '사용자'를 사용하고
AWS 서비스에서만 할당할 수 있는 권한을 주고 싶다면 IAM의 '역할' 을 사용
때문에 이전에 travis CI 에게 권한을 주기위해서는 IAM의 사용자를 사용

먼저 EC2가 CodeDeploy를 연동 받을 수 있게 역할을 만들어주고
EC2를 접속해서 CodeDeploy 에이전트를 설치해줍니다.

  • EC2를 위해 만들어 놓은 역할을 해당 EC2에 추가

명령어와 코드 등은 제가 이전에 공부하고 있다고한 블로그에 있습니다
CodeDeploy 에이전트를 성공적으로 설치해주었다면 권한을 생성합니다.
이때 마찬가지로 CodeDeploy에서 EC2에 접근하기위해서도 역할 생성

AWS에는 배포 삼형제가 있다

  • Code Commit
  • Code Build
  • CodeDeploy
    Code Commit의 역할은 깃허브로 CodeBuild의 역할은 Travis로 진행하고있기때문에 CodeDeploy를 사용해보자

CodeDeploy 생성

AWS로 이동해서 CodeDeploy를 생성한다.

deploy를 생성했다면 이제 만들어진 CodeDeploy를 Travis CI와 연동한다
이렇게 되면 Travis CI, S3, CodeDeploy 이렇게 세가지가 연동하게된다

  • Travis CI 는 S3에게 jar 파일을 전달
  • S3는 AWS CodeDeploy에게 jar 파일을 전달
  • Travis CI 는 AWS CodeDeploy에게 배포 요청
    결론적으로 AWS CodeDeploy가 AWS EC2에게 배포

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로 전달하는 과정에서 오류 발생

상세보기

오류 발생
각각의 상황들을 확인해봤다.

  • appspec.yml 파일 에러 (오타, 들여쓰기 등)
  • CodeDeploy 그룹의 태그를 잘못 입력함 (키를 Name이 아닌 임의의 값으로 설정)
  • .travis.yml 파일 에러 (오타)
  • codedeploy-agent가 실행되지 않았는지
    알고보니 codedeploy-agent log 를 확인할 수 있었다.
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의 퍼블릭 도메인 주소로 접속하면

에러가 발생했다 다음 게시글에서 해결해보자.

profile
멋있는 사람 - 일단 하자

0개의 댓글