본문 바로가기
서버연구 블로그 서버연구 블로그

서버 디스크가 100% 가득 찼을 때 발생하는 문제와 대응법

읽는 시간 약 16분

서버에서 디스크 사용률이 100%까지 올라가면 생각보다 문제가 크게 번집니다.

처음에는 로그 파일 하나가 커진 정도로 시작했는데, 어느 순간 애플리케이션이 파일을 쓰지 못하고 데이터베이스까지 오류를 내면서 서비스 전체가 불안정해지는 경우가 있습니다.

이때 가장 위험한 대응은 급한 마음에 큰 파일부터 무작정 삭제하는 것입니다.

운영 서버에서는 먼저 정말 공간 부족이 맞는지, 어느 파일시스템이 문제인지, 그리고 단순 용량 부족인지 파일시스템 장애인지를 구분해야 합니다.

이번 글에서는 실제 서버에서 디스크 사용률이 100%까지 올라갔을 때 확인하는 순서를 조금 더 현실적으로 정리해보겠습니다.

먼저 어느 디스크가 가득 찼는지 확인한다

가장 먼저 볼 명령어는 df입니다.

df -hT

예를 들어 결과가 다음과 같다고 해보겠습니다.

Filesystem     Type  Size  Used Avail Use% Mounted on
/dev/sda2      ext4   50G   48G     0 100% /
/dev/sdb1      xfs   200G  110G   90G  55% /data

이 상태라면 /data가 아니라 루트 파일시스템 /가 문제입니다.

여기서 중요한 점은 서버 전체 용량만 보는 것이 아니라 어느 마운트 포인트가 가득 찼는지 확인하는 것입니다.

/var, /home, 데이터베이스 영역을 별도 파티션으로 사용하는 서버라면 특정 영역 하나만 100%가 될 수도 있습니다.

100%라고 해서 물리적으로 모든 공간을 사용한 것은 아닐 수 있다

여기서 한 가지 잘 알려지지 않은 부분이 있습니다.

ext4 파일시스템에서는 일부 공간을 root 사용자용으로 예약해 둘 수 있습니다. 일반적으로 df의 Avail 값은 일반 사용자가 사용할 수 있는 공간 기준으로 계산되기 때문에 사용률이 100%로 표시돼도 root가 사용할 수 있는 예약 블록이 일부 남아 있을 수 있습니다.

현재 예약 블록을 확인하려면 파일시스템 장치를 먼저 확인한 뒤 다음처럼 볼 수 있습니다.

tune2fs -l /dev/sda2 | grep -i reserved

예를 들면 다음과 같은 값이 나올 수 있습니다.

Reserved block count:     655360
Reserved blocks uid:      0

이 공간은 시스템이 완전히 멈추는 것을 막기 위한 일종의 안전장치입니다.

따라서 Use% 100%라는 숫자 하나만 보고 “디스크 블록을 완전히 다 썼다”고 판단하기보다 파일시스템 종류와 예약 공간도 함께 볼 필요가 있습니다.

다만 예약 블록을 줄여서 공간을 확보하는 방법도 있지만, 운영 서버에서는 단순히 공간이 부족하다는 이유만으로 바로 변경하는 것은 권하지 않습니다. 특히 루트 파일시스템에서는 비상시에 필요한 여유 공간이 될 수 있기 때문입니다.

디스크가 가득 차면 실제로 어떤 문제가 생길까

가장 흔한 오류는 다음 메시지입니다.

No space left on device

하지만 실제 영향은 단순한 파일 생성 실패보다 훨씬 넓습니다.

Nginx가 access log나 error log를 쓰지 못할 수 있고, 애플리케이션에서 임시파일 생성이 실패할 수도 있습니다.

데이터베이스에서는 새로운 데이터를 쓰거나 임시 테이블을 만드는 작업이 실패할 수 있습니다. PHP 세션이나 캐시 파일을 디스크에 저장하는 환경이라면 로그인이나 세션 처리까지 문제가 생길 수 있습니다.

더 까다로운 건 장애가 발생한 순간부터 로그 자체가 기록되지 않을 수도 있다는 점입니다.

그래서 디스크가 100%가 된 서버에서는 로그에 아무것도 없다고 해서 문제가 없었다고 판단하면 안 됩니다.

