[AWS] 프로젝트 자동 배포하기(CICD) EC2 & S3 & CodeDeploy

시작하기 전에

본인은 현재 EC2 인스턴스를 생성했고, 그 위에 git 을 이용해 프로젝트를 clone 해놓은 상태이다.
가볍게 테스트 용도라 매번 pull 받고 서버를 동작시켰는데, 이번 기회에 해보고싶었던 배포 자동화를 추가해보려고한다.

진행 흐름

  • git 에서 push
  • 지정된 branch에서 push가 일어나면 build
  • s3에 build 파일 업로드(github actions)
  • s3에 있는 build 파일을 EC2에 업로드(CodeDeploy)

EC2

CodeDeploy agent 설치

EC2에 CodeDeploy가 접근하여 파일을 업로드 할수 있도록 code deploy agent를 설치한다.

AWS

AWS

1
2
3
4
5
6
7
sudo apt-get update
sudo apt-get install ruby
sudo apt-get install wget
cd /home/ubuntu
wget https://aws-codedeploy-ap-northeast-2.s3.ap-northeast-2.amazonaws.com/latest/install
chmod +x ./install
sudo ./install auto


IAM 권한 추가

EC2가 s3와 CodeDeploy를 이용할 수 있도록 권한 설정을 하자.

AWS

AWS

AWS

AWS

AWS

AWS


EC2 와 IAM 권한 연동

EC2 인스턴스 우클릭 -> 보안 -> IAM 역할 수정

AWS

AWS


S3

빌드 파일을 보관 할 S3 Bucket 을 생성해보자.

S3 Bucket 생성

버킷 이름을 지정해주고 CICD 전용 계정에서 접근할 수 있도록 ACL 을 활성화한다.
나머지는 기본 옵션 그대로 적용했다.

AWS

AWS

AWS

AWS

AWS

AWS


CodeDeploy

IAM 권한 추가

AWS

AWS

AWS

AWS

AWS


CodeDeploy 어플리케이션 생성

AWS

AWS


배포 그룹 생성

위에서 생성한 CodeDeploy 역할을 선택한다.

AWS

AWS

배포 방법: 현재위치 환경 구성 : Amazon EC2 인스턴스 태그 그룹 : Key = name / 값 = 생성한 EC2 인스턴스

AWS

로드 밸런싱 활성화 체크 해제

AWS

CodeDeploy 생성완료

CodeDeploy 생성이 완료됐다.
이제 Github action 을 통해 S3에 파일을 자동으로 업로드 하는 방법을 진행하자.

Github Actions

IAM 사용자 추가

github actions 가 s3에 접근하여 파일을 업로드 할 수 있도록 사용자를 추가하자.

AWS

AWS

AWS

AWS

AWS


Access key 발급

access key 와 secret key 는 github 에 등록해야 하니 따로 보관하자.

AWS

AWS


Access key 등록

레파지토리 -> Settings -> Secrets and variables -> Actions 를 선택한다.

  • AWS_ACCESS_KEY_ID : access-key
  • AWS_SECRET_ACCESS_KEY : secret-access-key
  • AWS_REGION : ap-northeast-2

AWS

AWS


AWS CLI

EC2 환경에 awscli 인스톨 및 설정을 진행하자.

1
2
3
4
5
6
7
8
9
10
# 설치
sudo apt install awscli
# 설치 확인
aws help
# 사용자 설정
aws configure
AWS Access Key ID [None]: 액세스 키를 입력
AWS Secret Access Key [None]: 시크릿 액세스 키를 입력
Default region name [None]: ap-northeast-2 # 혹시 리전이 다르면 해당 리전 기입
Default output format [None]: 그냥 Enter 입력


yml 파일 생성

아래 두가지에 대한 파일을 생성한다.

  • 깃헙의 업데이트 내용을 s3로 올리는 명령어 작성
  • s3에 올린 내용을 CodeDeploy를 통해 EC2로 업로드 하는 명령어 작성


리엑트 프로젝트의 폴더 구조는 아래와 같다.

1
2
3
4
5
6
7
.github
 ┣ workflows
 ┃ ┣ deploy.yml
appspec.yml
src
node_modules
public

deploy.yml

  • S3 버킷에 파일을 업로드 하는 내용
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
name: Deploy # Workflow 이름
on: # Event 감지
  push:
    branches:
      - develop # 해당 브랜치의 푸쉬가 일어날 때 CI/CD를 진행하겠다는 뜻
jobs:
  build:
    runs-on: ubuntu-20.04
    steps:
      # - name: Checkout source code. # Repo checkout
      #   uses: actions/checkout@v2
      - uses: actions/checkout@v4
      - name: Use Node.js
        uses: actions/setup-node@v3
        with:
          node-version: "18.x"

      - name: Check Node v # Node v 확인
        run: node -v

      - name: Install Dependencies # 의존 파일 설치
        run: npm install --legacy-peer-deps --frozen-lockfile

      - name: Build # React Build
        run: yarn build
        env:
          CI: ""

      - name: zip create
        # zip 파일을 만듭니다(파일명은 자유, 대신 아래 workflow에 적을 파일명과 동일하게 맞춰주세요).
        # 여기서는 build-app.zip
        run: zip -qq -r ./build-app.zip .
        shell: bash

      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v1
        with:
          aws-access-key-id: $
          aws-secret-access-key: $
          aws-region: $

      - name: Upload to S3 # Upload build file to S3
        env:
          AWS_ACCESS_KEY_ID: $
          AWS_SECRET_ACCESS_KEY: $
        run: |
          aws s3 cp --region ap-northeast-2 ./build-app.zip s3://<S3버킷이름>/build-app.zip

      - name: Deploy # Deploy to EC2
        run: aws deploy create-deployment
          --application-name <CodeDeploy어플리케이션이름>
          --deployment-config-name CodeDeployDefault.AllAtOnce
          --deployment-group-name <CodeDeploy배포그룹이름>
          --s3-location bucket=<S3버킷이름>,key=build-app.zip,bundleType=zip


