본문 바로가기
Research/CICD

CICD_github action-s3-codedeploy로 CICD 구축하기

by RIEM 2023. 3. 10.

배경지식

목표

  • Github Action s활용하여 nest.js로 만든 어플리케이션을 EC2에 자동으로 배포한다

CICD

  • CI(Continuous Integration, 지속적 통합) : CI를 구축하면 어플리케이션 관련 코드가 바뀔 때마다 Build와 Test를 자동화해준다
  • CD(Continuous Delivery|Deployment, 지속적 배포) :

즉, 배포 전에 CI 단계에서 어플리케이션 문제 여부를 검증한 뒤, 검증한 어플리케이션을 프로덕션 환경으로 자동 배포해주는 것이 CI/CD의 핵심이다.

CI

Github 환경변수 등록

Github action 환경변수 등록 페이지로 가서 환경변수를 등록해주자. 우리 프로젝트는 보안을 위해 .gitignore 를 사용하여 .env를 따로 올리지 않도록 설정했을 것이다. 그러므로 환경 변수에 대한 정보를 따로 github action에게 전달해주는 작업을 해주기 위함이다.

우선 Github 저장소에 Settings -> Secrets and variables -> Actions으로 이동

Screen Shot 2023-02-22 at 6 00 00 PM

Screen Shot 2023-02-22 at 6 05 29 PM
New repository secret 버튼을 누르고 .env 파일에 있는 환경 변수들을 하나씩 등록해주자.

Screen Shot 2023-02-22 at 6 07 57 PM

등록 완료 후 리스트로 보인다면 성공적으로 환경 변수가 등록된 것이다.

Github Actions workflow

github workflow 생성하기 위해 deploy.yml 파일을 생성해주어야 한다. 루트 디렉토리에 .github/workflows/deploy.yml 경로로 파일을 생성해준다. (.github 디렉터리에 점.을 꼭 붙여주어야 한다)

deploy.yml 파일 작성

name: deploy

on:
  push:
    branches: [main] # Workflow is triggered when you push to these branches
  pull_request:
    branches: [main]

jobs:
  build:
    runs-on: ubuntu-18.04 # ex) EC2 instance

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

    # What you will do after (repository code -> CI server)
    steps:
      - name: Checkout source code.
        uses: actions/checkout@v2

      - name: Use Node.js ${{ matrix.node-version }} # install Node.js with the version you wrote above
        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 NODE_SERVER_PORT=${{ secrets.NODE_SERVER_PORT }} >> .env
          echo JWT_SECRET=${{ secrets.JWT_SECRET }} >> .env
          echo HTTPS_PORT=${{ secrets.HTTPS_PORT }} >> .env
          echo HTTP_PORT=${{ secrets.HTTP_PORT }} >> .env
          echo RDS_HOST=${{ secrets.RDS_HOST }} >> .env
          echo RDS_PORT=${{ secrets.RDS_PORT }} >> .env
          echo RDS_USERNAME=${{ secrets.RDS_USERNAME }} >> .env
          echo RDS_PASSWORD=${{ secrets.RDS_PASSWORD }} >> .env
          echo RDS_DATABASE_NAME=${{ secrets.RDS_DATABASE_NAME }} >> .env
          cat .env

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

위와 같이 파일을 작성하고 우리의 저장소로 코드를 push 해주면..

Screen Shot 2023-02-22 at 6 34 37 PM
Action 페이지에 들어가면 workflow가 생성되어 자동으로 돌아가는 것을 볼 수 있다. 빌드 성공 여부에 따라 성공/실패 결과가 나온다.

CD

CI를 해주었으니, CD를 해주자.

AWS CodeDeploy를 활용하기 위해 추가로 설정을 해주자.

AWS S3 버킷 생성

AWS 스토리지 서비스인 S3에서 스토리지인 '버킷'을 생성해주자. Github Actions에 빌드한 프로젝트를 AWS에 저장하기 위해 사용한다.

Screen Shot 2023-02-22 at 6 37 51 PM

그 외 옵션은 default로 해주고 그냥 바로 버킷을 생성해주자.

EC2를 위한 IAM 생성 및 적용

EC2가 S3와 CodeDeploy를 사용하려면 권한 정보를 다루는 IAM을 사용하면 된다.

