스프링부트와 AWS로 혼자 구현하는 웹서비스 - 0114 ~ 0116

megaseunghan·2022년 1월 16일
0
post-thumbnail

0114 Spring_Boot_RDS 접근 및 자동 배포

  • 오늘은 프로젝트로 RDS에 접근하는 방법 +
  • 24시간 배포환경을 구축한다.

8.4 스프링 부트 프로젝트로 RDS 접근하기

RDS는 MariaDB를 사용하기 때문에

  1. 테이블 생성
  2. 프로젝트 설정
  3. EC2 설정이 필요하다.

RDS 테이블 생성

  • JPA가 사용될 Entity테이블과 스프링 세션이 사용될 테이블 2가지 종류를 생성한다.

예제를 따라서 성공적으로 만들었다

프로젝트 설정

  • MariaDB를 build.gradle에 등록한다.

    compile('org.mariadb.jdbc:mariadb-java-client')를 의존성에 추가한다.

  • src/main/resources에 application-real.properties를 생성하고 다음과 같이 작성한다.

  spring.profiles.include=oauth,real-db
  spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
  spring.session.store-type=jdbc

서버에서 구동될 환경을 구성하는 것이다.

profile=real인 환경이 구성된다. 실제 운영될 환경이기 때문에 보안/로그상 이슈가 될 만한 설정은 제거하고 RDS 환경 profile 설정이 추가된다.

EC2 설정

  • OAuth과 마찬가지로 RDS 접속 정보도 보호해야 하므로, EC2 서버에 직접 설정 파일을 둔다.

    app 디렉토리에 applicatio-real-db.properties파일을 생성하고 다음과 같이 작성한다.

  spring.jpa.hibernate.ddl-auto=none
  spring.datasource.url=jdbc:mariadb://rds주소:포트명/database이름
  spring.datasource.username=db계정
  spring.datasource.password=db비번
  spring.datasource.driver-class-name=org.mariadb.jdbc.driver
  • 그리고 deploy.sh를 수정한다.

    -Dspring.profiles.active=real

    • application-real.properties를 활성화 시킨다. 해당 파일 내의 spring.profiles.include=oauth,real-db 옵션 때문에 real-db역시 활성화 대상에 포함된다.
  • curl localhost:8080을 SSH에 입력하여 html코드가 정상적으로 보인다면 성공!

EC2에서 소셜 로그인

  • 이제 EC2에 서비스가 잘 배포되었다. AWS의 보안그룹 중 8080이 열려있는 것을 확인한다.
  • 퍼블릭 DNS를 확인하고 도메인 주소 뒤에 :8080을 붙여 브라우저에 접속해본다.
  • 소셜 로그인을 위해 EC2 도메인을 구글, 네이버에서 만든 애플리케이션 Redirect 도메인에 추가해준다.

Travis CI 배포 자동화

코드가 푸시되면 Test & Build 를 자동화 해준다.

  • CI(Continuous Integration - 지속적 통합) : 코드 버전 관리를 하는 VCS 시스템에 PUSH가 되면 자동으로 테스트와 빌드가 수행되어 안정적인 배포 파일을 만드는 과정

    CI는 다음과 같은 규칙이 필요하다

    1. 모든 소스 코드가 현재 실행되고 누구든 현재의 소스에 접근할 수 있는 단일지점을 유지
    2. 빌드 프로세스 자동화를 통해 누구든 단일 명령어를 사용할 수 있게할 것
    3. 테스팅 자동화하여 언제든지 시스템에 건전한 테스트 수트를 실행할 수 있게할 것
    4. 누구나 현재 실행 파일을 얻을 때, 가장 완전한 파일이라고 확신하게 할 것

    : 프로젝트가 완전한 상태임을 보장하기 위함이다.

  • CD(Continuous Deployment - 지속적 배포) : 빌드 결과를 자동으로 운영 서버에 무중단 배포까지 진행되는 과정

