[9. Spring boot] Travis CI 배포 자동화 - push -> 자동 배포

박현우·2021년 4월 23일
3

Spring

목록 보기
10/11

CI & CD 소개

저번 장에서 EC2에 프로젝트를 배포했고, 쉘 스크립트를 이용하여 스크립트를 실행하면 서버에 반영시켰습니다. 하지만 스크립트를 개발자가 직접 실행해야 하기 때문에 번거롭습니다.

CI(Continuous Integration)와 CD(Continuous Deployment)란
코드 버전 관리를 하는 VCS 시스템(Git, SVN 등)에 PUSH를 하게 되면 자동으로 테스트와 빌드가 수행되어 안정적인 배포 파일을 만드는 과정CI,
이 빌드 결과를 자동으로 운영 서버에 무중단 배포까지 진행되는 과정을 CD 라고 합니다.

예전 여러사람들이 참여하는 프로젝트에서는 각자의 코드를 합쳐야 할때마다 일이었다고 합니다. 그래서 merge만 하는 날을 정해야 했고 당연히 생산성이 좋을 수 없습니다. 이것이 CI와 CD가 나온 배경입니다.

여기서 중요한 것은 테스팅 자동화입니다. 위와 같이 CI CD가 올바르게 진행되려면 모든 테스트를 거쳐야 하는데 그만큼 테스트가 자동화되어 있으면 merge를 하는 과정에서 시간 단축이 될 수 있겠습니다.


Travis CI 연동하기

Travis CI는 깃허브에서 제공하는 무료 CI 서비스입니다. 같은 CI도구인 젠킨스는 EC2 인스턴스가 하나 더 필요하다고 합니다.

Travis CI 웹 서비스 설정

로그인 후, 프로젝트를 활성화 시킵니다. 상세한 설정은 프로젝트의 yml 파일로 진행합니다.

YAML파일이란?

.yml 파일의 확장자를 YAML(YAML Ain’t Markup Language)라고 합니다. 프로젝트에서 xml이나 json 같은 데이터 포맷 파일입니다. 데이터 포맷 파일은 다른 시스템들과의 연동에서 "데이터를 이렇게 사용 하겠다"라는 규칙과 비슷합니다.
xml이나 json보다 직관적으로 알아보기 쉽고 작성하기도 훨씬 간단해진 파일 포맷이라고 생각하시면 될 것 같습니다.

출처


프로젝트 설정

위 그림과 같이 YAML은 Json에서 껍질만 벗겼다 라고 생각하시면 됩니다. 현재는 많은 프로젝트와 서비스들이 YAML을 사용하고 있다고 합니다.

build.gradle과 같은 자리에 .travis.yml을 생성합니다.

language: java
jdk:
  - openjdk8

branches: # 1.
  only:
    - master

# Travis CI 서버의 Home
cache: # 2.
  directories:
    - '$HOME/.m2/repository'
    - '$HOME/.gradle'
script: "./gradlew clean build" # 3.

# CI 실행 완료 시 메일 알람
notifications: # 4.
  email:
    recipients:
      - qweadzs@naver.com

  1. branches
    • Travis CI를 어느 브랜치가 푸시될 때 수행할지 지정합니다.
    • 현재 옵션은 오직 master 브랜치에 push될 때만 수행합니다.
  1. cache
    • 그레이들을 통해 의존성을 받게 되면 이를 해당 디렉토리에 캐시하여, 같은 의존성은 다음 배포 때부터 다시 받지 않도록 설정합니다.
  1. script
    • master 브랜치에 푸시되었을 때 수행하는 명령어입니다.
    • 여기서는 프로젝트 내부에 둔 gradlew을 통해 clean&push를 수행합니다.

그 후 master 브랜치에 커밋 & 푸시를 하면 Travis CI 저장소 페이지에서 passed를 확인할 수 있습니다. 또, 등록한 이메일로 빌드 성공 메일이 옵니다.


Travis CI와 AWS S3 연동하기

S3란 AWS에서 제공하는 일종의 파일 서버 입니다. 이미지와 같은 정적 파일이나 배포 파일들을 관리하는 등의 기능을 제공합니다. 보통 이미지 업로드를 구현한다면 S3를 이용해 구현합니다.

전체적인 구조


사진 출처
위 그림은 Travis CI 연동을 했을때의 전체적인 구조입니다.
정적 파일이 보관되어있는 AWS S3의 실제 배포는 AWS의 CodeDeploy라는 서비스를 이용합니다.

