2023. 12. 20. 20:01ㆍTEAM-PROJECT/IMAD-WEB
들어가기에 앞서..
본격적으로 프로젝트의 틀을 마련하기 전에 AWS 서버에 배포 자동화 프로세스를 구현하고 시작을 하기로 하였다.
AWS 에 배포를 해본적은 있지만 빌드 파일 만 올려 작동시키는것은 기존에 전체 파일을 전부 업로드 시켜 구동 시키는것보다 효율적이라고 생각이 들었다.
CI 와 CD 란?
이제 막 프로젝트를 시작한 나에겐 이러한 용어들이 커다란 장벽으로 다가오는 느낌이다.
하지만 지금까지 배웠던 내용들도 부르는 용어가 생소 했을 뿐이지 그렇게 까지 어려웠던 내용은 없었던 경험을 생각해 간단히 검색을 해보았다.
CI (Continuous Integration) 지속적인 통합
간단히 말하자면 빌드 및 테스트의 자동화를 의미한다. 프로젝트의 인원이 많다면 각자의 브랜치에서 개발을 진행을 하다가 하나의 브랜치로 통합하고 빌드하는 과정을 거치는데 이때 발생되는 에러등을 디버깅하고 리빌딩 하는 과정을 거친다 이것을 자동화 하는 의미라고 이해했다.
CD (Continuous Deployment) 지속적인 배포
CD는 배포의 자동화를 의미한다. 위에 기술한 CI 과정이 문제없이 끝나 빌드가 완료되면 자동으로 배포하여 서비스 하는것을 의미한다고 이해했다.
github action
이런 배포 자동화 과정에서 사용할수있는 툴중 하나다!
우리가 평소에 github에 푸쉬를 하듯 푸쉬를 하면 그 해당 푸쉬를 트리거로 작동하여 테스트 배포 빌드등 일련의 반복과정을 자동으로 실행시켜주는 툴이다.
반복을 싫어해야하는 개발자의 의지가 보여진다.
#1 .github 폴더안에 workflows 폴더 만들기
프로젝트 폴더속에 .github폴더 그안에 workflows 폴더를 만들고 임의의 이름을가진 .yml 파일을 만들어준다.
name: Deploy # Workflow 이름
on: # Event 감지
push:
branches:
- release # 해당 브랜치의 푸쉬가 일어날 때 CI/CD를 진행하겠다는 뜻
env:
S3_BUCKET_NAME: ryuforaws01-github-actions-s3-bucket
CODE_DEPLOY_APP_NAME: deploy-application-front
CODE_DEPLOY_DEPLOYMENT_GROUP_NAME: deploy-group-front
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout source code. # Repo checkout
uses: actions/checkout@v2
- name: Check Node v # Node v 확인
run: node -v
- name: Install Dependencies # 의존 파일 설치
run: yarn install
- name: Build # React Build
run: yarn build
env:
CI: ""
- name: zip create
# zip 파일을 만듭니다(파일명은 자유, 대신 아래 workflow에 적을 파일명과 동일하게 맞춰주세요).
run: zip -qq -r ./build-fe.zip .
shell: bash
- name: Configure AWS 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: ${{ secrets.AWS_REGION }}
# 빌드 결과물을 S3 버킷에 업로드
- name: Upload to AWS S3
run: |
aws s3 cp --region ap-northeast-2 ./build-fe.zip s3://$S3_BUCKET_NAME/$GITHUB_SHA.zip
- name: Deploy # Deploy to EC2
run: |
aws deploy create-deployment \
--application-name ${{ env.CODE_DEPLOY_APP_NAME }} \
--deployment-config-name CodeDeployDefault.AllAtOnce \
--deployment-group-name ${{ env.CODE_DEPLOY_DEPLOYMENT_GROUP_NAME }} \
--s3-location bucket=$S3_BUCKET_NAME,key=$GITHUB_SHA.zip,bundleType=zip
해당 deploy.yml 파일의 내용물이다. 주석에 해당되는 내용과 aws 파일의 이름 주소등을 정확히 기재해야한다.
#2 AWS 사전설정하기
AWS 측에서도 기존에 있던 서버설정들의 수정과 새로운 추가설정들이 필요하다. 나는 이프로젝트의 늦게 참여해 서버 초기세팅부문에는 참가하지 못했으니 AWS 를 공부후 새포스팅으로 서버 초기 세팅을 따로 포스팅하겠다. 지금은 일단 배포자동화를 위해 추가로 세팅해야되는 부분을 포스팅하겠음을 밝힌다.
I AM Identity Center 에서 프론트 전용 계정을 추가해 준다.
권한세팅에서 사전정의된 poweruseraccess 라는 세팅을 고른다
기존에 사용하던 EC2 인스턴스와 방금 만들었던 I AM 계정을 연결한다.
sudo yum update
# 루비 설치(Amazon Linux 기준)
sudo yum install ruby -y
sudo gem update --system
# CodeDeploy Agent 설치
sudo yum install wget
wget https://aws-codedeploy-ap-northeast-2.s3.ap-northeast-2.amazonaws.com/latest/install
chmod +x ./install
sudo ./install auto > /tmp/logfile
# CodeDeploy Agent 설치 확인
sudo service codedeploy-agent status
EC2 인스턴스 에서 CodeDeploy 가 실행 될수 있도록 하는 패키지인 CodeDeployAgent 를 설치한다.
!!github action 에서는 EC2로 바로 접근을 하지 못한다!!
CodeDeploy 에서도 해당되는 과제를 수행할뿐 저장할 공간이 따로 존재하는것이아니라 저장공간이 따로 필요하다. S3 버킷 하나를 새로 지정하여 생성해주기로 하자
CodeDeploy 를 생성해주고 I AM 계정을 연결해준다
해당사진은 같이 프로젝트를 진행하는 친구의 백엔드 배포자동화 적용시의 사진이라 이름과 주소가다르다
진행하려는 프로젝트에맞춰서 이름과 주소를 설정하자
배포그룹을 생성하고 EC2 태그와 서비스 역활은 위에서 설정한것으로 진행한다.
해당사진은 백엔드 배포용으로 혼동이 없어야한다.
github actions 에 사용하기위한 acess key 와 secret key 를 발급받는다.
#3 github secret 세팅하기
프로젝트의 repo에들어가 settings - security - secrets and variables - actions 에들어가 new repository secret 을 클릭한다.
발급받은 키값으로 해당 시크릿을 작성해준다.
#4 appspec.yml 파일 작성
프로젝트 폴더안 해당경로에 appspec.yml 파일을 생성해준다.
version: 0.0
os: linux
# 배포 파일 설정
## source: 인스턴스에 복사할 디렉터리 경로
## destination: 인스턴스에서 파일이 복사되는 위치
## overwrite: 복사할 위치에 파일이 있는 경우 대체
files:
- source: /
destination: /home/ec2-user/apps/imad-web
overwrite: yes
# files 섹션에서 복사한 파일에 대한 권한 설정
## object: 권한이 지정되는 파일 또는 디렉터리
## pattern (optional): 매칭되는 패턴에만 권한 부여
## owner (optional): object 의 소유자
## group (optional): object 의 그룹 이름
permissions:
- object: /
pattern: "**"
owner: ec2-user
group: ec2-user
mode: 755
# 배포 이후에 실행할 일련의 라이프사이클
# 파일을 설치한 후 `AfterInstall` 에서 기존에 실행중이던 애플리케이션을 종료
# `ApplicationStart` 에서 새로운 애플리케이션을 실행
## location: hooks 에서 실행할 스크립트 위치
## timeout (optional): 스크립트 실행에 허용되는 최대 시간이며, 넘으면 배포 실패로 간주됨
## runas (optional): 스크립트를 실행하는 사용자
hooks:
AfterInstall:
- location: scripts/stop.sh
timeout: 60
runas: ec2-user
ApplicationStart:
- location: scripts/start.sh
timeout: 60
runas: ec2-user
여기서 이해해야하는부분은 EC2에 복사될 디렉토리경로 덮어쓰기 설정인 OVERWRITE
hooks 에있는 afterinstall 과 applicationstart 부분에서 실행되는 스크립트들의 확인이다.
간단하게 설치가 끝난후에 scripts 폴더안에 있는 stop.sh 가 실행되니 프로젝트 정지에 관한 스크립트가 들어가야할것이고
어플리케이션 스타트 부분에선 start.sh 스크립트가 작동되니 yarn start 와 같은 서버실행 명령어가 들어가야 할것이다.
#5 스크립트 작성
위에서 작성한 appspec.yml에서 지정한 스크립트위치에 스크립트.sh 파일을 생성해준다
stop.sh
cd /home/ec2-user/apps/imad-web
fuser -k 3000/tcp
echo 서버종료
원래는 프로세스킬 명령어를 사용하여 종료할려고하였지만 생각한대로 중지가 되질않아 내가 사용하는 포트인 3000 포트를 죽여 프로세스를 강제종료 하였다. 이후 보완이 필요할듯 하다.
start.sh
#!/usr/bin/env bash
PROJECT_ROOT="/home/ec2-user/apps/imad-web"
APP_LOG="$PROJECT_ROOT/application.log"
ERROR_LOG="$PROJECT_ROOT/error.log"
DEPLOY_LOG="$PROJECT_ROOT/deploy.log"
TIME_NOW=$(date +%c)
cd $PROJECT_ROOT
nohup yarn start > $APP_LOG 2> $ERROR_LOG &
echo "$TIME_NOW > yarn 실행 중" >> $DEPLOY_LOG
헤매고 헤매다 친구가 작성해준 start.sh 코드이다. 오류는 후술 하도록 하겠다.
배포 테스트
위의 과정을 진행한후 배포를 테스트 해보았다 지금 내 github actions 의 트리거는 master 브랜치의 커밋들을 release 브랜치에 pull request 를 날려 머지가 되었을때 작동된다.
github actions 가 끝이나면 codedeploy 의 배포가 시작된다
배포과정중 stop.sh 와 start.sh 도 순서에 따라 작동되어 프로세스 종료후 yarn start 명령어를 사용해 다시 서버가 실행될것이다.
배포후 자동으로 서버가 실행되어 사이트 접속이 잘되는것을 확인할수있다.
에러케이스
CodeDeploy timeout 에러
CodeDeploy의 배포 중 계속해서 timeout이 발생하는 문제가 있었다. timeout 제한 시간을 아무리 넉넉하게 줘도 같은 문제가 발생했다. 특이한 점으로는 배포 시작 후 잠시 후에는 서버가 정상적으로 동작했지만, timeout이 발생하면서 중단됐다.
nohup yarn start
문제는 start.sh 파일에서 yarn start 명령어를 실행했을 때 백그라운드에서 동작하지 않았기 때문이다. 위의 스크립트는 처음에 작성했던 start.sh의 일부다.
리눅스 시스템에서 nohup는 쉘 스크립트 파일을 데몬 형태로 실행시키는 명령어다. 터미널을 실행한 세션이 끊겨도 실행한 프로세스는 계속 동작하게 한다.
& 기호를 명령어 맨 뒤에 붙이면 Foregroud가 아닌 Background에서 실행된다. & 기호로 실행한 명령어는 세션이 종료되면 해당 프로그램도 함께 종료된다.
그렇기 때문에 리눅스 시스템에서 세션이 종료되도 프로그램이 종료되지 않고 백그라운드에서 계속 동작시키고 싶다면 nohup과 &를 조합해서 사용하면 된다.
nohup yarn start > $APP_LOG 2> $ERROR_LOG &
nohup과 &를 적용하면 위와 같은 코드가 된다. 서버 실행 시 표준출력과 표준에러 로그를 기록하고 싶어서 리다이렉션으로 빼주었다.
참고
'TEAM-PROJECT > IMAD-WEB' 카테고리의 다른 글
#어이없었던 에러 - 파일이름 대소문자 대소동 (0) | 2024.08.07 |
---|---|
작품검색의 로직변경! 실시간 반영 검색기능 구현하기! (0) | 2024.04.20 |
#3 소셜 로그인 구현 (1) | 2024.02.25 |
#1 팀 프로젝트 시작! 로그인/회원 조회 API 테스트 (REACT) (0) | 2023.11.30 |