Travis CI 연동

  1. travis-ci.com에서 가입을 한뒤 깃허브 저장소를 활성화한다.

  2. travis.yml : travis CI의 상세 설정을 할 수 있다. 이를 생성한다. (아래 파일은 p.383까지 진행한 내용이다. 참고하지 않는게 좋습니다! )

   language: java
   jdk:
     - openjdk8
   
   branches:
     only:
       - master
   
   # 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/seung-springboot-webservice.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: seung-springboot-webservice
       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
       secret_access_key: $AWS_SECRET_KEY
       bucket: seung-springboot-webservice
       key: seung-springboot-webservice.zip # 빌드 파일을 압축해서 전달
       bundle_type: zip
       application: seung-springboot-webservice # 웹 콘솔에서 등록한 CodeDeploy 애플리케이션
       deployment_group: seung-springboot-webservice-group # 웹 콘솔에서 등록한 CodeDeploy 배포 그룹
       region: ap-northeast-2
       wait-until-deployed: true
   
   # CI 실행 완료 시 메일로 알람
   notifications:
     email:
       recipients:
         skud113@naver.com
   
  • branches : master 브랜치에 푸시될 때만 travis-ci 수행
  • cache : 그레이들을 통해 의존성을 받게되면 해당 디렉토리에 cache하여 같은 의존성은 다음 배포엔 받지 않음
  • script : push되면 수행하는 명령어 gradlew clean build
  • notifications : 자동으로 알람이 옴

Travis와 S3연동

  • S3 : 일종의 파일 서버이다. 정적인 파일들을 관리하거나 배포 파일들을 관리하는 등의 기능을 지원한다.
  1. IAM에서 AWS key를 발급 받는다

    일반적으로 AWS 서비스에 외부 서비스가 접근할 수 없기 때문.

  2. travis-ci에 키를 등록한다.

  3. S3 버킷을 생성한다.

    버킷의 보안과 권한 설정에서 모든 차단을 해야한다. Jar 파일이 퍼블릭일 경우 누구나 내려받을 수 있어 중요한 정보가 탈취될 수 있다.

  4. 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/seung-springboot-webservice.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: seung-springboot-webservice
       region: ap-northeast-2
       skip_cleanup: true
       acl: private # zip 파일 접근을 private으로
       local_dir: deploy # before_deploy에서 생성한 디렉토리
       wait-until-deployed: true
  1. 깃허브에 푸시하고 Travis CI에서 빌드가 성공했는지 확인한다.

알게된 점

  • 당일날 한걸 몰아서 정리하려다가 실패했다. 분명 많은 실수가 있었는데 글로 작성하려니 생각이 안나고 16일인 지금 너무 후회된다. 383페이지까지 빠르게 정리하고 다음부터는 꼭 TIL이라는 주제에 맞게 글을 작성하겠다.

내일 할 일

  • CodeDeploy 연동글 작성 + Nginx 연동글 작성

  • 자바 공부

0114 Spring_Boot_RDS 접근 및 자동 배포

  • 오늘은 CodeDeploy 연동글 작성 + Nginx 연동글 작성, 자바 공부를 한다.

9.4 Travis CI와 AWS S3, CodeDeploy 연동하기

  • CodeDeploy : AWS의 배포 시스템

  • 그 외 배포 역할을 하는 서비스들

    • Code Commit

      : 깃허브와 같은 코드 저장소의 역할, 프라이빗을 지원하는 강점이 있지만 깃허브에서 무료로 지원하고 있어서 거의 사용되지 않음

    • Code Build

      : Travis CI와 마찬가지로 빌드용 서비스, 멀티 모듈을 배포하는 경우 사용해 볼만하지만 규모가 있는 곳에선 젠킨스, 팀시티등을 이용하여 거의 사용되지 않음

EC2에 IAM 역할 추가하기

  • IAM은 AWS에서 제공하는 서비스의 접근 방식과 권한을 관리한다. 따라서 S3와 마찬가지로 IAM을 탭으로 이동한다.
  • 사용자가 아닌 역할 -> 역할 만들기 버튼을 누른다. 사용자와 역할의 차이는 다음과 같다.
  • 사용자

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

    • AWS 서비스에만 할당할 수 있는 권한
    • EC2, CodeDeploy, SQS 등
  • 서비스 선택에서 AWS 서비스 ▶ EC2 탭을 차례대로 클릭

  • 정책에서는 AmazonEC2RoleforAWSCodeDeploy를 선택

  • 태그네임은 원하는대로 지어주면 된다. 난 예제를 따라 똑같이 Name이라고 지었다.

  • 이제 생성된 역할을 적용할 차례다.인스턴스 우클릭 ▶ IAM 역할 연결/바꾸기를 선택하여 방금 생성한 역할을 적용한 뒤, 재부팅을 해준다.

    재부팅을 해야만 역할이 정상적으로 작동된다.

