간단한 토이 프로젝트 github action, aws s3, ec2로 한통에 배포

kwak woojong·2022년 9월 26일
0

코드스테이츠

목록 보기
36/36

레포에 앞단 뒷단 레포가 다 있었음.

이거 가지고 깃헙 액션을 사용하여 브랜치별로 앞단은 s3로 보내서 정적 웹사이트로 쓰고,

뒷단은 ec2로 보내서 java를 구동해도 됨.

난 좀 다르게 생각 했음

  1. 같은 팀 앞단 분들이 .env가 적용이 안된다고 하는 상황
  2. 뒷단 api 완성이 먼저된 상태 (최적화는 아직 안함 일단 돌아는 가는 상태)
  3. aws에 아직 익숙치 않음

상기 상황에서 나는 아에 ec2에 앞단 뒷단 다 올리고 2개 서버를 구동한 뒤에

3000번 포트만 보안그룹에서 오픈 해주면 되지 않을까 생각했다.

이용자 -> 앞단(3000) -> 뒷단 (localhost:8080) -> db (aws rds)

이 경우 ec2만 https로 감싸주면 나쁘지 않은 배포가 될 것 같았다.

어차피 큰 규모의 프로젝트도 아니고 용량도 얼마 안하는데 이정도야 뭐...

이미지 파일도 s3 버킷을 써 먹을거니까 괜찮은 생각 같았음.

뭐 엄밀히 보자면 앞단 뒷단이 강하게 붙으니까 개발 할 때 문제가 생길 수 있는데, 어차피 앞단 분들 테스트는 내 컴퓨터에 직접 들어와서 하고, 뒷단 api가 어느정도 개발이 된 상태여서 커밋 푸시가 활발하지 않으므로 괜찮아 보였다.


  1. ec2 인스턴스를 만든다
  • 워낙 많은 자료가 있으니까 굳이 스샷을 붙이진 않겠음.

  • 나는 중간에 IAM 프로파일이 꼬여서 2번을 만들었다. 왜 IAM 프로파일이 2개 붙어있다는 에러를 뱉었는지 ㅡㅡ

  • 정책 권한은 다음과 같음.

    내가 aws에 익숙치 않아서 이것 저것 다 박은 느낌
    codeDeployRole이 2개나 있는데 하난 없애도 되지 않을까? ㅋㅋㅋㅋ

  • 아직 테스트 중이기 때문에 포트는 3000, 8080을 다 열어놨다. 보안에 취약한 상태

  1. s3 버킷을 만들어 준다.
    얘는 그냥 만들면 되니까 스킵. 그래도 주소는 잘 봐두자

  2. github action에서 workflow yml파일을 작성한다.
    앞단, 뒷단 모두 들어가야 하기 때문에 꽤 길다.

name: Java CI with Gradle

on:
  push:
    branches: [ "main" ]
  pull_request:
    branches: [ "main" ]

permissions:
  contents: read
  
env:
  S3_BUCKET_NAME: ${{ secrets.AWS_BUCKET_NAME }}
  application: ${{ secrets.APPLICATION }}

jobs:
  build:

    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v3
    
    - name: Set up JDK 11
      uses: actions/setup-java@v3
      with:
        java-version: '11'
        distribution: 'temurin'
        
    - run: mkdir ./back/src/main/resources
    - run: touch ./back/src/main/resources/application.yml
    - run: echo "${{env.application}}" > ./back/src/main/resources/application.yml
    
    - name: Grant execute permission for gradlew
      run: chmod +x gradlew
      working-directory: ./back/
    
    - name: Build with Gradle
      run: ./gradlew build
      working-directory: ./back/
        
    - name: Setup Node.js environment
      uses: actions/setup-node@v3.4.1
      with:
        node-version: '16.17.0'
        
    - name: npm install
      run: npm install
      working-directory: ./front/
    
    - name: npm build
      run: npm run build
      working-directory: ./front/
    
    - name: Make zip file
      run: zip -r ./full-deploy.zip .
      
    - name: Configure AWS credentials
      uses: aws-actions/configure-aws-credentials@v1
      with:
        aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY }}
        aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
        aws-region: ap-northeast-2
        
    - name: Upload to S3
      run: aws s3 cp --region ap-northeast-2 ./full-deploy.zip s3://$S3_BUCKET_NAME/full-deploy.zip

    - name: Code Deploy
      run: >
        aws deploy create-deployment --application-name parking-go
        --deployment-config-name CodeDeployDefault.AllAtOnce
        --deployment-group-name parking-go-deploy
        --s3-location bucket=$S3_BUCKET_NAME,bundleType=zip,key=full-deploy.zip