오히려 공간이 부족해진 시점 이후의 로그가 남지 않았을 가능성도 생각해야 합니다.

어디에서 용량을 사용하고 있는지 좁혀간다

원인을 찾을 때는 디렉터리 크기를 위에서부터 내려가며 확인하는 방법이 안전합니다.

du -xhd1 / 2>/dev/null | sort -h

-x를 사용하는 이유는 다른 파일시스템까지 넘어가서 계산하지 않도록 하기 위해서입니다.

예를 들어 결과가 다음과 같다면

1.8G    /usr
4.2G    /home
31G     /var
48G     /

/var를 다시 확인합니다.

du -xhd1 /var 2>/dev/null | sort -h

이번에는 /var/log가 크게 나온다고 해보겠습니다.

2.1G    /var/lib
4.6G    /var/cache
22G     /var/log

그다음에는 /var/log 아래를 확인합니다.

du -xhd1 /var/log 2>/dev/null | sort -h

이런 식으로 범위를 좁혀가면 어느 서비스가 공간을 사용하고 있는지 상당히 빠르게 찾을 수 있습니다.

갑자기 커진 파일이 있는지 확인한다

특정 로그나 백업 파일 하나가 비정상적으로 커지는 경우도 많습니다.

예를 들어 /var에서 1GB가 넘는 파일을 찾으려면 다음처럼 확인할 수 있습니다.

find /var -xdev -type f -size +1G -ls 2>/dev/null

여기서 흔하게 발견되는 것은 애플리케이션 로그, 오래된 백업 파일, 데이터베이스 덤프, Docker 로그 등입니다.

중요한 것은 큰 파일을 발견한 뒤 바로 삭제하는 것이 아닙니다.

예를 들어 application.log가 20GB라면 질문은 두 가지입니다.

왜 이 로그가 20GB까지 커졌는지, 그리고 평소에는 왜 logrotate나 로그 제한 정책이 동작하지 않았는지입니다.

파일 하나를 지우는 것은 응급조치일 뿐이고, 원인을 고치지 않으면 며칠 뒤 다시 같은 장애가 발생합니다.

df는 100%인데 du에서는 파일이 안 보일 때

운영 서버에서 꽤 당황스러운 상황입니다.

df -h에서는 50GB 중 거의 전부를 사용했다고 나오는데, du로 디렉터리를 다 더해보면 30GB 정도밖에 나오지 않는 경우가 있습니다.

예를 들어

df 기준 사용량 : 49GB
du 기준 사용량 : 30GB
차이           : 약 19GB

이런 차이가 있다면 삭제된 파일을 프로세스가 계속 열고 있는 상황을 의심해야 합니다.

lsof +L1 또는 lsof | grep deleted

예를 들어 Nginx나 Java 프로세스가 수십 GB짜리 로그 파일을 열고 있는데 관리자가 그 파일을 삭제했다고 가정해보겠습니다.

디렉터리에서는 파일이 사라집니다.

하지만 해당 프로세스가 아직 파일 디스크립터를 열고 있으면 Linux는 그 공간을 즉시 반환하지 않습니다.

그래서 du에서는 보이지 않는데 df에서는 계속 공간을 사용하고 있는 것처럼 나타납니다.

이 경우에는 단순히 다른 파일을 계속 지우기보다 어떤 프로세스가 삭제된 파일을 잡고 있는지부터 확인해야 합니다.

용량이 남았는데도 No space left on device가 발생할 수 있다

또 하나 자주 놓치는 것이 inode입니다.

df -i

예를 들어 다음과 같은 결과가 나왔다고 해보겠습니다.

Filesystem      Inodes   IUsed  IFree IUse%
/dev/sda2      3276800 3276800      0  100%

디스크에 몇 GB가 남아 있어도 inode가 모두 소진되면 새로운 파일을 만들 수 없습니다.

이 문제는 작은 파일이 매우 많이 만들어지는 서버에서 자주 발생합니다.

세션 파일, 캐시 파일, 메일 큐, 임시파일 등이 수백만 개씩 생성되는 환경이라면 용량보다 inode가 먼저 고갈될 수도 있습니다.