CodeDeploy 에이전트 설치

  • CodeDeploy의 요청을 받을 수 있게 EC2 서버에 접속하여 다음 명령어를 차례로 입력한다.
# 에이전트 설치
aws s3 cp s3://aws-codedeploy-ap-northeast-2/latest/instatll . --region ap-northeast-2
# 설치 완료시 출력문
> download: s3://aws-codedeploy-ap-northeast-2/latest/instatll to ./install 
# insatll 파일 실행 권한 추가
chmod +x ./install
# install 파일로 설치 진행
sudo ./install auto
# Agent 정상 실행 상태 확인
sudo service codedeploy-agent status
# 아래와 같이 출력되면 정상 !
> The AWS CodeDeploy agent is running as PID XXX
  • 난 Ruby가 설치되어있지 않아 sudo yum install ruby를 통해 ruby를 설치했다. 안되는 사람은 참고!

CodeDeploy를 위한 권한 생성

  • EC2에 접근하려면 마찬가지로 권한이 필요하다. IAM 역할을 생성하자.
  • AWS서비스 ▶ CodeDeploy 선택
  • 서비스와 사용사례에서는 CodeDeploy를 선택한다.
  • 태그 네임을 짓고 생성을 완료한다.

CodeDeploy 생성

깃허브와 Travis가 각각 커밋, 빌드의 역할을 하고 있으니 배포를 위해 CodeDeploy를 생성한다.

  • 애플리케이션 생성컴퓨팅 플랫폼 - EC2/온프레미스배포 그룹 생성배포 그룹 이름 입력, 서비스 역할 - IAM 역할 선택배포 유형 - 현재위치환경구성 - Amazon EC2 인스턴스생성완료

Travis CI, S3, CodeDeploy 연동

  • EC2 서버에 디렉토리를 생성한다. - mkdir ~/app/step2 && mkdir ~/app/step2/zip

    Travis CI의 Build가 끝나면 S3에 zip 파일이 전송되고 이 zip파일을 위 디렉토리에 복사되어 압축을 풀 예정이다.

  • Travis의 설정은 travis.yml, CodeDeploy의 설정은 appspec.yml에서 진행한다.

  • appspec.yml - 다음과 같이 작성

  version: 0.0
  # codedeploy의 버전, 프로젝트 버전이 아니므로 0.0 사용
  os: linux
  files:
  	- source:	/
  	# codedeploy에서 전달해 준 파일 중 destination으로 이동시킬 대상 지정
  	destination: /home/ec2-user/app/step2/zip
  	# source에서 지정된 파일을 받을 위치, Jar를 실행하는 등을 여기서 옮긴 파일들로 진행
  	overwrite: yes
  	# 덮어쓰기 결정 Yes
  • .travis.yml - 코드 추가
    - provider: codedeploy
      access_key_id: $AWS_ACCESS_KEY
      secret_access_key: $AWS_SECRET_KEY
      bucket: seung-springboot-webservice
      key: seung-springboot-webservice.zip # 빌드 파일을 압축해서 전달
      bundle_type: zip
      application: seung-springboot-webservice # 웹 콘솔에서 등록한 CodeDeploy 애플리케이션
      deployment_group: seung-springboot-webservice-group # 웹 콘솔에서 등록한 CodeDeploy 배포 그룹
      region: ap-northeast-2
      wait-until-deployed: true

S3의 옵션과 유사하다. 다른 부분은 CodeDeploy의 애플리케이션 이름과 배포 그룹명을 지정하는 것이다.

  • 커밋 후 푸시한다.

  • cd /home/ec2-user/step2/zip으로 이동하여 파일이 잘 왔는지 확인한다.

  • 연동이 완료됐다

배포 자동화 구성