application.yml을 직접 때려박아 줬다.

뒷단 개발자라고 해봐야 나 포함 2명이니까 메신저로 그냥 공유하면 됨

굳이 암호화 하면서 깃 레포에 올릴 필요 없이 통으로 ignore 때려 버렸다.

그래서 mkdir로 폴더 만들고
touch 로 파일 만들고
깃헙 액션 시크릿에 저장된 yml 설정을 고대로 때려 박아줌.

   - run: mkdir ./back/src/main/resources
    - run: touch ./back/src/main/resources/application.yml
    - run: echo "${{env.application}}" > ./back/src/main/resources/application.yml

(다시는 내 귀찮이즘을 무시하지 마라)

그 뒤로 뭐 npm 하고 빌드 하고 뭐 압축했음.

일단 귀찮으니까 다 압축함.

    - name: Configure AWS credentials
      uses: aws-actions/configure-aws-credentials@v1
      with:
        aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY }}
        aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
        aws-region: ap-northeast-2

aws IAM 키를 박아준다. 이 역시 시크릿을 이용함.

그리고 s3에 업로드 하고, code Deploy를 발동시킨다.

이러면 깃헙 액션 부분은 끝임 여기서 고칠게 생기면 고치면 된다.

뼈대는 완성이 돼 있으니 수정이야 뭐 일도 아니지


잘 올라감


  1. ec2에 code deploy agent를 설치한다.

code deploy 설정 역시 웹에 깔려 있다.

일단 ec2에 설치를 잘 해야한다.

다만 IAM롤이 꼬이거나 인스턴스 재시작할 경우 ec2 내부 Code Deploy agent가 맛이 갈 수 있다. 이 땐 agent 재시작을 하면 된다.

sudo service codedeploy-agent status
sudo service codedeploy-agent start
sudo service codedeploy-agent restart
sudo service codedeploy-agent stop

status랑 restart만 알아도 될 듯.


아직 s3에서 ec2로 안퍼와진다. 당연하게도 appspec.yml 파일을 만들어줘야 하기 때문

  1. appspec.yml 작성

프로젝트 가장 최상위 디렉토리에

appspec.yml을 만들어주자

version: 0.0
os: linux
files:
  - source:  /
    destination: /home/ubuntu/action
    overwrite: yes
file_exists_behavior: OVERWRITE

permissions:
  - object: /
    pattern: "**"
    owner: ubuntu
    group: ubuntu

hooks:
  ApplicationStart:
    - location: scripts/deploy.sh
      timeout: 60
      runas: ubuntu

파일을 가져와서 home/ubuntu/action 에 넣어줌

이건 선택임 찾기 쉬운 아무데나 넣어도 될 거다.

만약 file이 이미 있으면 덮어쓰기 옵션 추가함.

그리고 마지막으로 ApplicationStart로 scripts/deploy.sh를 발동하게 했다.

내 마지막 난관이 저거 였다. 솔직히 이 윗 과정은 곰방했는데 저 deploy.sh에서 실수 하나 하니까 그거 잡는다고 엄청 고생함.


  1. deploy.sh 로 자동 서버 실행 ㄱ
#!/bin/bash
BUILD_JAR=$(ls /home/ubuntu/action/back/build/libs/parking-go-0.0.1-SNAPSHOT.jar)
JAR_NAME=$(basename $BUILD_JAR)

