Travis CI와 AWS S3 연동하기

dawn·2021년 5월 31일
0

인프런

목록 보기
7/11

일반적으로 AWS 서비스에 외부 서비스가 접근할 수 없다.
그러므로 접근 가능한 권한을 가진 Key를 생성해서 사용해야 한다. AWS에서는 이러한 인증과 관련된 기능을 제공하는 서비스로 IAM이 있다.
IAM은 AWS에서 제공하는 서비스의 접근 방식과 권한을 관리한다. 이 IAM을 통해 Travis CI가 AWS의 S3와 CodeDeploy에 접근할 수 있도록 해보겠다. (RDS는...?)

1. AWS 키 발급하기

IAM의 왼쪽 사이드바에서 [사용자] -> [사용자 추가]버튼 클릭


+실제 서비스 회사에서는 권한도 S3와 CodeDeploy를 분리해서 관리하기도 하지만, 여기서는 간단하게 둘을 합쳐서 관리한다.

최종 생성 완료되면 엑세스 키와 비밀 엑세스 키가 생성되는데 이 두 값이 Travis CI에서 사용될 키이다.

1-1. Travis CI에 키 등록


여기에 등록된 값들은 이제 .travis.yml에서 $AWS_ACCESS_KEY, $AWS_SECRET_KEY란 이름으로 사용할 수 있다.
그럼 이제 이 키를 사용해서 jar를 관리할 S3버킷을 생성하겠다.

2 S3 버킷 생성

AWS의 S3서비스는 일종의 파일서버이다. 순수하게 파일들을 저장하고 접근 권한을 관리, 검색 등을 지원하는 파일 서버의 역할을 하낟.
S3는 보통 게시글을 쓸 떄 나오는 첨부파일 등록을 구현할 때 많이 이용한다. 여기서는 Travis CI에서 생성된 Build 파일을 저장하도록 구성하겠다. S3에 저장된 Build 팡리은 이후 AWS의 CodeDeploy에서 배포할 파일로 가져가도록 구성할 예정이다.

AWS에서 S3검색 -> [버킷 만들기] 클릭

버킷명은 이 버킷에 배포할 Zip 파일이 모여있는 장소임을 의미하도록 짓는 것을 추천!


버킷의 보안과 권한 설정 부분에서 모든 차단을 해야 한다. 실제 서비스에서 Jar파일이 퍼블릭일 경우 누구나 내려받을 수 있어 코드나 설정값, 주요 키값들이 다 탈취될 수 있다.
퍼블릭이 아니더라도 우리는 IAM 사용자로 발급받은 키를 사용하니 접근 가능하다.

2-1. .travis.yml 추가

S3가 생성되었으면 이 S3로 배포파일을 전달하자.
Travis CI에서 빌드하여 만든 Jar파일을 S3에 올릴 수 있도록 .travis.yml을 수정하자.

language: java
jdk:
  - openjdk11

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 hello-spring *
  - mkdir -p deploy
  - mv hello-spring.zip deploy/hello-spring.zip

deploy:
  - provider: s3
    access_key_id: $AWS_ACCESS_KEY # Travis repo settings에 설정된 값
    secret_access_key: $AWS_SECRET_KEY # Travis repo settings에 설정된 값
    bucket: hello-spring-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+기타 설정 파일들을 모아 압축한다.
  • mkdir -p deploy

    • deploy라는 디렉토리를 Travis CI가 실행 중인 위치에서 생성한다.
  • deploy

    • S3로 파일 업로드 혹은 CodeDeploy로 배포 등 외부 서비스와 연동될 행위들을 선언한다.
  • local_dir: deploy

    • 앞에서 생성한 deploy 디렉리를 지정한다.

    • 해당 위치의 파일들만 S3로 전송한다.


      설정이 다 되었으면 깃허브로 push한다. Travis CI에서 자동으로 빌드가 진행되는 것을 확인하고, 모든 빌드가 성공하는지 확인한다. 이제는 CodeDeploy로 배포까지 완료해보자.
      들여쓰기를 잘못했더니 build가 안됐었다. 들여쓰기 하나때문에ㅜ

    3. Travis CI와 AWS S3, CodeDeploy 연동하기

    AWS의 배포 시스템인 CodeDeploy를 이용하기 전에 배포 대상인 EC2가 CodeDeploy를 연동 받을 수 있게 IAM 역할을 하나 생성하자.

    3-1. EC2에 IAM역할 추가하기

    3-1-1. AWS의 IAM에서 [역할] -> [역할 만들기] 버튼 클릭

    +IAM의 사용자와 역할의 차이

  • 역할

    • AWS 서비스에만 할당할 수 있는 권한
    • EC2, CodeDeploy, SQS 등
  • 사용자

    • AWS 서비스 외에 사용할 수 있는 권한
    • 로컬PC, IDC 서버 등