연동까지 구현되었으니, 실제로 Jar를 배포하여 실행까지 진행한다.

deploy.sh 파일 추가

  • 프로젝트에 scripts/deploy.sh 추가하고 다음과 같이 작성한다.
  #!/bin/bash
  
  REPOSITORY=/home/ec2-user/app/step2
  PROJECT_NAME=Spring_BootPJ_booboo
  
  echo "> Build 파일 복사"
  
  cp $REPOSITORY/zip/*.jar $REPOSITORY
  
  echo "> 현재 구동중인 애플리케이션 pid 확인"
  
  CURRENT_PID=$(pgrep -fl Spring_BootPJ_booboo | grep jar | awk '{print $1}')
  # 현재 수행 중인 스프링 부트 애플리케이션의 PID를 찾는다. 실행 중이면 종료
  echo "현재 구동중인 애플리케이션 : $CURRENT_PID"
  
  if [ -z "$CURRNET_PID" ]; then
    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
  # jar 파일에 nohup으로 실행할 수 있게 실행권한을 추가한다.
  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 &
    # nohup 실행시 CodeDeploy가 무한대기하는 이슈를 해결하기 위해 사용
  
  • .travis.yml 수정 - 다음과 같이 수정
  before_deploy:
    - mkdir -p before-deploy # zip에 포함시킬 파일들을 담을 디렉토리 생성
    # S3에서는 디렉토리 단위로만 업로드가 가능하기 떄문에 디렉토리를 항상 생성한다.
    - cp scripts/*.sh before-deploy/  
    # zip 파일에 포함시킬 파일들을 저장한다.
    - cp appspec.yml before-deploy/
    - cp build/libs/*.jar before-deploy/
    - cd before-deploy && zip -r before-deploy * # before-deploy로 이동 후 전체 압축
    # zip -r 명령어를 통해 디렉토리 전체 파일을 압축한다.
    - cd ../ && mkdir -p deploy # 상위 디렉토리로 이동 후 deploy 디렉토리 생성
    - mv before-deploy/before-deploy.zip deploy/seung-springboot-webservice.zip # deploy로 zip파일 이동
  • appspec.yml 수정 - 다음과 같이 수정
  permissions:
    - object: /
      pattern: "**"
      owner: ec2-user
      group: ec2-user
  
  hooks:
  # CodeDeploy에서 실행할 명령어 지정 ApplicationStart에서 deploy.sh를 ec2-user 권한으로 실행하게함
    ApplicationStart:
      - location: deploy.sh
        timeout: 12000
        runas: ec2-user

난 노트북 사양이 안좋아서 timeout을 12000까지 늘렸다 ㅜㅜ.. 원랜 60이다

  • 모든 설정이 완료되었으니 push를 하고 Travis CI에서 성공 메시지를 확인하고 CodeDeploy에서도 성공을 확인한다.

실제 배포 과정 체험

build.gradle에서 프로젝트 버전을 다음과 같이 변경한다. version '1.0.1-SNAPSHOT'

변경된 사항을 알 수 있게 index.mustache에서 h1태그에 Ver.2 텍스트를 추가하고 깃허브로 푸시해본다.

  • 여기서 문제가 발생했다. 변경 사항이 적용이 안되는 것..

  • 그러다가 EC2 인스턴스가 일치하지 않는다는 걸 알게됐다ㅜㅜ

  • 현타는 자기 전에 오게 놔두고 일단 해결부터 했다. 결과는 성공

문제발생

분명 15일에 진도를 나가기 전까지는 괜찮았다. 하지만

  • 이후에 문제가 또 발생했다. 383페이지까지 진행한 이후로 커밋과 푸시를 했는데 저번에 수정이 반영돼서 나왔던 결과가 다시 반영되지 않고, /profile에 접근하면 OAuth 페이지로 이동하는 것이다.

현재 발생하고 있는 문제

  1. 수정이 반영되지 않는 문제
  2. 페이지가 OAuth로 이동하는 문제

어떻게 해결할지 감이 안온다. 알고 싶다,, 지금 한 9시간 동안 잡고 있는거 같은데 거의 끝자락와서 이러니까 속상하다 ㅠㅠ

0개의 댓글