본문 바로가기

Infra

AWS와 Github로 Node CICD 연결하기

반응형
SMALL

CI (Continuous Integration, 지속적 통합) 

CI, 즉 지속적 통합은 새로운 코드의 변경 사항이 정기적으로 빌드 및 테스트 되어 한 레포지토리에서 통합되는 것을 의미합니다.

개발자들이 협업을 진행할 때, 병합 과정에서의 충돌을 방지할 수 있고 작업을 빠르고 효율적으로 진행할 수 있습니다.

 

그럼 깃허브 액션을 사용하여 Node 파일을 CI 세팅해봅시다.

 

Github Actions Secrets

먼저 깃허브 액션을 사용하기 위해, .env 파일 내용을 환경변수로 등록해야 합니다.

setting > security > secrets and variables > actions 으로 들어가서 .env 파일의 내용을 환경변수로 등록해주세요.

 

New Repository secrete 버튼을 눌러서 환경변수를 등록할 수 있습니다!

 

Workflows

다음으로 CI 를 위한 작업 파일을 만들어주어야 합니다. 프로젝트에서 .github/workflows/deploy.yml 파일을 만들어주세요.

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

develop 브랜치에 push 하거나 pull request를 날릴 때 작업을 수행합니다.

 

  build:
    runs-on: ubuntu-20.04

    strategy:
      matrix:
        node-version: [16.x]

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

      - name: Use Node.js ${{ matrix.node-version }}
        uses: actions/setup-node@v3
        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 DATABASE_URL=${{ secrets.DATABASE_URL }} >> .env
          echo SLACK_URL=${{ secrets.SLACK_URL }} >> .env
          echo JWT_SECRET=${{ secrets.JWT_SECRET }} >> .env
          echo TEST_ACCESS_TOKEN=${{ secrets.TEST_ACCESS_TOKEN }} >> .env
          echo FIXED_ACCESS_TOKEN=${{ secrets.FIXED_ACCESS_TOKEN }} >> .env
          cat .env

.env 파일을 생성합니다. (레포지토리에 노출되지 않아야 하는 파일이므로 별도로 생성되어야 합니다.)

 

      - name: build server files
        working-directory: ./
        run: |
          yarn
          yarn run build

프로젝트를 build 합니다.

 

전체 코드

name: deploy

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

jobs:
  build:
    runs-on: ubuntu-20.04

    strategy:
      matrix:
        node-version: [16.x]

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

      - name: Use Node.js ${{ matrix.node-version }}
        uses: actions/setup-node@v3
        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 DATABASE_URL=${{ secrets.DATABASE_URL }} >> .env
          echo SLACK_URL=${{ secrets.SLACK_URL }} >> .env
          echo JWT_SECRET=${{ secrets.JWT_SECRET }} >> .env
          echo TEST_ACCESS_TOKEN=${{ secrets.TEST_ACCESS_TOKEN }} >> .env
          echo FIXED_ACCESS_TOKEN=${{ secrets.FIXED_ACCESS_TOKEN }} >> .env
          cat .env
      - name: build server files
        working-directory: ./
        run: |
          yarn
          yarn run build

 

CI TEST

develop 브랜치에 push 또는 PR을 날리면 위와 같이 정상적으로 실행된 것을 확인할 수 있습니다. 충돌 없이 잘 통합되었을 때의 결과 입니다. 또한, 왼쪽의 Jobs > build 탭을 선택하면 yml 파일을 수행한 과정과 로그를 확인할 수도 있습니다.

 

CD (Continuous Deployment, 지속적 배포)

CD, 즉 지속적 배포는 새로운 코드의 변경 사항이 레포지토리를 넘어서 프로덕션 환경까지 릴리즈 되는 것을 의미합니다. 다시 말해서 자동으로 배포해주는 것입니다. 이 포스팅에서는 AWS의 Code deploy를 활용하여 EC2 까지 자동으로 배포되도록 설정해보겠습니다.

 

AWS S3

깃허브 액션에서 빌드한 프로젝트를 저장하기 위해 AWS에서 S3를 생성해주어야 합니다.

