ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Travis CI 배포 자동화 (Travis CI repository 연동 오류)
    AWS 2023. 11. 9. 16:10

    참고 : 스프링 부트와 AWS로 혼자 구현하는 웹 서비스

     

    CI (Continuous Integration - 지속적 통합)

    : 코드 버전 관리를 하는 VCS 시스템(Git, SVN 등)에 PUSH가 되면 자동으로 테스트와 빌드가 수행되어 안정적인 배포 파일을 만드는 과정

    • 모든 소스 코드가 살아 있고(현재 실행되고) 누구든 현재의 소스에 접근할 수 있는 단일 지점을 유지할 것
    • 빌드 프로세스를 자동화해서 누구든 소스로부터 시스템을 빌드하는 단일 명령어를 사용할 수 있게 할 것
    • 테스팅을 자동화해서 단일 명령어로 언제든지 시스템에 대한 건전한 테스트 수트를 실행할 수 있게 할 것
    • 누구나 현재 실행 파일을 얻으면 지금까지 가장 완전한 실행 파일을 얻었다는 확신을 하게 할 것

     

    CD (Continuous Deployment - 지속적인 배포)

    : 이 빌드 결과를 자동으로 운영 서버에 무중단 배포까지 진행되는 과정


    1. Travis CI 연동하기

    • Travis CI는 깃허브에서 제공하는 무료 CI 서비스
    • 젠킨스는 설치형이기 때문에 이를 위한 EC2 인스턴스가 하나 더 필요

     

    https://app.travis-ci.com/

     

    Travis CI - Test and Deploy with Confidence

     

    app.travis-ci.com

     

    ※ Travis CI My Repositories 연동 안 되는 문제

    (1) Plan - Trial Plan $1 결제

     

    해당 플랜을 결제하였는데도 My Repository 연동이 되지 않았다.

    금요일 오후에 결제 후, 월요일에 확인해보니 연동이 되어있었다.

    하루, 이틀 정도 후에 확인해보기 ! 결제된 $1는 일주일 정도 후에 취소 처리되었다.

     

    (2) Github Actions 사용하기

    Travis CI 연동이 안 되어 Github Actions로 진행하려고 했으나, 며칠 후 연동이 되어 Travis CI로 진행하였다.

    Github Actions 내용은 하기 블로그 참고

     

    https://wbluke.tistory.com/39

     

    Github Actions + CodeDeploy + Nginx 로 무중단 배포하기 (1)

    개요 안녕하세요! 이번 시리즈에서는 제목에서와 같이 Github Actions 와 CodeDeploy, 그리고 Nginx 를 사용하여 하나의 서버에서 최소 규모의 무중단 배포를 진행하는 방법에 대해 정리해보려고 합니다.

    wbluke.tistory.com

     

     

    * 프로젝트 설정

    프로젝트의 build.gradle과 같은 위치에서 .travis.yml 생성 후 Travis CI 상세 설정

     

    .travis.yml

    language: java
    jdk:
      - openjdk8
    
    branches:
      only:
        - master
    
    # Travis CI 서버의 Home
    cache:
      directories:
        - '$HOME/.m2/repository'
        - '$HOME/.gradle'
    
    script: "./gradlew clean build"
    
    # CI 실행 완료 시 메일로 알람
    notifications:
      email:
        recipients:
          - 본인 메일 주소

    Travis CI 설정이 잘 되면 커밋, 푸시 시 자동으로 빌드 진행

     

     

    2. Travis CI와 AWS S3 연동하기

    CodeDeploy는 저장 기능이 없어서 Travis CI가 빌드한 결과물을 받아서 CodeDeploy가 가져갈 수 있도록 보관할 수 있는 공간이 필요

    → AWS S3를 이용

     

     

    CodeDeploy에서는 깃허브 코드를 가져오는 기능을 지원하므로, CodeDeploy가 빌드도 하고 배포도 할 수 있다.

    하지만 이렇게 하는 경우 빌드 없이 배포만 필요할 때 대응하기가 어렵다.

    빌드와 배포가 분리되어 있으면 예전에 빌드되어 만들어진 Jar를 재사용하면 되지만, CodeDeploy가 모든 것을 하게 될 땐 항상 빌드를 하게 되니 확장성이 많이 떨어진다. 웬만하면 빌드와 배포는 분리 !

     

    AWS Key 발급

    일반적으로 AWS 서비스에 외부 서비스가 접근할 수 없다. 그러므로 접근 가능한 권한을 가진 Key를 생성해서 사용해야 한다.

    AWS에서는 이러한 인증과 관련된 기능을 제공하는 서비스로 IAM(Identity and Access Management)이 있다.

     

    IAM은 AWS에서 제공하는 서비스의 접근 방식과 권한을 관리한다. 이 IAM을 통해 Travis CI가 AWS와 S3에 접근할 수 있도록 설정할 수 있다.

    IAM > 액세스 관리 - 사용자 > 사용자 이름 > 보안 자격 증명 - 액세스 키

     

    생성된 엑세스 키와 비밀 엑세스 키를 Travis CI에 등록한다.

     

    Travis CI에 키 등록

    해당 Repository > More options > Settings > Environment Variables

     

    여기에 AWS_ACCESS_KEY, AWS_SECRET_KEY을 변수로 해서 IAM 사용자에서 발급받은 키 값들을 등록한다.

    • AWS_ACCESS_KEY: 엑세스 키 ID
    • AWS_SECRET_KEY: 비밀 엑세스 키

    → .travis.yml에서 $AWS_ACCESS_KEY, $AWS_SECRET_KEY으로 사용 가능

     

     

    .travis.yml

    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 freelec-springboot2-webservice *
      - mkdir -p deploy
      - mv freelec-springboot2-webservice.zip deploy/freelec-springboot2-webservice.zip
    
    deploy:
      - provider: s3
        access_key_id: $AWS_ACCESS_KEY # Travis repo settings에 설정된 값
        secret_access_key: $AWS_SECRET_KEY # Travis repo settings에 설정된 값
        bucket: freelec-sol-springboot-build # S3 버킷
        region: ap-northeast-2
        skip_cleanup: true
        acl: private # zip 파일 접근을 private으로
        local_dir: deploy # before_deploy에서 생성한 디렉토리
        wait_until_deploy: true
    
      - provider: codedeploy
        access_key_id: $AWS_ACCESS_KEY # Travis repo settings에 설정된 값
        secret_access_key: $AWS_SECRET_KEY # Travis repo settings에 설정된 값
        bucket: freelec-sol-springboot-build # S3 버킷
        key: freelec-springboot2-webservice.zip # 빌드 파일을 압축해서 전달
        build_type: zip # 압축 확장자
        application: freelec-springboot2-webservice # 웹 콘솔에서 등록한 CodeDelploy 애플리케이션
        deployment_group: freelec-springboot2-webservice-group # 웹 콘솔에서 등록한 CodeDeploy 배포 그룹
        region: ap-northeast-2
        wait_until_deploy: true
    
    # CI 실행 완료 시 메일로 알람
    notifications:
      email:
        recipients:
          - 본인 메일 주소

     

     

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

    CodeDeploy 생성

    • Code Commit
      - 깃허브와 같은 코드 저장소의 역할을 한다.
      - 프라이빗 기능을 지원한다는 강점이 있지만, 현재 깃허브에서 무료로 프라이빗 지원을 하고 있어서 거의 사용되지 않는다.

    • Code Build
      - Travis CI와 마찬가지로 빌드용 서비스
      - 멀티 모듈을 배포해야 하는 경우 사용해 볼만하지만, 규모가 있는 서비스에서는 대부분 젠킨스/팀시티 등을 이용하여 사용할 일이 거의 없다.

    • CodeDeploy
      - AWS의 배포 서비스
      - 앞에서 언급한 다른 서비스들은 대체제가 있고, 딱히 대체제보다 나은 점이 없지만, CodeDeploy는 대체제가 없다.
      - 오토 스케일링 그룹 배포, 블루 그린 배포, EC2 단독 배포 등 많은 기능을 지원한다.

     

    현재 Code Commit의 역할은 깃허브가, Code Build의 역할은 Travis CI가 하고 있어 CodeDeploy만 사용한다. 

     

    Travis CI, S3, CodeDeploy 연동

    # S3에서 넘겨줄 zip 파일을 저장할 디렉토리 생성
    mkdir ~/app/step2 && mkdir ~/app/step2/zip

     

    Travis CI의 Build가 끝나면 S3에 zip 파일이 전송되고, 이 zip 파일은 /home/ec2-user/app/step2/zip로 복사되어 압축을 풀 예정

    AWS CodeDeploy의 설정appspec.yml 

     

    appspec.yml

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

    깃 허브로 푸시가 되면 Travis CI가 자동으로 시작되고, Traivis CI가 끝나면 CodeDeploy에서 배포가 수행된다.

     

     

    4. 배포 자동화 구성

    프로젝트/scripts/deploy.sh 생성

    #!/bin/bash
    
    REPOSITORY=/home/ec2-user/app/step2
    PROJECT_NAME=freelec-springboot2-webservice
    
    echo "> Build 파일 복사"
    
    cp $REPOSITORY/zip/*.jar $REPOSITORY/
    
    echo "> 현재 구동 중인 애플리케이션 pid 확인"
    
    CURRENT_PID=$(pgrep -fl freelec-springboot2-webservice | 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,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.yml 

    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 # 상위 디렉토리로 이동 후 deplooy 디렉토리 생성
      - mv before-deploy/before-deploy.zip deploy/freelec-springboot2-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: freelec-sol-springboot-build # S3 버킷
        region: ap-northeast-2
        skip_cleanup: true
        acl: private # zip 파일 접근을 private으로
        local_dir: deploy # before_deploy에서 생성한 디렉토리
        wait_until_deploy: true
    
      - provider: codedeploy
        access_key_id: $AWS_ACCESS_KEY # Travis repo settings에 설정된 값
        secret_access_key: $AWS_SECRET_KEY # Travis repo settings에 설정된 값
        bucket: freelec-sol-springboot-build # S3 버킷
        key: freelec-springboot2-webservice.zip # 빌드 파일을 압축해서 전달
        build_type: zip # 압축 확장자
        application: freelec-springboot2-webservice # 웹 콘솔에서 등록한 CodeDelploy 애플리케이션
        deployment_group: freelec-springboot2-webservice-group # 웹 콘솔에서 등록한 CodeDeploy 배포 그룹
        region: ap-northeast-2
        wait_until_deploy: true
    
    # CI 실행 완료 시 메일로 알람
    notifications:
      email:
        recipients:
          - 본인 메일 주소

     

    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

     

     

    5. CodeDeploy 로그 확인

    CodeDeploy에 관한 대부분 내용은 /opt/codedeploy-agent/deployment-root에 있다.

    • 최상단의 영문과 대시(-)가 있는 디렉토리명은 CodeDeploy ID
      - 사용자마다 고유한 ID가 생성되어 각자 다른 ID가 발급된다.
      - 해당 디렉토리로 들어가 보면 배포한 단위별로 배포 파일들이 있습니다.
      - 본인의 배포 파일이 정상적으로 왔는지 확인해볼 수 있다.

    •  /opt/codedeploy-agent/deployment-root/deployment-logs/codedeploy-agent-deployments.log
      - CodeDeploy 로그 파일
      - CodeDeploy로 이루어지는 배포 내용 중 표준 입/출력 내용은 모두 여기에 담겨있다.
      - 작성한 echo 내용도 모두 표기된다.

     

     

    댓글

Designed by Tistory.