그래서 디스크 문제에서는 df -h와 df -i를 같이 확인하는 편이 좋습니다.

파일시스템이 읽기 전용으로 바뀐 것은 아닌지 확인한다

이 부분은 단순 공간 부족과 반드시 구분해야 합니다.

스토리지나 파일시스템에 문제가 발생하면 Linux가 데이터 손상을 막기 위해 파일시스템을 Read-only 상태로 전환하는 경우가 있습니다.

그런데 사용자는 파일을 쓰지 못하니 처음에는 공간 부족으로 착각하기 쉽습니다.

현재 마운트 옵션은 다음과 같이 확인할 수 있습니다.

findmnt -no TARGET,OPTIONS /

커널 로그도 함께 확인합니다.

dmesg -T | grep -Ei "I/O error|EXT4-fs error|read-only|remount"

systemd journal을 사용하는 서버라면 다음도 확인합니다.

journalctl -k | grep -Ei "I/O error|EXT4-fs error|read-only|remount"

예를 들어 이런 메시지가 보인다면 상황이 완전히 달라집니다.

EXT4-fs error
Remounting filesystem read-only

이때는 로그 몇 개를 삭제해서 해결할 문제가 아닙니다.

디스크 장치, 스토리지, 파일시스템 상태까지 확인해야 합니다.

100% 공간 부족과 파일시스템 장애는 대응 방향 자체가 다릅니다.

로그를 정리하기 전에 원인부터 확인한다

/var/log가 커졌다고 로그 파일을 전부 삭제하는 경우가 있는데, 그렇게 하면 장애 원인을 확인할 중요한 기록까지 없어질 수 있습니다.

먼저 어떤 로그가 큰지 확인합니다.