3-1-2. [역할]이 만들어졌다면 EC2서비스에 등록한다.

3-2. CodeDeploy 에이전트 설치

CodeDeploy의 요청을 받을 수 있도록??
참고 https://docs.aws.amazon.com/ko_kr/codedeploy/latest/userguide/codedeploy-agent-operations-install-linux.html

3-3. CodeDeploy를 위한 권한 생성

CodeDeply에서 EC2에 접근하려면 마찬가지로 권한이 필요하다. AWS의 서비스이니 IAM 역할 생성

CodeDeploy란?

애플리케이션 배포를 자동화하는 배포 서비스.
오토 스케일링 그룹 배포, 블루 그린 배포, 롤링 배포, EC2 단독 배포 등 많은 기능을 지원




배포 구성이란 한번 배포할 때 몇 대의 서버에 배포할지를 결정하낟. 2대 이상이라면 여러 옵션을 선택하겠지만, 1대 서버다 보니 전체 배포하는 옵션으로 선택하면 된다.
배포 그룹까지 생성되었다면 CodeDeploy 설정은 끝이다. 이제 Travis CI와 CodeDeploy를 연동해보자.

3-5. Travis CI, S3, CodeDeploy 연동

먼저 S3에서 넘겨줄 zip 파일을 저장할 디렉토리 생성. EC2 서버에 접속해서 다음과 같이 디렉토리 생성
mkdir ~/app/step2 && mkdir ~/app/step2/zip

Travis CI의 Build가 끝나면 S3에 zip파일이 전송되고, 이 zip 파일은 /home/ec2-user/app/step2/zip으로 복사되어 압축을 풀 예정
AWS CpdeDeploy의 설정은 appspec.yml로 진행한다.

version: 0.0
os: linux
files:
  - source:  /
    destination: /home/ec2-user/app/step2/zip/
    overwrite: yes

+코드해석

  • version
    - CodeDeploy 버전
  • source
    -Code

deploy.sh 책에서는 아래처럼 나와있는데 -Dspring.profiles.active=real \ 이거 프로파일 설정 안해서 빼도 될거같은데

#!/bin/bash

REPOSITORY=/home/ec2-user/app/step2
PROJECT_NAME=hello-spring

echo "> Build 파일 복사"

