← 전체 글로 돌아가기

서버 운영

Linux inode가 먼저 바닥났을 때 디스크 용량만 보던 습관을 고친 순서

df -h가 여유 있다고 나오는데 파일 생성이 실패했던 VPS에서 inode와 작은 파일을 확인하고 정리한 과정입니다.

40GB가 남았는데 파일을 만들 수 없었다

새 배포가 임시 디렉터리에 파일을 쓰는 순간 No space left on device가 발생했다. 먼저 df -h를 실행했더니 루트 파티션 사용량은 68%였다. 디스크가 남았다는 숫자만 믿고 Docker 이미지부터 지우려던 것이 첫 번째 실수였다.

이번에는 블록 용량이 아니라 파일 개수(inode)가 부족한 상황이었다. 예전에 디버그 옵션을 켜 둔 작은 Node 작업이 요청마다 파일 하나를 남기고 있었고, 수십만 개의 파일이 한 디렉터리에 쌓였다.

용량과 inode를 분리해서 본 명령

df -h /
df -i /
sudo du -xhd1 /var | sort -h

df -h는 실제 저장 공간을, df -i는 생성 가능한 파일의 남은 개수를 보여준다. 두 번째 명령에서 IUse%가 100%에 가까우면 큰 로그 파일을 찾는 것보다 작은 파일 묶음을 먼저 의심해야 한다.

sudo find /var/tmp/my-worker -xdev -type f -printf '%T@ %p\n' \
  | sort -n | head -20
sudo find /var/tmp/my-worker -xdev -type f | wc -l

삭제 전에는 애플리케이션이 해당 경로를 현재 사용 중인지 확인했다. 실행 중인 프로세스가 파일을 열고 있으면 파일을 지워도 프로세스가 종료될 때까지 공간이 돌아오지 않을 수 있다.

sudo lsof +L1

재발 방지 기준

원인은 로그 로테이션 설정이 아니라 로그처럼 쓰던 임시 파일이었다. 파일을 생성하는 코드를 날짜별 한 파일로 바꾸고, 7일이 지난 작업 결과는 배치로 제거했다. systemd timer에서 삭제 작업이 실패해도 본 작업의 종료 상태를 가리지 않도록 별도 서비스로 분리했다.

체크리스트는 다음처럼 남겼다.

  • 장애 시 df -hdf -i를 항상 같이 실행한다
  • /var, /tmp, Docker 저장소를 파티션별로 나눠 확인한다
  • 수동 삭제 전 find 결과의 경로와 개수를 출력한다
  • 작은 파일을 만드는 작업에는 보존 기간과 최대 개수를 둔다
  • lsof +L1로 삭제됐지만 열린 파일을 확인한다

숫자 하나로 판단하지 않기

이번 일 이후 “디스크가 찼다”라는 문장을 바로 믿지 않는다. 블록이 부족한지 inode가 부족한지에 따라 조사 순서와 정리 방법이 완전히 달라진다. 운영 중에는 지우는 속도보다 무엇을 지우는지 확인하는 속도가 더 중요했다.