echo "> 현재 시간: $(date)" >> /home/ubuntu/action/deploy.log

echo "> build 파일명: $JAR_NAME" >> /home/ubuntu/action/deploy.log

echo "> build 파일 복사" >> /home/ubuntu/action/deploy.log
DEPLOY_PATH=/home/ubuntu/action/
cp $BUILD_JAR $DEPLOY_PATH

echo "> 현재 실행중인 애플리케이션 pid 확인" >> /home/ubuntu/action/deploy.log
CURRENT_PID=$(pgrep -f $JAR_NAME)

if [ -z $CURRENT_PID ]
then
  echo "> 현재 구동중인 애플리케이션이 없으므로 종료하지 않습니다." >> /home/ubuntu/action/deploy.log
else
  echo "> kill -15 $CURRENT_PID" >> /home/ubuntu/action/deploy.log
  sudo kill -15 $CURRENT_PID
  sleep 5
fi

DEPLOY_JAR=$DEPLOY_PATH$JAR_NAME
echo "> DEPLOY_JAR 배포"    >> /home/ubuntu/action/deploy.log
sudo nohup java -jar $DEPLOY_JAR >> /home/ubuntu/deployBe.log 2>/home/ubuntu/action/deploy_err.log &

BUILD_FRONT=/home/ubuntu/action/front/build/
echo "> 현재 실행중인 리액트 pid 확인" >> /home/ubuntu/action/deploy.log
REACT_PID=$(pgrep -f node)

if [ -z $REACT_PID ]
then
  echo "> 현재 구동중인 노드가 없으므로 종료하지 않습니다." >> /home/ubuntu/action/deploy.log
else
  echo "> kill -15 $REACT_PID" >> /home/ubuntu/action/deploy.log
  sudo kill -15 $REACT_PID
  sleep 5
fi

echo "> 프론트 서버 배포" >> /home/ubuntu/action/deploy.log
sudo ln -s /home/ubuntu/.nvm/versions/node/v16.17.1/bin/node /usr/bin/node
sudo ln -s /home/ubuntu/.nvm/versions/node/v16.17.1/bin/npm /usr/bin/npm
sudo nohup /home/ubuntu/.nvm/versions/node/v16.17.1/bin/serve -s $BUILD_FRONT >> /home/ubuntu/deployFe.log 2> /home/ubuntu/deploy_Fe_err.log &

echo "> ============== 끝 ==============" >> /home/ubuntu/action/deploy.log

일단 나는 node는 얕게 알고 있음. 아니 java는 그냥 쉘에서 java 때리면 먹는데 node는 왜 안먹는 거야 ㅠㅠㅠ

쨋든 심볼릭 링크를 만들고 넘겼다. (마지막에서 ln -s 명령어 친구들)
문제는 저 심볼릭 링크에 변동사항 (node 버전 변경)이 생길 경우 수동으로 지워야 한다. 이미 존재할 경우엔 덮어 쓰는게 아니라 안만들어줌.

만약 node 버전을 잘 못 깐 뒤에 심볼릭 링크를 만들었다면 수동으로 지우고 깔아줘야 한다. 이미 만들어져 있으므로 저 쉘에선 이제 지워도 될 것으로 보임. 근데 귀찮으니까 걍 냅두고 있다.


내가 가장 오래 걸린 친구가 앞단 리액트 서버 동작인데 왜인지 자꾸 serve를 하면 경로가 2개 이상이 떴다.

이게 머선 일인가 싶어서 보니까 $BUILD_FRONT 변수를 잘못 만들어 놨었다.

컴파일 에러가 뜨는 친구가 아니다보니 사소한 실수 하나가 치명적이게 되는 듯.

쨋든 앞단 뒷단 둘 다 ec2에 성공적으로 업로드 했다.

profile
https://crazyleader.notion.site/Crazykwak-36c7ffc9d32e4e83b325da26ed8d1728?pvs=4<-- 포트폴리오

0개의 댓글