node 서버 세팅 이야기
회사 프로젝트를 하면서 간단한 노드서버를 운용할 기회를 얻었습니다. 노드서버를 세팅하면서 겪은 작은 이슈들을 기록겸 공유하고자 합니다.
개발환경
개발환경은 Node.
- 서버 프레임워크는
express
. 가장 유명하고 사용하기 쉬움. - 개발시에는 변경 즉시 node 서버를 재시작하도록 nodemon이라는 모듈을 사용.(개발에 최적화)
운영환경
운영환경에서 노드 서버운용을 위해 많이 쓰는건 아래 세가지가 있다.
StrongLoop, pm2, Foreverjs
선택할 때는 아래사항을 고려하였다.
- 안정적이어야 한다.
- 운영 이슈에 대응할 만한 옵션이 있다.
- 개발자가 계속하여 관리를 하고 있다.
- 문서화가 잘되어 있어야 한다.
StrongLoop에서 http://strong-pm.io/compare/ 3가지를 비교해 놓은 것이 있는데 언뜻보면 strongLoop가 나아보이기도 하지만 사이트 곳곳의 링크가 깨져있고 관리에서 손을 놓은지 오래되어보였다(운영 커밋이 몇 년전). 또한 도커지원같은 여러 옵션들은 이제는 pm2도 지원을 해주고 있다.
foreverjs는 워낙 유명하지만 운영에 적용하기에는 옵션들이 너무 간단하고 기능도 없다. 또한 최근 커밋이 몇년전이다.
pm2는
- 문서화가 잘되어있다.
- 또한 클러스트를 지원해준다.
- 옵션들이 쓰기 쉽다. 옵션들은 커맨드라인과 json파일 또 코드안에도 넣을 수 있다.
그래서 pm2를 선택하게 되었다.
간단히 살펴보면,
pm2 사용법
설치
npm install pm2 -g
https://nhnent.dooray.com/share/posts/GsuGbRAKRqSKX2OQAawbiA
앱실행
앱을 실행하면 pm2에 등록이 되고 app Id로 프로세스를 관리 하게 된다.
pm2 start dooray.js
pm2 stop all # stop all processes
pm2 restart all # Restart all processes
pm2 stop 0 # Stop specific process id
pm2 restart 0
현재 구동되고 있는 앱
pm2 list
메모리 제한
app이 사용하는 메모리가 일정 지점을 넘을 시 자동으로 재실행되도록 할 수 있다.
pm2 start dooray --max-memory-restart 20M
logging하기
pm2에서는 자동으로 로그하기가 쉽다. 기본 설정으로 로그는 /home/user/.pm2/logs
안에 error와 out이라는 파일명으로 저장이 된다.
log 보기
pm2 logs [app 명]
app명을 쓰지 않으면 전체 pm2 app의 로그가 나오고 app명에는 정규식이 들어 갈 수도 있다.
비우기
pm2 flush
format
시작할 때 log format 을 지정하면 해당 포맷으로 로그가 쌓인다. 실서비스에서는 아래와 같이 하도록 하자 .
pm2 start dooray --merge-logs --log-date-format="YYYY-MM-DD HH:mm "
log output 예시
/home1/irteam/.pm2/logs/dooray-error.log last 15 lines:
/home1/irteam/.pm2/logs/dooray-out.log last 15 lines:
0|dooray | 2018-03-30 14:24: Listening on port 10150!
monitor
pm2의 모니터링은 ui가 괜찮았다. 아래와 같은 명령어로 실행하면 된다. 프로세스별, 또는 합쳐서 로그를 보거나 관리할 수 있어서 한서버에 여러 노드 모듈을 쓸 때 유용하다.
pm2 monit
keymetrics
pm2에서 지원하는 monitor 유료모델도 있다. 원격에서 조회가 가능하다.
- key만 link시키면 간단히 연동이 가능하다
- 유료가 아니라면 볼 수 있는건 이정도
https://github.com/sindresorhus/awesome-nodejs
배포과정
pm2를 이용하여 데브에서 배포는 이렇게 했다.
- 깃에 마스터로 새 커밋이 올라오면 젠킨스에서 탐지
- ssh로 붙어서 데브서버에서 현재 pm2로 app 중지
- 젠킨스에서 데브서버에 scp로 프로젝트 폴더 전체를 옮겨서 덮어 씀
- 데브서버에서 npm 모듈을 install
- 데브서버에서 pm2로 app 실행
자바의 일반적인 빌드.배포과정이랑 달라서 당황스러웠다. 기존 자바 WAS에는 노드서버가 아니라서 젠킨스 서버에서 쓰는 노드모듈만 묶어서 배포하였는데 노드 서버는 노드모듈을 직접쓰니 그렇게 할 수 도 없었다.
또 상용서버에서 npm install이 잘되라는 보장이 없었다. 내가 사용한 서버만 해도 nmap으로 조회해보면
$ nmap github.com -p http,git
80/tcp open http
8008/tcp filtered http
9418/tcp filtered git
보이듯 git 프로토콜이 막혀있다. 그래서 git의 기본 프로토콜을 https로 바꿔줘야 한다.
git config --global url."https://".insteadOf git://
지인 이야기로는 파이썬서버도 비슷하게 관리한다고 해서 일단은 넘어갔다. 하지만 결국 바꾸게 되었다.
pkg의 사용
폴더를 통채로 옮기거나 git으로 받는건 결국 문제가 있다.
- 각 서버에서 git으로 받거나 npm으로 모듈을 받는 과정을 모든서버에서 해줘야 한다.
- 폴더를 통채로 옮기면 배포시스템에서 바이너리 관리가 안된다. 그말은 롤백이 어렵다는 뜻이다.
- 모듈을 받을 때 네트워크 환경에 따라서 배포과정에 장애가 날 수 있다.
- 모듈 업데이트 과정이 매끄럽지 못하다. 버전이 같은데 내용이 바뀌면 서버마다 들어가서 모듈을 직접 삭제해 줘야한다.
그래서 war 파일같이 실행파일 하나로 떨구는 pkg라는 모듈을 사용하였다.(몇 가지가 더 있는데 pkg가 사용법이 간단하고 star가 가장 많다.)
전역으로 설치를 한 후
$npm install -g pkg
package.json에 아래와 같이 pkg옵션을 설정한다. bin은 시작파일의 경로이다. asset, script로 같이 묶을 리소스를 지정할 수 있다.
"bin": "index.js",
"pkg": {
"targets": [
"node8"
],
"assets": [
"server/theme/**/*"
]
},
아래 명령어로 터미널에 실행 하면 package.json의 name으로 excutable한 바이너리 파일을 생성해준다.
$pkg .
시스템환경등에 따라 여러 실행 옵션들이 있다.
이렇게 적용하고 나니 빌드과정이 무척 간단해졌다.
- 젠킨스에서 탐지 후 젠킨스 서버에서 pkg로 빌드
- 바이너리를 배포서버에 전송
- pm2 재실행 (다행히 pm2는 바이너리 파일을 지원해준다)
개발환경과 운용환경에서 다른점이라면 아래정도로 요약 할 수 있다.
- pm2로 프로세스 관리
- pkg로 실행파일 관리
참고) 노드 모듈들