IAM -> Access management -> Roles -> Create role
Screen Shot 2023-02-22 at 6 44 26 PM

  • trusted entity : AWS service
  • Use case : EC2
  • 그 외 패스
  • -> 다음 페이지

Screen Shot 2023-02-22 at 6 46 59 PM
권한 추가에 2개를 추가하면 된다

  • AWSCodeDeployFullAccess
  • AmazonS3FullAccess

지금 생성하는 IAM 역할이 이 2개의 영역을 관리할 수 있는 Full 권한을 주는 것이다.
-> 다음!

Screen Shot 2023-02-22 at 6 52 30 PM
IAM 역할의 이름을 지어준 다음 생성하기 버튼을 누른다.

이 다음에는 이렇게 만든 역할을 EC2에 연결해주는 작업을 할 것이다.

EC2 인스턴스의 보안그룹 메뉴에서 IAM 역할 수정 클릭
Screen Shot 2023-02-22 at 6 55 14 PM

우리가 만든 IAM('ec2-deploy') 연동하고 업데이트해주기
Screen Shot 2023-02-22 at 6 56 46 PM

CodeDeploy를 위한 IAM 생성 및 적용

CodeDeploy를 위한 IAM도 추가로 생성해주어야 한다.

AWS-> IAM -> Roles -> Create Role

Screen Shot 2023-02-22 at 6 59 48 PM

여기서 아까의 방식과 다른 점은 EC2가 아닌 CodeDeploy를 Use case에 등록한다는 점이다.
-> 다음

Screen Shot 2023-02-22 at 7 01 28 PM
자동으로 AWSCodeDeployRole 권한 추가가 설정되어 있다. 그냥 그대로 다음 페이지로 넘어간다.

Screen Shot 2023-02-22 at 7 02 42 PM
이름만 추가해주고 IAM 역할 생성해준다.

CodeDeploy 어플리케이션 생성

AWS -> CodeDeploy -> Application -> Create Application 경로로 간다.

Screen Shot 2023-02-22 at 7 04 17 PM

  • Application 이름은 알아서 정하고
  • 컴퓨팅 플랫폼을 EC2/On-premises로 설정해준 뒤
  • -> Create application

이 다음 배포 그룹을 생성해주면 된다.
Screen Shot 2023-02-22 at 7 06 21 PM

Screen Shot 2023-02-22 at 7 07 17 PM

배포 그룹은 그냥 알아서 정하고

Service role을 우리가 생성했던 CodeDeploy IAM을 지정해준다.

Screen Shot 2023-02-22 at 7 09 02 PM

Deployment type은 In-place(현재 위치)로 되어있는데 그대로 두면 된다.

Environment configuration에서 EC2 Instance를 선택해주고, 연결할 EC2 인스턴스를 선택해준다.

Screen Shot 2023-02-22 at 7 10 44 PM

그 다음 Load Balancer 체크는 해제해주고 나머지는 그냥 그대로 진행하면 된다.
-> Create deployment group!!

AWS IAM 사용자 추가

IAM 사용자를 추가해주자. 역할(Role)이 아니라 사용자(User)다.
Github Action에서 S3에 접근해서 파일을 업로드하도록 하기 위함이다.

AWS -> IAM -> Access management -> Users -> Add users

Screen Shot 2023-02-22 at 7 13 44 PM

Screen Shot 2023-02-22 at 7 19 04 PM
이름 지정해주고 진행

Screen Shot 2023-02-22 at 7 19 55 PM

기존 정책은

  • AWSCodeDeployFullAccess
  • AmazonS3FullAccess

이 두개를 선택해준 다음. 유저 생성하기까지 완료해준다.

deployUser에서 access key 생성하기 버튼을 누른다
Screen Shot 2023-02-22 at 7 22 52 PM
Access key에서 Application running on an AWS compute service 옵션을 선택.

Screen Shot 2023-02-22 at 7 24 59 PM
다음 누르면 공개 키와 비밀 키가 나온다. 잘 저장해두자.

위 키 2개를 Github action 환경변수에 추가

Screen Shot 2023-02-22 at 7 28 14 PM

EC2 CodeDeploy Agent 설치

전제조건

  • npm, yarn, git, node, pm2가 이미 설치되어있어야 한다.

AWS CodeDeploy 사용을 위한 준비..