첫번째로 CI와 S3를 연동해야 하는데 Jar 파일을 전달하기 위해서입니다.
CodeDeploy에는 저장 기능이 없기 때문에 CI가 빌드한 결과를 S3에 저장한 후 CodeDeploy에서 가져가는 방식입니다.


AWS KEY 발급

AWS는 일반적으로 외부 서비스가 접근할 수 없습니다. 때문에 권한을 가진 후 접근을 시도해야 합니다.
AWS에서는 인증 관련 기능 서비스인 IAM(Identity and Access Management)을 제공합니다. IAM은 AWS에서 제공하는 서비스의 접근 방식과 권한을 관리합니다.

이렇게 IAM 사용자를 만들면 다음과 같이 액세스 키와 비밀 엑세스 키가 Travis CI에서 사용됩니다.


Travis CI에 키 등록

키를 만들었으니 키를 등록해야합니다.
Travis CI에 등록한 이 키들을 .travis.yml에서 $AWS_ACCESS_KEY, $AWS_SECRET_KEY라는 변수로 사용 가능합니다.


S3 생성

S3는 일종의 파일 서버이고, 순수하게 파일들을 저장하고 접근 권한을 관리, 검색 등을 지원하는 파일 서버의 역할을 합니다. 아까의 그림을 되짚어 보면 CodeDeploy에서 S3의 파일을 가져간다고 말씀드렸듯이 S3에 Travis CI에서 생성된 빌드 파일을 저장하도록 구성해야 합니다.


모든 부분은 입맛대로 하시면 되지만, 퍼블릭 액세스는 반드시 모두 차단하시길 바랍니다. 실제 서비스에서 Jar파일이 퍼블릭일 경우 누구나 내려받을 수 있어 코드, 설정값, 주요키값들이 탈취될 수 있기 때문입니다. 우리는 IAM 사용자로 발급받은 키가 있어 접근이 가능합니다.


.travis.yml 추가

Travis CI에서 빌드하여 만든 Jar파일을 S3에 올릴 수 있도록 해야 합니다.
다음과 같이 S3버킷에서 zip 파일을 확인할 수 있다면 Travis CI와 S3연동이 성공한 것입니다.

현재 진행 정보는 다음과 같습니다.


Travis CI와 AWS S3, CodeDeploy 연동하기

CodeDeploy를 이용하기 전 배포 대상인 EC2가 CodeDeploy를 연동 받을 수 있게 IAM 역할을 하나 생성해야 합니다.

IAM 사용자와 역할의 차이

역할
* AWS 서비스에만 할당할 수 있는 권한
* EC2, CodeDeploy, SQS 등

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


이렇게 만든 역할을 EC2 서비스에 등록합니다.

그 후 인스턴스를 재부팅 해야 역할이 정상적용됩니다.


CodeDeply 에이전트 설치

CodeDeploy의 요청을 받을 수 있게 에이전트를 하나 설치해야 합니다.
Putty에 접속하여 wget https://aws-codedeploy-ap-northeast-2.s3.ap-northeast-2.amazonaws.com/latest/install 입력합니다.
다음과 같이 PID xxxx로 실행 중이라는 메시지가 뜨면 성공입니다.

여러 이슈들

aws s3 cp s3://aws-codedeply-ap-northeast-2/latest/install . --region ap-northeast-2 오류
wget https://aws-codedeploy-ap-northeast-2.s3.amazonaws.com/latest/install 로 해결.

sudo ./install auto 오류
/usr/bin/env: ruby ... 라는 오류가 보인다면 ruby라는 언어의 미설치로 인한 오류입니다. sudo apt-get install ruby;으로 해결

sudo: apt-get: command not found 오류
apt-get 이라는 명령어는 AWS Linux에서 지원하지 않습니다. 때문에 yum 명령어를 사용해 해결합니다.


CodeDeploy를 위한 권한 생성

CodeDeploy에서 EC2에 접근하려면 권한이 필요합니다. AWS의 서비스니 IAM 역할을 생성합니다.


CodeDeploy 생성

AWS의 배포 삼대장을 알아보겠습니다.

  1. Code Commit
    • 깃허브와 같은 코드 저장소의 역할.
    • 프라이빗 기능때문에 사용했지만, 현재 깃허브에서 무료로 프라이빗 지원을 하고 있어 사용X
  2. Code Build
    • Travis Ci와 마찬가지로 빌드용 서비스 입니다.
    • 규모가 있는 서비스에서는 젠킨스/팀시티를 사용하니 사용 X
  3. CodeDeploy
    • AWS의 배포 서비스입니다.
    • 대체제가 없다.
    • 오토 스케일링 그룹 배포, 블루 그린 배포, 롤링 배포, EC2 단독 배포 등의 기능 지원.

