Github Actions, AWS CodeDeploy를 활용한 CI/CD - Node.js(2)

공혁준·2022년 7월 8일
14
post-thumbnail

📌 Node.js 프로젝트를 Github Actions, AWS CodeDeploy를 활용하여 CI/CD 하는 과정을 다룹니다.

지난 글에서는 CI 과정을 살펴봤고, 이번 글에서는 CD 과정을 진행해보겠습니다.

AWS CodeDeploy를 활용해서 자동 배포를 하기 위해서는 AWS에서 관련 설정들을 해줘야 합니다.

AWS S3 버킷 생성

Github Actions에서 빌드한 프로젝트를 AWS에 저장하기 위한 S3 버킷이 필요합니다.

AWS > S3 > 버킷 > 버킷 만들기를 눌러줍니다.

버킷 이름만 지정한 후 다른 설정들은 그대로 두고 버킷 만들기를 눌러 버킷을 생성해줍니다.

EC2 IAM 설정

EC2가 S3와 CodeDeploy를 이용할 수 있도록 권한 설정을 해줘야합니다.

AWS > IAM > 액세스 관리 > 역할 > 역할 만들기를 눌러줍니다.

위와 같이 선택하고 다음을 눌러줍니다.

AWSCodeDeployFullAccess
AmazonS3FullAccess

두 가지 권한을 선택해주고 다음을 눌러줍니다.

마지막으로 역할 이름을 입력하고 역할 생성을 눌러줍니다.

이제 생성된 IAM을 EC2에 연결해주면 됩니다.

AWS > EC2 > 인스턴스로 이동해서 생성된 EC2 인스턴스에 마우스를 대고 우클릭을 해줍니다.

보안 > IAM 역할 수정을 눌러줍니다.

생성한 IAM을 선택하고 Update IAM role을 눌러줍니다.

CodeDeploy IAM 설정

다음은 CodeDeploy를 위한 IAM을 생성해줘야합니다. 위 과정과 비슷합니다.

AWS > IAM > 액세스 관리 > 역할 > 역할 만들기를 눌러줍니다.

이번에는 다른 AWS 서비스의 사용 사례에서 CodeDeploy를 검색한 뒤 위와 같이 선택하고 다음을 눌러줍니다.

그대로 다음을 눌러줍니다.

이름만 설정해주고 역할 생성을 눌러줍니다.

CodeDeploy 애플리케이션 생성

AWS > CodeDeploy > 애플리케이션 > 애플리케이션 생성을 눌러줍니다.

애플리케이션 이름을 정하고 컴퓨팅 플랫폼은 EC2/온프레미스로 설정한 후 애플리케이션 생성을 눌러줍니다.

이제 배포 그룹 생성을 눌러줍니다.

배포 그룹 이름을 정하고 서비스 역할에는 위에서 생성했던 CodeDeploy IAM을 지정해줍니다.

배포 유형은 그대로 둡니다.
환경 구성으로는 Amazon EC2 인스턴스를 선택하고 연결할 EC2 인스턴스를 선택해줍니다.

나머지 설정은 그대로 두고 로드 밸런싱 활성화 체크를 해제한 후 배포 그룹 생성을 눌러줍니다.

AWS IAM 사용자 추가

이제 Github Actions에서 S3에 접근하여 파일을 업로드할 수 있도록 IAM 사용자를 추가해줍니다.

AWS > IAM > 액세스 관리 > 사용자 > 사용자 추가를 눌러줍니다.

사용자 이름을 설정하고 액세스 키 - 프로그래밍 방식 엑세스에 체크를 한 뒤 다음을 눌러줍니다.

기존 정책 직접 연결에서 아까 선택한것처럼

AWSCodeDeployFullAccess
AmazonS3FullAccess

두 개의 권한을 체크한 후 다음을 눌러줍니다.
이후 다른 설정들은 변경하지 않고 사용자 만들기를 해줍니다.