S3 > 버킷 > 버킷 만들기로 이동해주세요.

 

우선 버킷 이름 설정 및 AWS 리전만 확인 후 버킷 만들기를 실행해서 버킷을 만들어주세요.

 

AWS IAM - Codedepoly, S3

EC2가 S3와 Codedeploy를 이용할 수 있도록 권한을 부여해야 합니다.

IAM > 역할 > 역할생성 으로 이동해주세요.

 

AWS 서비스와 EC2를 선택하고 다음으로 넘어가주세요.

 

AWSCodeDeployFullAccess 와 AmazonS3FullAccess 권한을 선택해주세요.

 

이름을 지정하고, 확인 및 검토 후 역할을 생성해주세요.

 

EC2 권한 부여

EC2에 권한을 부여하기 위해, 프로젝트를 배포할 EC2의 작업 > 보안 > IAM 역할 수정으로 들어가주세요.

 

위 단계에서 만든 IAM을 선택하고 IAM 역할을 업데이트 해주세요.

 

AWS IAM - Codedeploy

다음으로 Codedeploy를 위한 IAM을 생성해야 합니다.

IAM 생성으로 다시 돌아와서 CodeDeploy를 검색하여 선택해주고 다음으로 넘어가주세요.

 

권한 정책을 확인하고 다음으로 넘어가주세요.

 

역할 이름을 지정하고 역할을 생성해주세요.

 

Code Deploy

다음으로 코드 자동 배포화를 위해 codedeploy의 애플리케이션을 생성해주어야 합니다.

 

CodeDeploy > 애플리케이션 > 애플리케이션 생성으로 들어가주세요.

이름을 지정하고, EC2/온프레미스를 선택하여 애플리케이션을 생성해주세요.

 

생성한 애플리케이션으로 들어가서, 하단에서 배포 그룹을 생성해주어야 합나디ㅏ. 배포 그룹 생성을 눌러주세요.

 

배포 그룹 이름을 지정하고, 위에서 만든 IAM 역할을 서비스 역할에서 선택해주세요.

 

환경 구성에서 EC2 인스턴스를 선택하고 태그 그룹에서 키와 값을 선택해주세요.

 

AWS IAM 사용자

다음으로 깃허브 액션에서 S3에 접근하여 파일을 배포할 수 있도록 사용자를 생성해주어야 합니다.

 

AWS > IAM > 사용자 > 사용자 추가로 이동해주세요.

 

사용자 이름을 지정하고, 자격 증명 유형에서 액세스 키 - 프로그래밍 방식 액세스를 선택하고 다음으로 넘어가주세요.

 

권한 설정에서 기존 정책 직접 연결을 선택하여 AWSCodeDeployFullAccess와 AmazonS3FullAccess를 검색하여 추가한 후 다음으로 넘어가주세요.

 

다음을 선택하여 과정 확인 및 검토 후, 사용자를 생성하면 Access Key Id와 Secret Access Key를 얻을 수 있습니다. 해당 페이지를 한번 나가면 다시는 찾을 수 없으니..!! 개인적인 공간에 복붙해두거나 csv 파일을 꼭 미리 받아주시길 바랍니다.

 

복붙 또는 받아둔 파일에서 Access Key Id와 Secret Access Key를 CI에서 진행한 것과 같이 깃허브에 환경 변수로 등록해주세요.

 

 

EC2 Codedeploy Agent 설치

AWS에서 생성 및 설정해야 하는 과정은 끝났습니다. 이제 EC2를 연결하여 우분투로 접속하여 해당 과정을 수행해주세요.

 

기본적으로 프로젝트에서 필요한 npm, yarn, git, node, pm2은 미리 설치해주시기 바랍니다.

 

$ sudo apt update
$ sudo apt install awscli

awscli를 설치합니다.

 

$ 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

앞서 사용자 추가해서 얻은 Access Key Id와 Secret Access Key를 입력하고, 리전과 포맷을 지정해주세요.

 

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

agent 파일을 설치하고, 권한을 추가해주세요.

 

$ sudo apt-get install ruby
$ sudo ./install auto
$ sudo service codedeploy-agent status

