LabHub

스토리지와 마운트 · 블록 장치와 파일시스템 · 이론

장치, 파일시스템, 마운트 세 층

LabHub 에서 이어서 보기

한 줄 요약

블록 장치는 바이트의 배열이고, 파일시스템은 그 배열 위에 얹은 자료구조이며, 마운트는 그 자료구조를 디렉터리 트리에 붙이는 행위다. 이 셋은 완전히 별개다.

왜 이게 필요했나

"디스크가 꽉 찼어요" 라는 한 문장에 최소 네 가지 다른 문제가 섞여 있다.

1. 블록이 정말 다 찼다 (df -h 가 100%)
2. inode 가 먼저 떨어졌다 (df -i 가 100%, 블록은 여유)
3. 지운 파일을 누가 열고 있어 공간이 반환되지 않는다 (dfdu 불일치)
4. 애초에 그 경로가 예상한 파일시스템이 아니다 (마운트가 안 됐다)

넷은 원인도 대응도 전혀 다르다. 그런데 증상은 똑같이 No space left on device 다. 세 층을 구분해야 이 넷이 갈린다.

어떻게 동작하나

층 1 — 블록 장치

/dev/sda, /dev/nvme0n1p1, 루프 장치 /dev/loop0 같은 것들이다. 커널에게는 그냥 읽고 쓸 수 있는 바이트 배열이다.

여기서 중요한 사실 하나. 파일시스템은 블록 장치가 아니라 평범한 파일 위에도 만들 수 있다. mkfs.ext4 는 대상이 장치인지 파일인지 신경 쓰지 않는다. 그저 그 대상의 처음부터 정해진 구조를 써 넣을 뿐이다. 이 성질 덕분에 특권 없이도 파일시스템 내부를 학습할 수 있다.

truncate -s 256M /root/disk/lab.img     # 희소 파일 — 실제 점유는 0mkfs.ext4 -F -L LABHUB /root/disk/lab.imgblkid /root/disk/lab.imgdumpe2fs -h /root/disk/lab.imgdebugfs -R 'ls -l /' /root/disk/lab.img

truncate 로 만든 파일은 희소 파일(sparse) 이다. 논리 크기는 256MB 인데 실제 디스크 점유는 거의 0 이다. du --apparent-sizedu 의 값이 다른 것으로 확인할 수 있다.

층 2 — 파일시스템

mkfs 가 만드는 것은 슈퍼블록 + inode 테이블 + 블록 그룹이다. dumpe2fs -h 로 슈퍼블록을 읽으면 이런 값들이 나온다.

| 항목 | 의미 | 왜 중요한가 |
| --- | --- | --- |
| Block size | 블록 하나의 크기(보통 4096) | 작은 파일이 많으면 내부 단편화 |
| Inode count | 포맷 시점에 고정된 inode 개수 | ext4 는 나중에 못 늘린다 |
| Reserved block count | root 전용 예약 블록 | 기본 5%, 대용량 데이터 디스크에서는 낭비 |
| Filesystem UUID | 이 파일시스템의 고유 ID | fstab 에서 장치명 대신 쓴다 |

inode 는 포맷할 때 개수가 정해지고 나중에 늘릴 수 없다. 그래서 세션 파일이나 메일 큐가 작은 파일 수백만 개를 만들면 블록은 남아도 inode 가 먼저 떨어진다. 용량 알람은 df -hdf -i 둘 다 걸어야 하는 이유다.

예약 블록도 실무 포인트다. 기본 5% 는 루트 파일시스템에서는 합리적이지만(root 가 로그를 쓸 여유를 남긴다) 8TB 데이터 디스크에서는 400GB 를 놀리는 셈이다. tune2fs -m 1 로 낮춘다.

층 3 — 마운트

마운트는 파일시스템을 디렉터리 트리의 한 지점에 붙인다. 여기서 두 가지를 구분해야 한다.

현장에서 만나는 모습

마운트 실패로 루트가 차는 사고. /var/lib/postgresql 에 별도 디스크를 마운트하도록 설계했는데 fstab 항목이 틀려 마운트가 안 됐다. 데이터베이스는 아무 불평 없이 루트 파일시스템에 데이터를 쓰기 시작한다. 며칠 뒤 루트가 100% 가 되고 시스템 전체가 멈춘다. 그래서 마운트 지점 디렉터리에 .not-mounted 같은 표식 파일을 두고 애플리케이션이 그걸 확인하게 하는 팀도 있다.

다음 실습에서 할 것

파일 위에 진짜 ext4 를 만들어 UUID 를 뽑고, 슈퍼블록을 읽고, tune2fs 로 예약 비율을 바꾸고, debugfs 로 안을 들여다본다. 마지막에는 그 이미지를 마운트하는 fstab 줄을 UUID 로 작성한다.