이렇게 사용자를 생성하면 Access Key Id, Secret Access Key가 나옵니다.
이 키 값들은 지금만 확인할 수 있으니 키를 메모해두거나 .csv 다운로드를 눌러 csv 파일을 다운로드 받아둡니다.

이제 이 두가지 키 값들을 Github 환경변수에 추가해줍니다.

EC2 CodeDeploy Agent 설치

기본적으로 프로젝트 실행에 필요한 npm, yarn, git, node, pm2 등은 설치가 됐다고 가정하겠습니다.

AWS CodeDeploy를 사용하기 위해서는 EC2에 CodeDeploy Agent를 설치해줘야합니다.

먼저 awscli 설치가 필요합니다.

$ sudo apt update
$ sudo apt install awscli

전 단계의 Access Key Id, Secret Access Key를 입력해줍니다.

$ sudo aws configure
AWS Access Key ID : 다운 받은 csv 파일 내에 Access Key ID
AWS Secret Access KEy : 다운 받은 csv 파일 내에 Secret Access Key
Default region name : ap-northeast-2
Default output format : json

CodeDeploy Agent 설치 파일을 다운로드 하고 install 파일에 권한을 추가합시다.

$ wget https://aws-codedeploy-ap-northeast-2.s3.amazonaws.com/latest/install
$ chmod +x ./install

ruby를 먼저 설치하고, CodeDeploy Agent를 설치합니다.

$ sudo apt-get install ruby
$ sudo ./install auto
$ sudo service codedeploy-agent status # 설치 확인

마지막 명령어를 입력했을 때 위와 같이 active 상태이면 성공입니다.

인스턴스 부팅 시 codedeploy-agent가 자동으로 재시작되도록 shell script를 작성해줍니다.

$ sudo vim /etc/init.d/codedeploy-startup.sh

i로 편집모드 진입 

#!/bin
sudo service codedeploy-agent restart

esc -> :wq 저장 후 나가기

작성한 스크립트 파일에 실행 권한을 추가합니다.

$ sudo chmod +x /etc/init.d/codedeploy-startup.sh

appspec.yml 파일 추가

배포할 프로젝트의 루트 경로에 appspec.yml 파일을 추가합니다.
appspec.yml 파일은 CodeDeploy가 배포를 관리하는 애플리케이션 사양 파일입니다.

CodeDeploy가 EC2에 프로젝트를 옮기고 나면, EC2에서 이루어질 작업을 해당 파일에 추가하여 정의할 수 있습니다.

appspec.yml 파일

version: 0.0
os: linux
files:
  - source: /
    destination: /home/ubuntu/build
    overwrite: yes

permissions:
  - object: /home/ubuntu
    pattern: '**'
    owner: ubuntu
    group: ubuntu

hooks:
  AfterInstall:
    - location: scripts/after-deploy.sh
      timeout: 300
      runas: ubuntu

CodeDeploy가 EC2에 배포할 위치를 destination으로 지정합니다.
프로젝트가 옮겨지고 난 후에 이루어질 작업은 scripts/after-deploy.sh에 정의합니다.

after-deploy.sh 파일 추가

배포할 프로젝트의 루트 경로에 scripts 폴더를 만들고 그 안에 after-deploy.sh 파일을 추가합니다.

scripts/after-deploy.sh 파일

#!/bin/bash
REPOSITORY=/home/ubuntu/build

cd $REPOSITORY

sudo yarn

sudo pm2 start dist

위 명령어들은 EC2에 배포가 끝난 후 실행되는 명령어들입니다.

배포된 경로로 가서 필요한 dependency를 yarn 명령어로 설치해준 뒤
서버를 다시 시작해주는 역할을 합니다.

❗️yarn not found, pm2 not found 에러
nvm으로 node를 설치했을 때 sudo로 하면 실행이 안되는 문제입니다.

다음과 같이 해결 가능합니다.
sudo ln -s /root/.nvm/versions/node/v16.15.1/bin/yarn /usr/bin/yarn
sudo ln -s /root/.nvm/versions/node/v16.15.1/bin/pm2 /usr/bin/pm2