codedeploy agent 파일을 설치해주세요.

 

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

파일을 생성하고,

 

#!/bin
sudo service codedeploy-agent restart

위 내용으로 복붙하여 작성해주세요.

 

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

권한 추가 합니다.

 

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

프로젝트 루트에 appspec.yml 파일을 추가하여 위 내용을 추가해주세요.

destination에서 EC2 배포 파일을 빌드하고, location의 파일에서 빌드 후 작업을 정의합니다.

 

after-deploy.sh

빌드 후 이루어질 작업을 정의하는 파일입니다. 프로젝트에서 scripts/after-deploy.sh 파일을 추가하여 아래의 내용을 추가해주세요.

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

cd $REPOSITORY

sudo /usr/bin/yarn

sudo /usr/bin/pm2 start dist

우분투로 프로젝트가 옮겨진 후, yarn 하고 pm2 start dist 하여 배포합니다.

 

deploy.yml 파일 추가

CI 단계에서 작성했던 deploy.yml 파일에 아래 내용을 추가해줍니다.

 

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

dist, scripts, appspec, .env, package.json, prisma 파일을 zip 파일로 묶어 생성합니다. DB 툴로 prisma를 사용하고 있으므로 ./prisma도 추가해주어야 합니다.

 

      - 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

사용자 추가에서 얻은 access key를 지정해줍니다.

 

      - name: upload to S3
        run: aws s3 cp --region ap-northeast-2 ./smeme.zip s3://smeme-bucket/deploy/

S3에 업로드 합니다.

 

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

codeploy를 통해 프로젝트를 배포합니다.

 

전체 코드

name: deploy

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

jobs:
  build:
    runs-on: ubuntu-20.04

    strategy:
      matrix:
        node-version: [16.x]

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

      - name: Use Node.js ${{ matrix.node-version }}
        uses: actions/setup-node@v3
        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 DATABASE_URL=${{ secrets.DATABASE_URL }} >> .env
          echo SLACK_URL=${{ secrets.SLACK_URL }} >> .env
          echo JWT_SECRET=${{ secrets.JWT_SECRET }} >> .env
          echo TEST_ACCESS_TOKEN=${{ secrets.TEST_ACCESS_TOKEN }} >> .env
          echo FIXED_ACCESS_TOKEN=${{ secrets.FIXED_ACCESS_TOKEN }} >> .env
          cat .env

      - name: build server files
        working-directory: ./
        run: |
          yarn
          yarn run build
      
      - name: zip file
        run: zip -r smeme.zip ./dist ./scripts ./appspec.yml ./.env ./package.json ./prisma
      
      - 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 ./smeme.zip s3://smeme-bucket/deploy/

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

 

CD TEST

develop 브랜치에 머지하고 깃허브 액션을 확인하면 정상적으로 실행 완료된 결과를 확인할 수 있습니다. 이를 확인하고 배포된 EC2의 ip로 API를 테스트 해보면 정상적으로 변경 사항이 반영된 것을 확인할 수도 있습니다.

 

 

효율적인 개발 작업을 위해 초반에 여러 레퍼런스를 참고하여 CICD를 세팅하였으나, 해당 프로젝트에서는 prisma를 사용하는 차별점이 있어서 deploy.yml 파일을 잘못 작성하여 CD TEST를 계속 실패하였습니다. prisma를 사용할 경우에는 deploy.yml 파일에서 ./prisma 파일을 추가해주고, 추가적으로 pakage.json 파일에서 script에

    "postinstall": "prisma generate",

위 내용을 추가해주세요. npx prisma generate 과정이 필요합니다. DB의 변경으로 삽질을 경험하면서 기록 겸 공유로 포스팅을 작성하였습니다.

 

 

 

 

References

https://velog.io/@server30sopt/Github-Actions-AWS-CodeDeploy%EB%A5%BC-%ED%99%9C%EC%9A%A9%ED%95%9C-CICD-Node.js1

https://velog.io/@server30sopt/Github-Actions-AWS-CodeDeploy%EB%A5%BC-%ED%99%9C%EC%9A%A9%ED%95%9C-CICD-Node.js2

반응형
LIST