LabHub

LFCS — 리눅스 재단 시스템 관리자 · 스토리지 관리 · 이론

용량이 남았는데 파일을 못 만드는 이유

LabHub 에서 이어서 보기

한 줄 요약

스토리지는 블록 장치 → 파티션 → 파일시스템 → 마운트 네 계층으로 쌓인다. 장애가 났을 때 가장 먼저 할 일은 증상이 어느 계층의 것인지 정하는 것이고, 그 판단만으로 후보가 4분의 1로 줄어든다.

왜 이게 필요했나

df -h 는 35GB 가 남았다고 하는데 touch 하나가 No space left on device 로 실패한다. 여기서 "모니터링이 이상하다" 로 결론 내리기 쉽지만, df 는 정직하게 블록 사용량을 보고했을 뿐이다. 이 오류는 errno 28 이고, 커널이 이 값을 돌려주는 경로는 블록 부족 말고도 여러 개다.

가장 흔한 것이 inode 고갈이다. 파일 하나는 데이터 블록과 별개로 메타데이터를 담는 inode 를 하나 쓴다. ext4 는 inode 개수가 파일시스템 생성 시점에 고정되므로, 아주 작은 파일이 대량으로 쌓이면 블록이 남아도 inode 가 먼저 바닥난다. 확인은 df -i 이고, IUse% 가 100 이면 답이 나온 것이다. 늘릴 수 없으므로 파일을 지우거나 파일시스템을 다시 만드는 수밖에 없다. 세션 파일, 밀린 메일 큐, 정리되지 않는 임시 파일이 단골 원인이다.

그다음 후보들도 알아 둘 값어치가 있다. 삭제됐지만 열려 있는 파일 — 디렉터리 엔트리는 사라졌으니 du 는 못 찾지만 프로세스가 열고 있으니 블록이 반환되지 않는다. dfdu 가 어긋나는 가장 흔한 이유다. 예약 블록 — ext 계열은 기본적으로 일정 비율을 root 전용으로 남겨 둔다. 마운트 가림 — 파일이 있는 디렉터리 위에 다른 파일시스템을 마운트하면 아래 파일은 보이지 않으면서 공간은 계속 차지한다.

그리고 진단 전에 30초를 쓸 가치가 있는 확인이 하나 있다. 정말 그 파일시스템에 쓰고 있는가. df -h 를 인자 없이 실행해 목록을 눈으로 훑고 짐작하는 것이 가장 흔한 실수다. findmnt -T <경로> 로 그 경로가 실제로 어느 장치에 속하는지 직접 물어보면 / 가 아니라 별도 파티션인 /var 가 꽉 찬 상황을 바로 잡아낸다. /tmp 가 tmpfs 인 환경도 흔한데, 여기가 차면 디스크와 무관하게 같은 오류가 나면서 그만큼의 물리 메모리를 잡아먹고 있다.

어떻게 동작하나

/etc/fstab 의 여섯 필드.

| 번호 | 필드 | 설명 |
| --- | --- | --- |
| 1 | 장치 | UUID, LABEL, 또는 장치 경로 |
| 2 | 마운트 지점 | 붙일 디렉터리 |
| 3 | 파일시스템 종류 | ext4, xfs, nfs 등 |
| 4 | 옵션 | defaults, noatime, nofail 등 |
| 5 | dump | 백업 도구용. 보통 0 |
| 6 | fsck 순서 | 루트는 1, 나머지는 2, 검사 안 함은 0 |

UUID 를 쓰는 이유는 장치 이름이 안정적이지 않기 때문이다. /dev/sdb 는 커널이 장치를 발견한 순서에 따라 붙는 이름이라, 디스크를 하나 추가하거나 컨트롤러가 바뀌면 다른 디스크가 그 이름을 가져갈 수 있다. 그러면 fstab 은 문법적으로 멀쩡한 채 엉뚱한 장치를 마운트한다. UUID 는 파일시스템에 새겨져 있어 장치가 어디에 꽂히든 따라다닌다.

옵션 중 nofail 은 특히 실무적이다. 이것이 없으면 그 장치가 없을 때 부팅이 긴급 모드로 떨어진다. 외장 디스크나 네트워크 스토리지 항목에는 대개 붙인다.

LVM 이 푸는 문제. 파티션은 디스크 위에 고정된 경계를 긋는 방식이라, 나중에 늘리려면 뒤쪽에 인접한 빈 공간이 있어야 한다. LVM 은 물리 볼륨(PV)들을 볼륨 그룹(VG)이라는 풀에 모으고, 그 풀에서 논리 볼륨(LV)을 잘라 쓴다. 그래서 여러 디스크에 걸쳐 하나의 볼륨을 만들 수 있고, 디스크를 추가해 풀을 키운 뒤 볼륨을 온라인으로 늘릴 수 있다. 스냅샷도 이 계층에서 나온다.

RAID 레벨은 요구사항이 고른다. RAID 0 은 성능과 용량만 주고 이중화가 전혀 없다(디스크 하나가 죽으면 전부 잃는다). RAID 1 은 그대로 복제라 안전하지만 용량이 절반이다. RAID 5 는 패리티 하나로 한 장 고장을 견디며 용량 효율이 좋지만, 재구축 중에 나머지 디스크를 전부 읽어야 해서 그때 두 번째 고장이 나면 끝이다. 디스크가 커질수록 재구축 시간이 길어져 이 위험이 커진다. RAID 10 은 미러를 스트라이프해 쓰기 성능과 재구축 안전성을 얻는 대신 용량 절반을 낸다. 그리고 어떤 RAID 도 백업이 아니다. RAID 는 하드웨어 고장을 견디는 장치이지 실수로 지운 파일을 되돌려 주지 않는다.

현장에서 만나는 모습

저자가 겪은 사례에서 Avail 은 35GB 였는데 0바이트 파일 하나를 만들 수 없었다. 순서대로 확인하면 5분이면 원인이 나온다 — 경로가 속한 파일시스템을 확정하고, df -i 로 inode 를 보고, 삭제된 열린 파일을 찾고, 예약 블록과 마운트 가림을 확인한다. 이 순서를 외워 두는 것이 값어치가 크다. 같은 오류 문구가 여러 원인에서 나오기 때문에, 문구만 보고 추측하면 매번 다른 길로 샌다.

dfdu 가 어긋날 때의 첫 번째 후보도 늘 같다. 삭제됐지만 프로세스가 붙잡고 있는 파일이다. 가장 안전한 해제 방법은 서비스를 재시작하는 것이 아니라 로그 파일을 다시 열게 하는 신호를 보내는 것이고, 그다음 수단이 디스크립터를 직접 비우는 것이다. 순서를 지키는 이유는 재시작이 그 순간의 진단 정보를 전부 날려 버리기 때문이다.

다음 퀴즈에서 확인할 것

이 실습 환경은 mount, umount, mkfs, fdisk, parted, pvcreate, swapon 같은 명령이 전부 막혀 있다. 커널 capability 가 제거된 컨테이너라 파일시스템을 실제로 만들거나 붙일 수 없기 때문이다. 그래서 이 모듈은 개념과 판단 기준에 집중한다. 솔직히 말하면 스토리지는 LFCS 에서 손으로 해 봐야 늘고, 그 부분은 가상 머신이나 루프백 장치를 쓸 수 있는 환경에서 따로 연습하기를 권한다. 여기서는 계층 구조, dfdu 의 차이, inode 고갈의 진단 순서, fstab 각 필드의 의미와 UUID 의 이유, LVM 과 RAID 의 선택 기준을 확실히 잡아 두고 퀴즈로 점검한다.