awscli 설치

$ sudo apt update
$ sudo apt install 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

CodeDeploy Agent 설치 파일 다운받고 install 파일에 권한 추가

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

ruby 설치 후 , Code Deploy Agent 설치해준다..

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

Screen Shot 2023-02-22 at 7 45 41 PM
Codedeploy-agent가 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 추가해주자. CodeDeploy가 배포 관리 시 참고하는 애플리케이션 사양 파일이다.
CodeDeploy가 EC2에 프로젝트를 옮기면, EC2에서 무슨 작업을 수행할지 이 파일에 정의한다.

appspec.yml

version: 0.0
os: linux
files:
  - source: /
    destination: /home/ubuntu/build # CodeDeploy가 EC2에 배포할 위치
    overwrite: yes

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

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

after-deploy.sh

after-deploy.sh는 프로젝트가 옮겨진 이후 수행할 작업들 정의한 파일이다. 배포할 프로젝트 루트 경로에 scripts 폴더 만든 뒤 이 파일을 생성해주자.

scripts/after-deploy.sh

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

cd $REPOSITORY

sudo npm install # npm으로 dependency 설치

# sudo pm2 start dist
sudo npm run start:dev

deploy.yml 파일 수정

아까 CI단계에서 만들었던 파일에 작업들 추가해주자.

deploy.yml

name: deploy

on:
  push:
    branches: [main] # Workflow is triggered when you push to these branches
  pull_request:
    branches: [main]

jobs:
  build:
    runs-on: ubuntu-18.04 # ex) EC2 instance

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

    # What you will do after (repository code -> CI server)
    steps:
      - name: Checkout source code.
        uses: actions/checkout@v2

      - name: Use Node.js ${{ matrix.node-version }} # install Node.js with the version you wrote above
        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 NODE_SERVER_PORT=${{ secrets.NODE_SERVER_PORT }} >> .env
          echo JWT_SECRET=${{ secrets.JWT_SECRET }} >> .env
          echo HTTPS_PORT=${{ secrets.HTTPS_PORT }} >> .env
          echo HTTP_PORT=${{ secrets.HTTP_PORT }} >> .env
          echo RDS_HOST=${{ secrets.RDS_HOST }} >> .env
          echo RDS_PORT=${{ secrets.RDS_PORT }} >> .env
          echo RDS_USERNAME=${{ secrets.RDS_USERNAME }} >> .env
          echo RDS_PASSWORD=${{ secrets.RDS_PASSWORD }} >> .env
          echo RDS_DATABASE_NAME=${{ secrets.RDS_DATABASE_NAME }} >> .env
          cat .env

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

      ################## CD 구축 단계에서 추가 부분

      # 명시한 파일, 폴더들을 pyramid.zip 파일로 압축
      - name: zip file
        # run: zip -r pyramid.zip ./dist ./scripts ./appspec.yml ./.env ./package.json
        run: zip -r pyramid.zip ./dist ./scripts ./src ./test ./appspec.yml ./.env ./package.json ./package-lock.json ./nest-cli.json ./readme.md ./tsconfig.build.json ./tsconfig.json

      # S3 접근을 위한 IAM 사용자 키값등록
      - 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

      # S3에 압축 파일을 옮겨줌
      - name: upload to S3
        run: aws s3 cp --region ap-northeast-2 ./pyramid.zip s3://pyramid-build/deploy/

      # AWS CodeDeploy 실행 시 가장 아랫줄 지정한 곳에 압축 파일 푼 뒤, CodeDeploy와 연결된 EC2 인스턴스에 배포
      - name: deploy with AWS codeDeploy
        run: aws deploy create-deployment
          --application-name pyramid-test-codedeploy
          --deployment-config-name CodeDeployDefault.OneAtATime
          --deployment-group-name GROUP
          --s3-location bucket=pyramid-build,bundleType=zip,key=deploy/pyramid.zip

      # 배포 완료 후 after-deploy.sh 저장한 명령어들이 실행되면서 서버 자동 재시작

레퍼런스

'Research > CICD' 카테고리의 다른 글

Github 액션 관련 요약  (0) 2023.12.09
CICD_Jenkins vs Github Action  (0) 2023.02.15
깃허브 액션 관련 영상 요약  (0) 2023.02.15

댓글