cp $REPOSITORY/zip/*.jar $REPOSITORY/

echo "> 현재 구동중인 애플리케이션 pid 확인"

CURRENT_PID=$(pgrep -fl ${PROJECT_NAME} | 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 \
    $JAR_NAME > $REPOSITORY/nohup.out 2>&1 &

+spring.profiles.include를 통해 다른 properties파일을 등록할 수 있다.

.travis.yml 파일 수정

현재는 프로젝트의 모든 파일을 zip 파일로 만드는데, 실제로 필요한 파일은 Jar, appspec.yml, 배포를 위한 스크립트들이다. 그래서 .travis.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 * # befor-deploy로 이동후 전체 압축
  - cd ../ && mkdir -p deploy
  - mv before-beploy/hello-spring.zip deploy/hello-spring.zip

appspec.yml 수정

permissions

  • codeDeploy에서 EC2서버로 넘겨준 파일들을 모두 ec2-user 권한을 갖도록 한다.

hooks

  • codeDeploy 배포 단계에서 실행할 명령어를 지정
  • ApplicationStart라는 단계에서 deploy.sh를 ec2-user 권한으로 실행하게 된다.
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

CodeDeploy 로그 확인

CodeDeploy와 같이 AWS가 지원하는 서비스에서는 오류가 발생했을때 로그 찾는 방법을 모르면 오류를 해결하기가 어렵다. 그래서 배포가 실패하면 어느 로그를 봐야 할지 알아보자.
CodeDeploy에 관한 댑분 내용은 /opt/codedeploy-agent/deployment-root에 있다.


오늘도 에러


codeDeploy까지 완료했는데 실화야...?

성공했다고 했잖아...

appspec.yml 에서 Applcation -> Application 으로 수정했더니 log파일까지는 생겼다.

Logfile created on 2021-05-31 13:45:23 +0900 by logger.rb/41954
[2021-05-31 13:45:23.191] [d-LXUIBXHBA]LifecycleEvent - ApplicationStart
[2021-05-31 13:45:23.191] [d-LXUIBXHBA]Script - deploy.sh
[2021-05-31 13:45:23.211] [d-LXUIBXHBA][stdout]> Build 파일 복사
[2021-05-31 13:45:23.241] [d-LXUIBXHBA][stdout]> 현재 구동중인 애플리케이션 pid 확인
[2021-05-31 13:45:23.333] [d-LXUIBXHBA][stdout]현재 구동중인 어플리케이션 pid:
[2021-05-31 13:45:23.333] [d-LXUIBXHBA][stdout]> 현재 구동중인 애플리케이션이 없으므로 종료하지 않습니다.
[2021-05-31 13:45:23.333] [d-LXUIBXHBA][stdout]> 새 어플리케이션 배포
[2021-05-31 13:45:23.402] [d-LXUIBXHBA][stdout]> JAR Name: /home/ec2-user/app/step2/hello-spring-0.0.1-SNAPSHOT.jar
[2021-05-31 13:45:23.402] [d-LXUIBXHBA][stdout]> /home/ec2-user/app/step2/hello-spring-0.0.1-SNAPSHOT.jar 에 실행권한 추가
[2021-05-31 13:45:23.403] [d-LXUIBXHBA][stdout]> /home/ec2-user/app/step2/hello-spring-0.0.1-SNAPSHOT.jar 실행
[2021-05-31 13:45:23.996] [d-LXUIBXHBA][stderr]Usage: java [options] <mainclass> [args...]
[2021-05-31 13:45:23.996] [d-LXUIBXHBA][stderr]           (to execute a class)
[2021-05-31 13:45:23.996] [d-LXUIBXHBA][stderr]   or  java [options] -jar <jarfile> [args...]
[2021-05-31 13:45:23.996] [d-LXUIBXHBA][stderr]           (to execute a jar file)
[2021-05-31 13:45:23.996] [d-LXUIBXHBA][stderr]   or  java [options] -m <module>[/<mainclass>] [args...]
[2021-05-31 13:45:23.996] [d-LXUIBXHBA][stderr]       java [options] --module <module>[/<mainclass>] [args...]
[2021-05-31 13:45:23.996] [d-LXUIBXHBA][stderr]           (to execute the main class in a module)
[2021-05-31 13:45:23.996] [d-LXUIBXHBA][stderr]   or  java [options] <sourcefile> [args]
[2021-05-31 13:45:23.996] [d-LXUIBXHBA][stderr]           (to execute a single source-file program)
[2021-05-31 13:45:23.996] [d-LXUIBXHBA][stderr]
[2021-05-31 13:45:23.996] [d-LXUIBXHBA][stderr] Arguments following the main class, source file, -jar <jarfile>,
[2021-05-31 13:45:23.996] [d-LXUIBXHBA][stderr] -m or --module <module>/<mainclass> are passed as the arguments to
[2021-05-31 13:45:23.996] [d-LXUIBXHBA][stderr] main class.
[2021-05-31 13:45:23.996] [d-LXUIBXHBA][stderr]
[2021-05-31 13:45:23.996] [d-LXUIBXHBA][stderr] where options include:
[2021-05-31 13:45:23.996] [d-LXUIBXHBA][stderr]
[2021-05-31 13:45:23.996] [d-LXUIBXHBA][stderr]    -cp <class search path of directories and zip/jar files>
[2021-05-31 13:45:23.996] [d-LXUIBXHBA][stderr]    -classpath <class search path of directories and zip/jar files>
[2021-05-31 13:45:23.996] [d-LXUIBXHBA][stderr]    --class-path <class search path of directories and zip/jar files>
[2021-05-31 13:45:23.996] [d-LXUIBXHBA][stderr]                  A : separated list of directories, JAR archives,
[2021-05-31 13:45:23.996] [d-LXUIBXHBA][stderr]                  and ZIP archives to search for class files.

Dspring.config.location=classpath:/application.properties \ 에서 맨 끝에 "\"가 빠져있었다. 이제 정상적으로 작동한다ㅎㅎ

profile
안녕하세요

0개의 댓글