du -sh /var/log/* 2>/dev/null | sort -h

systemd journal 사용량은 다음과 같이 확인할 수 있습니다.

journalctl --disk-usage

오래된 journal이 과도하게 쌓였다면 운영 정책을 확인한 뒤 정리할 수 있습니다.

journalctl --vacuum-time=7d

하지만 이 명령을 실행하기 전에 필요한 로그가 있는지부터 확인하는 것이 좋습니다.

애플리케이션 로그가 원인이라면 /etc/logrotate.conf와 /etc/logrotate.d/ 아래 설정도 같이 살펴봐야 합니다.

공간을 비우는 것보다 왜 로그 로테이션이 되지 않았는지 확인하는 게 재발 방지에는 더 중요합니다.

Docker를 사용한다면 /var/lib/docker도 확인한다

Docker 서버에서는 예상보다 /var/lib/docker가 빠르게 커지는 경우가 많습니다.

du -sh /var/lib/docker

Docker가 실제로 얼마나 사용하고 있는지는 다음 명령어로 확인할 수 있습니다.

docker system df

특히 컨테이너의 JSON 로그가 제한 없이 쌓이는 환경에서는 로그 하나가 수십 GB까지 커질 수 있습니다.

여기서 주의할 점이 있습니다.

공간이 부족하다고 /var/lib/docker/overlay2 아래 파일을 직접 찾아서 지우는 것은 피해야 합니다.

Docker가 관리하는 레이어 데이터를 직접 삭제하면 단순 용량 문제가 컨테이너 손상으로 바뀔 수 있습니다.

Docker 데이터는 Docker가 제공하는 명령과 로그 정책을 이용해서 관리하는 것이 안전합니다.

데이터베이스 디렉터리는 더 조심해야 한다

급한 상황에서는 큰 파일부터 눈에 들어옵니다.

그런데 /var/lib/mysql, PostgreSQL data directory 같은 곳에서 큰 파일을 발견했다고 해서 직접 삭제해서는 안 됩니다.

데이터 파일, WAL, redo log, binlog 등은 데이터베이스가 관리하는 구조입니다.

파일 하나를 직접 지우면 공간은 확보될지 몰라도 데이터베이스 자체가 기동하지 않는 더 큰 장애가 생길 수 있습니다.

DB 영역이 원인이라면 먼저 데이터베이스 내부에서 어떤 데이터가 증가했는지 확인하고 해당 DB가 제공하는 정상적인 정리 절차를 따라야 합니다.

운영 서버에서는 큰 파일과 지워도 되는 파일은 전혀 같은 의미가 아닙니다.

공간을 확보했다고 장애가 끝난 것은 아니다

디스크 공간을 확보한 뒤 df -h가 정상으로 돌아왔다고 바로 작업을 끝내면 안 됩니다.

디스크가 가득 차 있던 동안 일부 서비스는 이미 오류 상태에 들어갔을 수 있습니다.

먼저 실패한 서비스가 있는지 확인합니다.

systemctl --failed

주요 서비스의 상태도 확인합니다.

systemctl status nginx

데이터베이스가 있다면 해당 서비스 역시 확인합니다.

systemctl status mysql

서비스 로그에서도 write error나 restart 기록이 있었는지 살펴봅니다.

journalctl -u nginx --since "30 minutes ago"

공간이 부족했던 동안 DB가 쓰기 오류를 냈다면 디스크가 정상화된 뒤에도 애플리케이션 연결이 복구되지 않을 수 있습니다.

따라서 순서는

공간 확보 → 서비스 상태 확인 → 로그 확인 → 실제 요청 테스트

까지 이어져야 합니다.

현장에서 보는 대응 순서는 이렇다

디스크가 100%까지 찬 서버라면 저는 대체로 다음 흐름으로 봅니다.

  1. df -hT로 어느 파일시스템이 100%인지 확인한다.
  2. df -i로 inode 고갈 여부를 확인한다.
  3. du -x로 공간을 많이 사용하는 디렉터리를 좁힌다.
  4. 큰 로그, 백업, 임시파일, Docker 사용량을 확인한다.
  5. df와 du 차이가 크면 lsof +L1을 확인한다.
  6. dmesg와 journalctl -k로 파일시스템·I/O 오류를 확인한다.
  7. 삭제 가능한 데이터만 선별해서 최소한의 여유 공간을 확보한다.
  8. Nginx, WAS, DB 등 주요 서비스 상태를 다시 확인한다.
  9. 마지막으로 로그 폭증, 백업 정책, logrotate, Docker 로그 설정 같은 실제 원인을 수정한다.

이 순서를 지키면 단순히 “큰 파일 하나 찾아서 삭제”하는 것보다 사고를 줄일 수 있습니다.

100%가 되기 전에 잡는 것이 가장 좋다

운영 서버에서는 디스크가 100%가 된 뒤 대응하는 것보다 증가 속도를 미리 보는 게 중요합니다.

예를 들어 디스크 사용률이 현재 70%라면 숫자만 보면 여유가 있어 보입니다.

하지만 하루에 5%씩 증가하고 있다면 약 6일 뒤에는 문제가 생길 수 있습니다.

그래서 단순히

Disk usage > 90%

같은 알람 하나만 보는 것보다

현재 사용률
일일 증가량
남은 공간
예상 소진 시점

을 함께 보는 것이 훨씬 실용적입니다.

특히 백업 서버, 로그 서버, Docker 서버처럼 데이터가 계속 증가하는 시스템에서는 현재 수치보다 증가 속도가 더 중요한 경우가 많습니다.

마무리

서버 디스크 사용률이 100%까지 올라갔다면 단순히 공간을 확보하는 데만 집중해서는 안 됩니다.

먼저 어느 파일시스템이 문제인지 확인하고, inode 부족인지, 실제 파일 증가인지, 삭제된 파일을 프로세스가 붙잡고 있는지, 파일시스템 자체가 Read-only 상태가 된 것인지 구분해야 합니다.

그리고 공간을 확보한 뒤에는 서비스가 정상적으로 복구됐는지도 반드시 확인해야 합니다.

무엇보다 중요한 것은 큰 파일 하나를 지우는 것이 아닙니다.

왜 디스크가 100%까지 올라갔는지 찾아내고, 같은 방식으로 다시 차지 않도록 만드는 것이 실제 장애 대응의 마지막 단계입니다.

instone
함께 보면 좋은 글

댓글 0

첫 댓글을 남겨보세요.

error: Content is protected !!

광고 차단 알림

광고 클릭 제한을 초과하여 광고가 차단되었습니다.

단시간에 반복적인 광고 클릭은 시스템에 의해 감지되며, IP가 수집되어 사이트 관리자가 확인 가능합니다.