appspec.yml

  • s3에 빌드파일 zip을 ec2에 배포하는 역할
  • appspec.yml은 프로젝트 루트경로에 생성
  • 파일의 이름은 반드시 appspec.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
version: 0.0
os: linux

files:
  - source: /
    destination: /home/ubuntu/deploy-fe
    overwrite: yes
file_exists_behavior: OVERWRITE
permissions:
  - object: /home/ubuntu/deploy-fe
    owner: ubuntu
    group: ubuntu
    mode: 755
hooks:
  AfterInstall:
    - location: deploy.sh
      timeout: 60
      runas: root


deploy.sh

1
2
3
4
5
6
#!/bin/bash
REPOSITORY=/home/ubuntu/deploy-fe # 배포된 프로젝트 경로.

cd $REPOSITORY # 이 경로로 이동해서 밑에 명령어들을 차례로 실행.

sudo npm install --legacy-peer-deps # 의존성 파일 설치.


빌드 및 배포 확인

빌드 된 파일이 올라온걸 확인 할 수있다.

AWS

AWS

AWS

Nginx 설치

1
2
3
4
5
6
7
8
9
10
11
## Nginx 설치
sudo apt-get install nginx

## 기본화면으로 연결되는 Nginx 설정파일 삭제
sudo rm /etc/nginx/sites-available/default
sudo rm /etc/nginx/sites-enabled/default

## 설정파일 생성
cd /etc/nginx/sites-available/
sudo touch myapp.conf
sudo vi myapp.conf

이제 Nginx 설정파일의 내용을 입력한다.

1
2
3
4
5
6
7
8
server {
  listen 10134;
  location / {
    root   /home/ubuntu/deploy-fe/build;
    index  index.html index.htm;
    try_files $uri $uri/ /index.html;
  }
}
  • root의 /home/ubuntu/deploy-fe/build 는 React의 빌드 산출물 경로
  • listen 10134은 포트번호에 대한 설정을 의미
  • location /는 URL이 ‘/’가 포함된 경로에 대한 설정을 의미
  • index는 인덱스의 파일들을 지정하는 곳이고, 이 파일들 중 꼭 하나는 root 경로 안에 존재해야 한다.
  • try_files는 어떤 파일을 찾을 때 명시된 순서로 찾으며, 가장 먼저 발견되는 파일을 사용한다는 의미
1
2
3
4
5
6
7
## 심볼릭링크생성
sudo ln -s /etc/nginx/sites-available/myapp.conf /etc/nginx/sites-enabled/myapp.conf

## Nginx  실행
sudo systemctl stop nginx
sudo systemctl start nginx
systemctl status nginx


최종 확인

이제 퍼블릭 IP 로 접속하면 배포한 React 프로젝트를 확인 할 수있다.

CodeDeploy Log 확인

1
less /var/log/aws/codedeploy-agent/codedeploy-agent.log


Nginx Log 확인

1
tail -f /var/log/nginx/error.log


주의할점

생각보다 권한과 스토리지 오류가 많이 발생한다.

잘 기억하자. 우리의 흐름은 아래와 같다.

github action -> S3 -> CodeDeploy -> EC2 Nginx

github action 은 Repositry 의 action 에서 바로 확인 가능하지만, 다음 스텝에서의 에러내용은 직관적이지 않다.
그러니 에러가 발생한다면 위 명령어를 통해 로그를 확인하는 습관을 가지자.
직접 작업하면서 발생한 에러는 아래와 같다.

  1. 저장 공간 부족

No space left on device @ fptr_finalize_flush - /opt/codedeploy-agent/deployment-root/deployment-instructions/~~/cleanup
EC2 의 스토리지가 부족하다는 의미이다. df -h 를 이용해 저장 공간을 확인 후 파일 정리를 하거나 저장공간을 늘리자.


  1. 권한 부족

stat() failed (13: permission denied)
EC2 의 유저가 해당 디렉토리에 접근할 권한이 없다는 내용이다.
간단하다. 해당 경로에 대해 권한을 추가하자.

1
2
3
chmod +x /home/
chmod +x /home/username
chmod +x /home/username/siteroot


소감

CICD 를 작업하면서 정말 재미있었다.
처음 접해보기에 부족한 점은 많겠지만 부딪혀보았기에 다음에는 좀 더 클린하게 작업 할 수 있을거라고 생각한다.
나중에는 만들어둔 토이 프로젝트들을 좀 더 다듬어 자동배포되게끔 하고싶다는 마음이 들었지만.. AWS 비용때문에 쉽지 않을거같다.
모두 화이팅입니다.

Tags: ,

Updated:

Leave a comment