우리는 깃허브로 코드 저장을 하고, Travis CI로 빌드를 하기 때문에 CodeDeploy밖에 필요한게 없습니다. 지금까지 설정한 것들을 바탕으로 배포 그룹을 만듭니다.


Travis CI, S3, CodeDeploy 연동

이제 Travis CI와 CodeDeploy를 연동하겠습니다.
먼저 S3에서 넘겨줄 zip파일을 저장할 디렉토리를 하나 생성하겠습니다.
mkdir ~/app/step2 && mkdir ~/app/step2/zip
아까 Travis CI에 의해 S3에 zip파일을 넘겨줬는데, zip파일을 /home/ec2-user/app/step2/aip으로 복사되어 압축을 풀 예정입니다.

AWS CodeDeploy의 설정은 appspec.yml로 진행합니다.
appspec.yml

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

.travis.yml

- provider: codedeploy
    access_key_id: $AWS_ACCESS_KEY # Travis repo settings에 설정된 값
    secret_access_key: $AWS_SECRET_KEY # Travis repo settings에 설정된 값
    bucket: freelec-springboot-build # S3 버킷
    key: freelec-springboot2-webservice.zip # 빌드 파일을 압축해서 전달
    bundle_type: zip
    application: freelec-springboot2-webservice # 웹 콘솔에서 등록한 CodeDeploy 어플리케이션
    deployment_group: freelec-springboot2-webservice-group # 웹 콘솔에서 등록한 CodeDeploy 배포 그룹
    region: ap-northeast-2
    wait-until-deployed: true

푸시 -> Travis CI -> S3 -> CodeDeploy -> EC2순으로 푸시만하게되면 자동으로 실행됩니다. CodeDeploy에서 배포가 된 것을 확인합니다.


다음과 같이 EC2에도 설정한 디렉토리에 푸시한 프로젝트의 zip이 풀려있는 것을 확인할 수 있습니다.


배포 자동화 구성

이제 jar를 배포하여 실행해보겠습니다.

deploy.sh 파일 추가

step2 환경에서 실행될 deploy.sh를 생성합니다.

.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 * # before-deploy로 이동후 전체 압축
  - cd ../ && mkdir -p deploy # 상위 디렉토리로 이동후 deploy 디렉토리 생성
  - mv before-deploy/before-deploy.zip deploy/Spring_Practice.zip # deploy로 zip파일 이동

Travis는 S3로 특정 파일만 업로드 하는 것이 불가능하기 때문에 저렇게 올릴 파일만 따로 zip에 포함 시켜서 올려야 합니다.

appspec.yml 파일 수정

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

그리고 특히 yml 파일을 작성할때는 들여쓰기가 정말 중요합니다. 왜냐하면 들여쓰기를 잘못하면 푸시를 해도 Travis에서 파싱 오류로 reject를 합니다. 파이썬과 비슷하게 간결한 언어에는 들여쓰기가 중요한가봅니다. 다음과 같은 사이트에서 들여쓰기가 맞는지 미리 확인해보는것도 나쁘지 않습니다.
http://www.yamllint.com/


실제 배포 과정 체험

build.gradle에서 프로젝트 버전을 변경합니다.

version '1.0.1-SNAPSHOT'

index도 알아볼 수 있게 다른 표시를 해줍니다.
스프링부트로 시작하는 웹 서비스 Ver.3


CodeDeploy 로그 확인

오류가 발생했을 때 로그 찾는 방법을 모르면 해결하기 힘듭니다.
CodeDeploy에 관한 대부분 내용은 /opt/codedeploy-agent/deployment-root 에 있습니다.

가서 한번 보겠습니다. cd /opt/codedeploy-agent/deployment-root

drwxr-xr-x 2 root root 247 Apr 23 22:37 deployment-instructions
drwxr-xr-x 2 root root 46 Apr 23 22:37 deployment-logs -- (2).
drwxr-xr-x 5 root root 63 Apr 23 22:43 fe75a149-658f-4e43-bd25-b6dd6aabfa49 -- (1).
drwxr-xr-x 2 root root 6 Apr 23 22:43 ongoing-deployment

  1. CodeDeploy ID 입니다.
    • 사용자마다 고유한 ID가 생성되어 각자 다른 ID가 발급되니 본인의 서버에는 다른 코드로 되어있습니다.
    • 해당 디렉토리로 들어가 보면 배포한 단위별로 배포 파일들이 들어있습니다.
    • 배포 파일이 정상적으로 왔는지 확인이 가능합니다.
  2. CodeDeploy 로그 파일입니다.

0개의 댓글