#!/bin/bash
REPOSITORY=/home/ubuntu/build

cd $REPOSITORY

sudo /usr/bin/yarn

sudo /usr/bin/pm2 start dist

deploy.yml 파일 수정

마지막으로 CI 과정에서 생성했던 deploy.yml 파일에 몇가지 작업을 추가해줘야합니다.

deploy.yml 파일

# This workflow will do a clean install of node dependencies, cache/restore them, build the source code and run tests across different versions of node
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions

name: deploy

on:
  push:
    branches: [develop]
  pull_request:
    branches: [develop]

jobs:
  build:
    runs-on: ubuntu-18.04

    strategy:
      matrix:
        node-version: [16.15.1]
        # See supported Node.js release schedule at https://nodejs.org/en/about/releases/

    steps:
      - name: Checkout source code.
        uses: actions/checkout@v2

      - name: Use Node.js ${{ matrix.node-version }}
        uses: actions/setup-node@v2
        with:
          node-version: ${{ matrix.node-version }}

      - name: Check Npm -v
        run: npm -v

      - name: create env file
        working-directory: ./
        run: |
          pwd
          touch .env
          echo PORT=${{ secrets.PORT }} >> .env
          echo MONGODB_URI=${{ secrets.MONGODB_URI }} >> .env
          echo JWT_SECRET=${{ secrets.JWT_SECRET }} >> .env
          echo JWT_ALGO=${{ secrets.JWT_ALGO }} >> .env
          cat .env

      - name: build server files
        working-directory: ./
        run: |
          yarn
          yarn run build
          
###################################### 추가된 부분 ######################################

      - name: zip file
        run: zip -r hous.zip ./dist ./scripts ./appspec.yml ./.env ./package.json

      - name: AWS configure credentials
        uses: aws-actions/configure-aws-credentials@v1
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          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 ./hous.zip s3://hous-build/deploy/

      - name: deploy with AWS codeDeploy
        run: aws deploy create-deployment
          --application-name hous-codedeploy
          --deployment-config-name CodeDeployDefault.OneAtATime
          --deployment-group-name GROUP
          --s3-location bucket=hous-build,bundleType=zip,key=deploy/hous.zip

zip file step 에서는 명시한 파일, 폴더들을 hous.zip 파일로 압축해줍니다.
AWS configure credentials step 에서는 S3에 접근하기 위한 IAM 사용자 키 값을 등록해주고
upload to S3 step 에서 실제로 S3에 hous.zip 압축파일을 옮겨줍니다.
deploy with AWS codeDeploy step 에서 AWS CodeDeploy가 실행되고 가장 아랫줄에 지정한 곳에서 압축 파일을 풀어서 CodeDeploy와 연결된 EC2 인스턴스에 배포해줍니다.

배포가 완료되면 after-deploy.sh 파일에 작성해둔 명령어들이 실행되면서 서버가 자동으로 재시작됩니다.

CI/CD 적용 확인

❗️상태가 전부 보류중으로 뜨고 진행이 되지 않는 경우 codedeploy-agent가 문제일 가능성이 큽니다.

sudo service codedeploy-agent status 명령어로 실행중인지 확인해보고
설치가 되지 않았다면 설치를 진행하고 실행중이라고 뜬다면
sudo service codedeploy-agent restart 명령어로 재실행하고 다시 시도해봅시다.

pm2 logs dist 명령어로 pm2 log를 확인할 수 있습니다.

CI/CD 서버 재시작까지 모두 성공한 모습입니다.

이렇게 한번 세팅을 해두면 더 이상 귀찮게 수동으로 배포하지 않아도 서버가 자동으로 배포됩니다.

profile
몰입을 즐기는 개발자입니다.

2개의 댓글

comment-user-thumbnail
2023년 8월 26일

너무 잘 봤습니다 덕분에 잘했는데요 혹시 yarn run build 커맨드로 어떤게 실행되게 설정하셨나요?

저는 build files 에서 몇분동안 멈춰있어서요..! node index.js 커맨드로 런했을 때용

1개의 답글