[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를 설치한다.
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를 이용할 수 있도록 권한 설정을 하자.
EC2 와 IAM 권한 연동
EC2 인스턴스 우클릭 -> 보안 -> IAM 역할 수정
S3
빌드 파일을 보관 할 S3 Bucket 을 생성해보자.
S3 Bucket 생성
버킷 이름을 지정해주고 CICD 전용 계정에서 접근할 수 있도록 ACL 을 활성화한다.
나머지는 기본 옵션 그대로 적용했다.
CodeDeploy
IAM 권한 추가
CodeDeploy 어플리케이션 생성
배포 그룹 생성
위에서 생성한 CodeDeploy 역할을 선택한다.
배포 방법: 현재위치 환경 구성 : Amazon EC2 인스턴스 태그 그룹 : Key = name / 값 = 생성한 EC2 인스턴스
로드 밸런싱 활성화 체크 해제
CodeDeploy 생성완료
CodeDeploy 생성이 완료됐다.
이제 Github action 을 통해 S3에 파일을 자동으로 업로드 하는 방법을 진행하자.
Github Actions
IAM 사용자 추가
github actions 가 s3에 접근하여 파일을 업로드 할 수 있도록 사용자를 추가하자.
Access key 발급
access key 와 secret key 는 github 에 등록해야 하니 따로 보관하자.
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 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 # 의존성 파일 설치.
빌드 및 배포 확인
빌드 된 파일이 올라온걸 확인 할 수있다.
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 에서 바로 확인 가능하지만, 다음 스텝에서의 에러내용은 직관적이지 않다.
그러니 에러가 발생한다면 위 명령어를 통해 로그를 확인하는 습관을 가지자.
직접 작업하면서 발생한 에러는 아래와 같다.
- 저장 공간 부족
No space left on device @ fptr_finalize_flush - /opt/codedeploy-agent/deployment-root/deployment-instructions/~~/cleanup
EC2 의 스토리지가 부족하다는 의미이다. df -h
를 이용해 저장 공간을 확인 후 파일 정리를 하거나 저장공간을 늘리자.
- 권한 부족
stat() failed (13: permission denied)
EC2 의 유저가 해당 디렉토리에 접근할 권한이 없다는 내용이다.
간단하다. 해당 경로에 대해 권한을 추가하자.
1
2
3
chmod +x /home/
chmod +x /home/username
chmod +x /home/username/siteroot
소감
CICD 를 작업하면서 정말 재미있었다.
처음 접해보기에 부족한 점은 많겠지만 부딪혀보았기에 다음에는 좀 더 클린하게 작업 할 수 있을거라고 생각한다.
나중에는 만들어둔 토이 프로젝트들을 좀 더 다듬어 자동배포되게끔 하고싶다는 마음이 들었지만.. AWS 비용때문에 쉽지 않을거같다.
모두 화이팅입니다.
Leave a comment