← 전체 글로 돌아가기

Next.js

logrotate를 넣고도 Node 로그 파일이 줄지 않았을 때 확인한 신호

logrotate가 파일을 회전했는데 디스크 사용량이 줄지 않았던 상황에서 프로세스의 열린 파일을 확인한 설정 노트.

파일은 바뀌었는데 디스크는 비어 있지 않았다

VPS의 디스크 사용량 경고를 보고 logrotate를 설정했다. 다음 날 /var/log/myapp/app.log.1은 생겼고 새 app.log도 있었다. 그런데 df -h의 사용량은 거의 그대로였다.

처음에는 압축이 늦게 도는 줄 알았다. 실제 원인은 Node 프로세스가 이름이 바뀐 옛 파일 디스크립터를 계속 열고 있었던 것이다. 경로에서 파일이 없어져도 프로세스가 열고 있으면 블록은 해제되지 않는다.

열린 deleted 파일을 찾는 방법

lsof에서 deleted 표시를 찾으면 경로와 실제 사용량의 차이를 설명할 수 있다.

sudo lsof +L1
sudo du -sh /var/log/myapp
df -h /

내 서비스는 stdout을 systemd journal로 보내면서 별도로 파일에도 기록하고 있었다. 두 로그 경로를 모두 관리하지 못한 것도 원인이었다. 애플리케이션 로그는 가능한 한 한 곳으로 모으기로 했다.

선택지는 copytruncate보다 재시작 신호였다

간단히 쓸 수 있는 copytruncate는 원본을 복사한 뒤 잘라낸다. 아주 짧지만 로그가 빠질 가능성이 있어, 트래픽 있는 서비스의 기본값으로 삼고 싶지 않았다. 애플리케이션이 로그 파일을 다시 열 수 있다면 그 신호를 보내는 편이 낫다.

systemd에서 journal을 사용한다면 파일 rotation 자체를 줄이고 journal 크기를 제한하는 방법도 있다.

sudo journalctl --disk-usage
sudo journalctl --vacuum-time=14d
sudoedit /etc/systemd/journald.conf

설정에는 SystemMaxUse=처럼 서버 용량에 맞는 상한을 적고, 수정 후 journald를 재시작했다. 운영 중인 서비스의 로그를 무작정 지우기보다 보존 기간과 최대 용량을 먼저 정했다.

적용 뒤 확인한 목록

  1. logrotate -d로 실제 적용 규칙을 미리 본다.
  2. 회전 직후 lsof +L1에 열린 삭제 파일이 없는지 확인한다.
  3. dudf가 함께 줄었는지 본다.
  4. 장애 조사에 필요한 로그 기간을 팀 기준으로 정한다.

로그 관리는 용량 절약 작업이면서 동시에 관측 가능성을 남기는 작업이다. 파일 이름만 바뀌었는지, 프로세스가 새 파일을 쓰기 시작했는지까지 확인해야 끝난다.