CI & CD
CICD의 기본 개념은 1. 지속적인 통합 2. 지속적인 서비스 제공 3. 지속적인 배포
이다.
애플리케이션의 통합 및 테스트 단계에서부터 제공 및 배포에 이르는 애플리케이션의 라이프사이클 전체에 걸쳐 지속적인 자동화와 지속적인 모니터링을 제공
1. git push
2. github actions에서 remote repository의 변화를 감지하여 테스트 빛 빌드를 한다.
3. 아무 문제가 없다고 판단되면 deploy를 한다.
4. 이 모든 사이클은 개발자가 판단하고 작성한다.
github actions는 기본적으로 제공하는 template(시간 단축 및 원활한 개발을 위한)가 있지만, 나는 처음 사용하는 유저이기 때문에, 구글링을 통해 전체적인 흐름을 파악하면서 새롭게 작성하였다.
Build
name: Node.js CI
# 구독할 이벤트
on:
push:
branches: [main]
pull_request:
branches: [main]
# jobs 단위로 개별 서버(정확히는 Docker 컨테이너 단위라고 한다.)에서 작업이 수행된다.
# 각 작업은 병렬로 실행 된다고 하는데, needs: build와 같이 표시해서 기다릴 수도 있다.
jobs:
build:
# Ubuntu, Windows, MacOS를 지원한다.
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [14.x] # 템플릿 기본값: [10.x, 12.x, 14.x]
# uses 개념은 다른 사람이 작성한 내용을 실행하는 개념이다.
# actions/checkout: GitHub의 마지막 커밋으로 Checkout 한다.
# actions/setup-node: Node.js를 설치한다.
steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
# npm ci === npm install
- run: npm ci --prefix /yeomanda/yeomanda/server
# --if-present 옵션은 npm 스크립트가 존재할 때만 실행시키라는 의미이다.
# 만약 build 스크립트가 없는 경우, 오류 없이 지나간다.
- run: npm run build --if-present --prefix /yeomanda/yeomanda/server
- run: npm run test --prefix /yeomanda/yeomanda/server
Deploy
deploy:
needs: [build]
runs-on: ubuntu-latest
steps:
- name: connect with ssh
env:
PRIVATE_KEY: ${{ secrets.AWS_PRIVATE_KEY }}
HOST_NAME : ${{ secrets.HOST_NAME }}
USER_NAME : ${{ secrets.USER_NAME }}
run: |
echo "$PRIVATE_KEY" > private_key
chmod 600 private_key
ssh -o StrictHostKeyChecking=no -i private_key ${USER_NAME}@${HOST_NAME} '
pm2 stop www
pm2 delete www
pm2 kill
cd ./repo/yeomanda
git pull origin main
cd yeomanda/server
pm2 start ./bin/www
'
여기서 중요하다
구글링을 해보니 다들 다른 방법으로 env
를 선언하였는데, 저 방법이 가장 깔끔하고 확실하다.
github repository의 Settings 탭에 보면 왼쪽에 위와 같이 여러 카테고리가 있다. 그 중에 Secrets 카테고리
에서 변수를 사전에 설정해준다. 저 변수들은 한번 설정을 하면 read 할 수 없다. update를 원한다면 빈칸으로 나오기 때문에 보안상 안전하다고 할 수 있을 것 같다.
AWS_PRIVATE_KEY
| vi path_to_key_pair/[ssh_key].pem
at local
ec2 instance를 생성하면 ssh key를 제공한다. 그 pem파일을 저장하고 파일 저장한 위치에서 vi로 파일을 열어야 한다. 반드시..
나는 cat으로 열었다가 계속 ssh connection timed out
에러가 떴었다.
HOST_NAME
& USER_NAME
| ec2 instance를 생성하면 ssh 접속하기 위한 방법을 보면 ssh -i [.pem file] [USER_NAME]@[HOST_NAME]
인 것을 알 수 있다. 여기서 추출하면 된다.
stop_list=$(ps -ef | grep "node ./bin/www" | awk '{print $2}')
for stop_target in ${stop_list};do
kill -9 $stop_target
done
cd ./repo/yeomanda
git pull origin main
cd yeomanda/server
npm install
npm run start
nohup
리눅스에서 프로세스를 실행한 터미널의 세션 연결이 끊어지더라도 지속적으로 동작 할 수 있게 해주는 명령어.
기본적으로 터미널에서 세션 로그아웃(logout)이 발생하면 리눅스는 해당 터미널에서 실행한 프로세스들에게 HUP signal 이 전달하여 종료시키게 되는데,
이 HUP signal을 프로세스가 무시(ignore)하도록 하는 명령어라서 nohup.
해당 스크립트를 실행하고 나면 그 결과가 로그로 찍히는데 그 로그는 nohup.out
으로 같은 위치에 생성된다. 너무 많은 데이터가 찍히면 디스크 용량 과부하가 생길 수 있으므로 불필요한 데이터는 쌓이지 않게 하는 것도 하나의 방법이다.
nohup.out
파일 생성을 원하지 않는다면 nohup [프로세스] 1>/dev/null 2>&1 &
와 같은 방법으로 실행하면 된다.
1>/dev/null 은 표준 출력을 사용하지 않겠다는 의미이고, 2>&1 은 표준 에러를 표준 출력과 같게 만드는 명령어
출처: https://gracefulprograming.tistory.com/128 [Peter의 우아한 프로그래밍]
Background
ec2 instance를 사용하는 이유가 뭘까
자원은 제한적이고, 항시 pc를 켜놓고 있을 수 없기 때문에, 가상의 컴퓨터를 우리가 대여받는 것이다. 그렇다면, 인스턴스에 접속하여 서버를 돌리고 만약에 터미널을 닫거나, pc의 전원을 끈다면? 의미가 없다
결국 우리는 터미널 및 pc의 전원 여부와 상관없이 24시간 서버를 구동시켜야 하는데, 이때 흔히 말하는 백그라운드로 서버를 돌린다
라는 말을 한다.
👏
로컬에서 ssh로 인스턴스에 붙어서 서버를 흔히 돌리는 방법인 npm run start
로 돌리게 되면 이는 포그라운드로 돌리는 방법이다. 그렇기 때문에 터미널을 종료하게 되면 서버도 같이 끊긴다.
결국, 서버를 백그라운드로 돌려야 하는데 이때 사용하는 패키지 중에는
나는 forever
가 작동이 잘 되지 않아, pm2
로 했다.
$ npm install -g pm2@latest
$ pm2 start app.js // app.js ps를 실행
$ pm2 stop app.js // app.js ps를 중단
$ pm2 delete app.js // app.js ps를 삭제
$ pm2 kill // pm2 중단
https://github.com/jjmmll0727/yeomanda/blob/main/.github/workflows/nodejs.yml