[Linux] 디스크와 스토리지 관리

2026. 5. 22. 22:24·Linux
SMALL
시나리오

새벽 2시, 슬랙 알림이 울립니다. "No space left on device — 서비스 쓰기 실패." df -h를 치니 루트 파티션이 100%입니다. du -sh /*로 큰 디렉토리를 찾아가다가 /var/log에 30GB짜리 로그가 쌓여 있습니다. 지웠는데 df -h가 여전히 100%. 알고 보니 삭제한 파일을 nginx 프로세스가 계속 열고 있어서 공간이 실제로 반환되지 않은 것이었습니다. lsof | grep deleted를 치고서야 원인을 찾았습니다.

df → du → lsof, 이 세 명령의 순서가 디스크 장애 진단의 기본입니다.

디스크와 스토리지 관리

이번 챕터에서 배울 것
1물리 디스크 → 파티션 → 파일시스템 → 마운트 포인트의 계층 구조를 설명할 수 있다
2df, du, lsblk, lsof로 디스크 사용량을 진단하고 용량 문제를 해결할 수 있다
3fdisk와 mkfs로 파티션을 생성하고 파일시스템을 포맷할 수 있다
4/etc/fstab으로 마운트를 영구 설정하고 부팅 실패를 예방할 수 있다
5inode 고갈과 열린 파일 공간 미반환 문제를 진단하고 해결할 수 있다
실습 환경 준비
블록 디바이스 목록 확인
lsblk -f
파일시스템 사용량 전체 확인
df -hT
I/O 모니터링 도구 설치 (Ubuntu)
sudo apt install -y sysstat iotop
실습은 가상 머신 또는 추가 디스크 환경을 권장
파티션 조작은 실제 데이터가 없는 별도 디스크에서 수행하세요
개념
Linux 스토리지 계층 구조
Linux 스토리지 스택 계층 — 애플리케이션에서 물리 디스크까지

서버에 새 디스크를 붙였는데 ls /dev에는 보이는데 파일로 저장할 수가 없고, df -h에도 나타나지 않습니다. 또는 df -h로 보면 공간이 충분한데 파일 쓰기에서 "No space left on device" 에러가 나기도 합니다. 이런 상황에서 원인을 찾으려면 물리 디스크가 파티션, 파일시스템, 마운트 포인트를 거쳐 경로가 되기까지의 계층 구조를 알아야 합니다. 어느 단계가 빠졌는지 파악하면 원인을 빠르게 좁힐 수 있습니다.

리눅스에서 디스크는 추상화 계층을 거쳐 사용자에게 노출됩니다. 물리 하드웨어부터 실제 파일 경로까지 4단계 구조로 이해하면 장애 원인을 빠르게 추적할 수 있습니다.

Linux 스토리지 계층 구조와 디스크 진단 워크플로우
물리 디스크 (Physical Disk)
    └── 파티션 (Partition)       ← 디스크를 논리적으로 분할
            └── 파일시스템 (Filesystem)  ← 데이터 저장 구조
                    └── 마운트 포인트 (Mount Point)  ← 접근 경로

장치 파일 명명 규칙

리눅스는 모든 하드웨어를 /dev/ 디렉토리 아래 파일로 표현합니다.

장치 경로 설명
/dev/sda 첫 번째 SATA/SAS 디스크
/dev/sdb 두 번째 SATA/SAS 디스크
/dev/sda1 /dev/sda의 첫 번째 파티션
/dev/sda2 /dev/sda의 두 번째 파티션
/dev/nvme0n1 첫 번째 NVMe SSD
/dev/nvme0n1p1 /dev/nvme0n1의 첫 번째 파티션
/dev/vda 가상 머신(KVM/QEMU)의 첫 번째 가상 디스크

명명 패턴 읽는 법: nvme0n1p2에서 0은 컨트롤러 번호, n1은 네임스페이스(디스크) 번호, p2는 파티션 번호입니다.

파티션 테이블: MBR vs GPT

디스크를 파티션으로 나누려면 파티션 테이블 형식을 먼저 선택해야 합니다.

항목 MBR (Master Boot Record) GPT (GUID Partition Table)
최대 디스크 크기 2TB 9.4ZB (사실상 무제한)
최대 파티션 수 4개 (주 파티션) 128개
부트 지원 BIOS UEFI (BIOS도 가능)
데이터 이중화 없음 헤더와 파티션 테이블 이중 저장
현재 권장 여부 레거시 시스템 신규 시스템 표준

2TB 이상 디스크나 신규 서버에는 반드시 GPT를 사용하세요. 클라우드 환경(AWS, GCP, Azure)의 부팅 볼륨은 대부분 GPT로 포맷되어 있습니다.

— — —

개념
파일시스템 종류와 특징
Linux 파일시스템 종류 비교 — ext4 · xfs · tmpfs · btrfs

새 디스크를 추가하거나 파티션을 포맷할 때 mkfs.ext4를 쓸지 mkfs.xfs를 쓸지 선택해야 합니다. 대부분의 경우 Ubuntu는 ext4를, RHEL/CentOS는 XFS를 기본으로 씁니다. 파일시스템 종류가 다르면 복구 방법도, 대용량 파일 처리 특성도 달라지기 때문에 나중에 바꾸려면 데이터를 옮기고 포맷을 다시 해야 합니다. 처음 선택이 중요하고, 어떤 상황에 어떤 파일시스템이 맞는지를 알아야 합니다.

파티션 위에 올라가는 파일시스템은 데이터를 어떻게 저장하고 복구할지를 결정합니다. 리눅스 환경에서 주로 만나게 될 세 가지 파일시스템을 비교합니다.

항목 ext4 XFS Btrfs
안정성 매우 높음 (오랜 검증) 높음 중간 (계속 개선 중)
최대 파일 크기 16TB 8EB 16EB
최대 파일시스템 크기 1EB 8EB 16EB
저널링 지원 지원 (메타데이터) 지원 (Copy-on-Write)
스냅샷 미지원 미지원 (LVM 필요) 네이티브 지원
온라인 축소 불가 불가 가능
주요 사용 사례 범용, 부팅 볼륨 대용량 파일, 데이터베이스 백업 서버, NAS
대표 배포판 Ubuntu, Debian RHEL, Rocky Linux openSUSE

실무 선택 기준

  • 일반 서버 루트 볼륨: ext4 (안정성 우선, 검증된 복구 도구)
  • 데이터베이스 서버: XFS (대용량 순차 I/O 성능 우수)
  • 백업/스냅샷 서버: Btrfs (스냅샷 기능 활용)
  • 클라우드 AWS EC2: 기본값은 ext4, Amazon Linux 2023은 XFS

inode란? 파일시스템은 각 파일에 대한 메타데이터(크기, 권한, 타임스탬프, 위치 등)를 inode에 저장합니다. inode 수는 파일시스템 생성 시 고정되며, inode를 모두 소진하면 디스크 공간이 남아 있어도 파일을 생성할 수 없습니다.

— — —

실습: 디스크 상태 진단부터 I/O 분석까지

실습 전 디렉토리와 예제 파일을 먼저 준비합니다.

bash# 실습 디렉토리 준비
mkdir -p /tmp/linux/part3/exam_1 && cd /tmp/linux/part3/exam_1

# 디스크 실습용 테스트 파일 생성
dd if=/dev/urandom of=/tmp/linux/part3/exam_1/testfile_100m.bin bs=1M count=100 2>/dev/null
echo "테스트 파일 생성 완료: $(du -sh /tmp/linux/part3/exam_1/testfile_100m.bin)"

이제 실습을 진행합니다.

Step 1. 마운트된 파일시스템 사용량 확인

df(disk free)는 현재 마운트된 모든 파일시스템의 용량 정보를 보여줍니다. -h는 사람이 읽기 좋은 단위(GB, MB), -T는 파일시스템 타입을 추가로 출력합니다.

bashdf -hT
Filesystem     Type      Size  Used Avail Use% Mounted on
/dev/nvme0n1p1 ext4       30G   14G   15G  49% /
tmpfs          tmpfs     3.9G     0  3.9G   0% /dev/shm
/dev/nvme0n1p3 ext4      100G   67G   28G  71% /var
/dev/sdb1      xfs       500G  312G  188G  63% /data
/dev/sdc1      xfs       2.0T  1.1T  900G  56% /backup
tmpfs          tmpfs     3.9G  1.2M  3.9G   1% /run

각 컬럼 읽는 법:

  • Filesystem: 장치 파일 경로
  • Type: 파일시스템 종류
  • Size: 전체 용량
  • Used: 사용 중인 용량
  • Avail: 실제 사용 가능한 용량 (루트 예약 공간 제외)
  • Use%: 사용률 — 85% 이상이면 즉시 확인 필요
  • Mounted on: 마운트 포인트
bash# 특정 디렉토리가 어떤 파티션에 속하는지 확인
df -hT /var/log

# tmpfs(메모리 기반 임시 파일시스템) 제외
df -hT --exclude-type=tmpfs

# 사용률 내림차순 정렬 (경보 대응 시 유용)
df -h | sort -rk5 | head -10
bashdf -hT

— — —

Step 2. 디렉토리별 용량 분석

du(disk usage)는 파일과 디렉토리의 실제 점유 용량을 계산합니다. df로 어떤 파티션이 가득 찼는지 파악했다면, du로 주범을 찾습니다.

bashdu -sh /var/log/* | sort -rh | head -20
4.2G    /var/log/journal
1.8G    /var/log/nginx
956M    /var/log/postgresql
312M    /var/log/syslog
189M    /var/log/auth.log
87M     /var/log/kern.log
45M     /var/log/apt
12M     /var/log/dpkg.log
8.4M    /var/log/faillog
2.1M    /var/log/btmp

옵션 설명:

  • -s: 각 항목의 합계만 출력 (하위 디렉토리 개별 표시 안 함)
  • -h: 사람이 읽기 좋은 단위
  • sort -rh: 용량 기준 내림차순 정렬 (-h는 K/M/G 단위 인식)
  • head -20: 상위 20개만 출력
bash# 현재 디렉토리 기준으로 하위 1단계만 분석
du -sh /* 2>/dev/null | sort -rh | head -15

# 특정 크기 이상 파일 찾기 (100MB 이상)
find /var -type f -size +100M -exec ls -lh {} \; 2>/dev/null

# 최근 24시간 내 수정된 대용량 파일 추적
find / -type f -size +50M -mtime -1 2>/dev/null | xargs ls -lh

주의: du -sh /*는 전체 파일시스템을 탐색하므로 대형 서버에서는 시간이 걸릴 수 있습니다. I/O 부하가 높은 운영 서버에서는 ionice -c3 du -sh /var/* 처럼 I/O 우선순위를 낮춰서 실행하세요.

bashdu -sh /var/log/* | sort -rh | head -20

— — —

Step 3. 블록 디바이스 트리 확인

lsblk는 시스템의 모든 블록 디바이스(디스크, 파티션, LVM 볼륨 등)를 트리 형태로 보여줍니다. -f 옵션을 추가하면 파일시스템 타입과 UUID, 마운트 포인트까지 함께 출력됩니다.

bashlsblk -f
NAME        FSTYPE FSVER LABEL UUID                                 FSAVAIL FSUSE% MOUNTPOINTS
nvme0n1
├─nvme0n1p1 vfat   FAT32       4E21-3A9F                             511M     1% /boot/efi
├─nvme0n1p2 ext4   1.0         a3f2c1d8-7b4e-4f91-9c2a-1e8f6b3d5a7c  884M    11% /boot
└─nvme0n1p3 ext4   1.0         b7d4e2f9-3c1a-4b82-8d5f-9e7a2c4b6f1e   15G    47% /
sdb
└─sdb1      xfs          data   f1a2b3c4-d5e6-7f8a-9b0c-1d2e3f4a5b6c  188G    63% /data
sdc
└─sdc1      xfs          backup 9a8b7c6d-5e4f-3a2b-1c0d-9e8f7a6b5c4d  900G    55% /backup

트리 구조 읽는 법:

  • 최상위 항목(nvme0n1, sdb)이 물리 디스크
  • ├─, └─ 하위 항목이 파티션
  • UUID는 장치 이름 대신 /etc/fstab에서 안정적인 식별자로 사용
bash# 디스크 크기 정보도 함께 출력
lsblk -f -o NAME,FSTYPE,SIZE,FSAVAIL,FSUSE%,MOUNTPOINTS

# 특정 디바이스만 확인
lsblk -f /dev/sdb

# 파티션 테이블 상세 정보 (루트 권한 필요)
sudo fdisk -l /dev/nvme0n1

fdisk -l 출력 예시:

Disk /dev/nvme0n1: 30 GiB, 32212254720 bytes, 62914560 sectors
Disk model: Amazon Elastic Block Store
Units: sectors of 1 * 512 = 512 bytes
Distor size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt

Device           Start      End  Sectors  Size Type
/dev/nvme0n1p1    2048  1050623  1048576  512M EFI System
/dev/nvme0n1p2 1050624  3147775  2097152    1G Linux filesystem
/dev/nvme0n1p3 3147776 62914526 59766751 28.5G Linux filesystem
bashlsblk -f

— — —

Step 4. 마운트 관리와 영구 설정

마운트는 파일시스템을 디렉토리 트리에 연결하는 작업입니다. 수동 마운트는 재부팅 시 사라지므로, 영구 설정은 /etc/fstab에 등록해야 합니다.

bash# 현재 마운트된 파일시스템 목록 확인
mount | grep -v "^cgroup\|^proc\|^sys\|^tmpfs\|^devtmpfs"
/dev/nvme0n1p3 on / type ext4 (rw,relatime)
/dev/nvme0n1p2 on /boot type ext4 (rw,relatime)
/dev/nvme0n1p1 on /boot/efi type vfat (rw,relatime,fmask=0077)
/dev/sdb1 on /data type xfs (rw,relatime,attr2,inode64,logbufs=8,noquota)
/dev/sdc1 on /backup type xfs (rw,relatime,attr2,inode64,logbufs=8,noquota)

수동 마운트 및 언마운트:

bash# 마운트 포인트 디렉토리 생성
sudo mkdir -p /mnt/external

# 파일시스템 마운트
sudo mount /dev/sdd1 /mnt/external

# 읽기 전용으로 마운트
sudo mount -o ro /dev/sdd1 /mnt/external

# 언마운트 (사용 중인 프로세스가 있으면 실패)
sudo umount /mnt/external

# 사용 중인 프로세스 확인 후 언마운트
lsof +D /mnt/external
sudo fuser -m /mnt/external

`/etc/fstab` 영구 마운트 설정:

bash# fstab 형식: <장치> <마운트포인트> <타입> <옵션> <dump> <fsck>
cat /etc/fstab
# /etc/fstab
UUID=b7d4e2f9-3c1a-4b82-8d5f-9e7a2c4b6f1e /       ext4  defaults        0 1
UUID=a3f2c1d8-7b4e-4f91-9c2a-1e8f6b3d5a7c /boot   ext4  defaults        0 2
UUID=4E21-3A9F                             /boot/efi vfat umask=0077     0 1
UUID=f1a2b3c4-d5e6-7f8a-9b0c-1d2e3f4a5b6c /data   xfs   defaults,nofail 0 2
UUID=9a8b7c6d-5e4f-3a2b-1c0d-9e8f7a6b5c4d /backup xfs   defaults,nofail 0 2

fstab 주요 옵션:

옵션 설명
defaults rw, suid, dev, exec, auto, nouser, async 기본값 묶음
nofail 마운트 실패해도 부팅 계속 진행 (외부 볼륨 필수)
noatime 파일 접근 시 atime 갱신 안 함 (I/O 성능 향상)
ro 읽기 전용 마운트
0 0 dump 비활성화, fsck 건너뜀
0 1 루트 파일시스템용 fsck 우선순위
0 2 루트 이후 fsck 실행
bash# fstab 수정 후 문법 검증 없이 전체 마운트 시도 (재부팅 전 테스트)
sudo mount -a

# UUID 확인 방법
blkid /dev/sdb1
bashmount / umount + /etc/fstab

— — —

Step 5. 디스크 I/O 모니터링

CPU와 메모리가 여유 있는데 서버가 느리다면 디스크 I/O 병목일 수 있습니다. iostat과 iotop으로 I/O 현황을 실시간으로 파악합니다.

bash# 1초 간격으로 확장 I/O 통계 출력 (sysstat 패키지 필요)
iostat -x 1
Linux 5.15.0-89-generic   03/26/2026   _x86_64_   (4 CPU)

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           8.25    0.00    3.42   31.67    0.12   56.54

Device            r/s     w/s     rkB/s     wkB/s   r_await  w_await  util
nvme0n1          12.40  245.80    156.80  15732.40      0.42     2.18  67.3%
sdb               0.20  189.60      2.60  12134.40      1.20    35.47  98.2%
sdc               0.10    4.20      1.20    268.80      2.10     8.34   3.1%

핵심 지표 읽는 법:

  • %iowait: CPU가 I/O 대기로 낭비한 비율 — 20% 이상이면 I/O 병목 의심
  • r/s, w/s: 초당 읽기/쓰기 요청 수
  • rkB/s, wkB/s: 초당 읽기/쓰기 처리량 (KB)
  • r_await, w_await: 읽기/쓰기 평균 응답시간 (ms) — HDD 20ms, SSD 1ms 이상이면 과부하
  • util: 장치 사용률 — `sdb`가 98.2%로 포화 상태
bash# 프로세스별 I/O 사용량 실시간 모니터링 (루트 권한 필요)
sudo iotop -o -d 2

# -o: I/O를 실제로 사용 중인 프로세스만 표시
# -d 2: 2초 간격 갱신
Total DISK READ: 1.23 M/s | Total DISK WRITE: 14.87 M/s
  TID  PRIO  USER  DISK READ  DISK WRITE  SWAPIN  IO>  COMMAND
 8421 be/4  postgres  0.00 B/s  13.45 M/s  0.00%  89.23% postgres: checkpointer
 3201 be/4  www-data  892.34 K/s  1.23 M/s  0.00%   8.12% nginx: worker
  891 be/4  root       0.00 B/s  198.23 K/s  0.00%   1.34% journald
bash# iotop 없을 때 대안: /proc/diskstats로 수동 확인
cat /proc/diskstats | awk '{print $3, $6, $10}' | grep -v "^loop\|^ram"

# 특정 장치의 I/O 대기 큐 크기 확인
cat /sys/block/sdb/queue/nr_requests
bashiostat -x 1 / iotop

— — —

Step 6. 디스크 쓰기 속도 테스트

새 서버나 스토리지 볼륨을 받았을 때, 또는 성능 이슈가 의심될 때 디스크 순차 쓰기 속도를 측정합니다.

bash# /tmp에 1GB 파일 쓰기 테스트 (bs=1M × count=1000)
dd if=/dev/zero of=/tmp/testfile bs=1M count=1000 conv=fdatasync
1000+0 records in
1000+0 records out
1048576000 bytes (1.0 GB, 1000 MiB) copied, 3.47218 s, 302 MB/s

옵션 설명:

  • if=/dev/zero: 입력 소스로 /dev/zero(무한 0 바이트 스트림) 사용
  • of=/tmp/testfile: 출력 파일 경로
  • bs=1M: 블록 크기 1MB (큰 블록 = 순차 I/O 시나리오)
  • count=1000: 1000블록 = 1GB
  • conv=fdatasync: 커널 버퍼 캐시를 거치지 않고 디스크에 직접 쓰기 (실제 디스크 속도 측정)

속도 기준값 (참고):

스토리지 유형 예상 순차 쓰기 속도
AWS EBS gp3 125 ~ 1000 MB/s
AWS EBS io2 256 KB/s ~ 4 GB/s
NVMe SSD (로컬) 1 ~ 7 GB/s
SATA SSD 300 ~ 560 MB/s
HDD (SATA) 80 ~ 200 MB/s
bash# 테스트 후 반드시 파일 삭제
rm /tmp/testfile

# 읽기 속도 테스트 (페이지 캐시 비우기 후 측정)
sudo sh -c 'echo 3 > /proc/sys/vm/drop_caches'
dd if=/tmp/testfile of=/dev/null bs=1M

주의: 운영 서버에서 dd 테스트 시 대상 경로를 반드시 확인하세요. of=/dev/sdb 처럼 장치 파일을 직접 지정하면 해당 디스크 데이터가 영구 삭제됩니다.

bashdd if=/dev/zero of=/tmp/test bs=1M count=1000

— — —

트러블슈팅: 현장에서 마주치는 디스크 장애

트러블슈팅
No space left on device — 디스크 풀 장애

증상

[Errno 28] No space left on device: '/var/log/app.log'
write error: No space left on device
cp: cannot create regular file '/tmp/backup.tar.gz': No space left on device

원인 진단

1단계: 어떤 파티션이 가득 찼는지 파악

bashdf -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/nvme0n1p3   30G   30G     0 100% /var

2단계: 문제 파티션에서 주범 추적

bashdu -sh /var/* 2>/dev/null | sort -rh | head -15
18G     /var/log
7.2G    /var/cache
3.1G    /var/lib
bashdu -sh /var/log/* 2>/dev/null | sort -rh | head -10
16G     /var/log/journal
1.1G    /var/log/nginx
450M    /var/log/app

3단계: 즉각 대응

bash# systemd journal 로그 정리 (최근 7일치만 보존)
sudo journalctl --vacuum-time=7d

# 오래된 로그 아카이브 삭제
sudo find /var/log -name "*.gz" -mtime +30 -delete
sudo find /var/log -name "*.log.*" -mtime +14 -delete

# /tmp 정리
sudo find /tmp -type f -mtime +3 -delete

# 코어 덤프 정리
sudo find /var/crash /tmp -name "core.*" -delete
sudo coredumpctl list
sudo rm -rf /var/lib/systemd/coredump/*

4단계: 삭제했는데도 공간이 안 늘어날 때 — 열려있는 삭제 파일

파일을 rm으로 삭제해도, 프로세스가 해당 파일을 열고 있으면 실제 블록은 해제되지 않습니다.

bash# 삭제됐지만 프로세스가 여전히 열고 있는 파일 찾기
sudo lsof | grep "(deleted)"
nginx     3201  www-data   3w   REG  259,3  9663676416 1234567 /var/log/nginx/access.log (deleted)
bash# 해결: 해당 프로세스 재시작
sudo systemctl restart nginx

# 또는 프로세스를 종료하지 않고 파일 내용만 비우기 (PID와 fd 번호 활용)
> /proc/3201/fd/3

재발 방지

bash# logrotate 설정 확인
cat /etc/logrotate.d/nginx

# systemd journal 최대 크기 제한
sudo sed -i 's/#SystemMaxUse=/SystemMaxUse=2G/' /etc/systemd/journald.conf
sudo systemctl restart systemd-journald

— — —

트러블슈팅
디스크 공간은 있는데 파일 생성 실패 — inode 고갈

증상

bashtouch /var/www/newfile.txt
touch: cannot touch '/var/www/newfile.txt': No space left on device

df -h  # 여전히 공간 있음
Filesystem      Size  Used Avail Use% Mounted on
/dev/sdb1       500G  245G  255G  49% /var/www   # 49%인데 파일 생성 실패?

원인 파악

bashdf -i
Filesystem      Inodes   IUsed   IFree IUse% Mounted on
/dev/nvme0n1p3 1966080 1966080       0  100% /var
/dev/sdb1      31252480  3421012 27831468   11% /data

/var 파티션의 inode가 100% 소진되었습니다. 디스크 바이트는 남아 있지만 파일을 더 만들 수 없습니다.

주범 찾기

inode를 대량 소비하는 주원인은 작은 파일이 수없이 많은 경우입니다 (이메일 스풀, 캐시, 세션 파일, PHP 세션 등).

bash# 하위 디렉토리별 파일 수 카운트
for dir in /var/*/; do
  count=$(find "$dir" -type f 2>/dev/null | wc -l)
  echo "$count $dir"
done | sort -rn | head -15
4821903 /var/spool/postfix/deferred/
342891  /var/cache/php/sessions/
89234   /var/tmp/

해결

bash# postfix 큐 긴급 정리 (운영 환경 주의)
sudo postsuper -d ALL deferred

# PHP 세션 파일 정리 (30분 이상 된 것)
sudo find /var/cache/php/sessions/ -type f -mmin +30 -delete

# 처리 후 inode 확인
df -i /var

재발 방지

bash# 파일시스템 생성 시 inode 밀도 조정 (ext4)
# bytes-per-inode 값을 낮추면 inode 수 증가 (파일시스템 생성 시에만 가능)
mkfs.ext4 -i 4096 /dev/sdd1  # 기본 16384 대신 4096바이트당 inode 1개

— — —

트러블슈팅
fstab 잘못 작성 후 부팅 실패

증상

/etc/fstab을 수정하고 재부팅했더니 서버가 응급 복구 모드로 진입합니다.

[  ***  ] A start job is running for /data (2min 30s / no limit)
[FAILED] Failed to mount /data.
You are in emergency mode. After logging in, type "journalctl -xb" to view
system logs, "systemctl reboot" to reboot, "systemctl default" or "exit"
to boot into default mode.
Give root password for maintenance (or press Control-D to continue):

원인 유형

  1. 존재하지 않는 UUID 입력
  2. 마운트 포인트 디렉토리 미생성
  3. 잘못된 파일시스템 타입 지정
  4. nofail 옵션 누락으로 선택적 볼륨 실패가 부팅 중단 유발

복구 절차

bash# 1. emergency mode에서 root 암호 입력 후 로그인

# 2. 루트 파일시스템을 읽기-쓰기로 재마운트
mount -o remount,rw /

# 3. fstab 편집
nano /etc/fstab
# 문제가 된 라인 주석 처리 또는 수정

# 4. 구문 검증
mount -a --fake    # 실제 마운트 없이 fstab 구문 검사

# 5. 재부팅
reboot

올바른 fstab 작성 패턴

bash# 클라우드/외부 볼륨에는 반드시 nofail 추가
UUID=f1a2b3c4-d5e6-7f8a-9b0c-1d2e3f4a5b6c /data xfs defaults,nofail 0 2

# fstab 수정 후 재부팅 전 반드시 테스트
sudo mount -a   # 오류 없으면 안전

예방 습관: fstab 수정 후 sudo mount -a로 반드시 테스트합니다. 클라우드 환경에서 데이터 볼륨에는 반드시 nofail을 추가하세요. AWS EC2에서 EBS가 연결되기 전에 인스턴스가 부팅을 시도할 수 있습니다.

— — —

실무 시나리오

실무 맥락
서버 디스크 90% 경보 대응

새벽 2시, 모니터링 시스템이 운영 서버 /var 파티션 90% 사용률 알람을 발송했습니다. 서비스는 아직 정상이지만 계속 증가하면 수 시간 내에 장애가 발생합니다.

표준 진단 플로우

bash# Step 1: 전체 파티션 상태 파악
df -hT
# → /var 파티션이 90%

# Step 2: /var 내 주요 디렉토리 용량 분석
sudo du -sh /var/* 2>/dev/null | sort -rh | head -10
# → /var/log 가 가장 크다고 가정

# Step 3: 로그 디렉토리 드릴다운
sudo du -sh /var/log/* 2>/dev/null | sort -rh | head -10
# → /var/log/app/access.log 가 30GB로 비정상 크기

# Step 4: 삭제됐는데 공간이 안 줄어드는지 확인
sudo lsof | grep "(deleted)" | awk '{print $1, $2, $7, $NF}' | sort -k3 -rn | head -10
# → 앱 프로세스가 삭제된 파일을 여전히 열고 있는지 확인

# Step 5: 실시간 쓰기 중인 프로세스 특정
sudo iotop -o -d 1

# Step 6: 로그 로테이션 강제 실행
sudo logrotate -f /etc/logrotate.d/myapp

# Step 7: 서비스 재시작으로 파일 핸들 해제
sudo systemctl restart myapp

# Step 8: 공간 회복 확인
df -h /var

임시 방편이 아닌 근본 해결

bash# 로그 레벨 확인 (DEBUG 레벨이면 INFO로 낮추기)
grep -i "log.level\|LOG_LEVEL" /etc/myapp/config.yaml

# logrotate 주기와 보존 정책 검토
cat /etc/logrotate.d/myapp
# rotate 7 → 더 짧게, daily → 더 자주

# 로그 볼륨을 별도 파티션으로 분리 검토 (장기 대책)

— — —

실무 맥락
데이터 볼륨 마운트 자동화 — AWS EBS 연결 보장

새로운 EC2 인스턴스를 시작할 때 /data 볼륨(EBS)이 서비스 시작 전에 반드시 마운트되어 있어야 합니다. 잘못된 순서로 서비스가 먼저 시작되면 /data에 쓰려던 파일이 루트 파티션에 쌓이고, EBS가 나중에 마운트되면 해당 마운트 포인트가 가려집니다.

문제 상황

bash# 서비스 시작 후 EBS가 마운트된 경우 발생하는 문제
ls /data/           # EBS 마운트 전 루트에 쌓인 파일들이 보임
umount /data        # EBS 언마운트
ls /data/           # 루트에 쌓인 쓰레기 파일 노출

systemd 의존성으로 마운트 보장

bash# /etc/systemd/system/data.mount 생성 (파일명이 마운트 경로와 일치해야 함)
sudo tee /etc/systemd/system/data.mount << 'EOF'
[Unit]
Description=Data Volume Mount
After=local-fs.target

[Mount]
What=/dev/disk/by-uuid/f1a2b3c4-d5e6-7f8a-9b0c-1d2e3f4a5b6c
Where=/data
Type=xfs
Options=defaults,nofail

[Install]
WantedBy=multi-user.target
EOF

# 서비스에서 마운트 의존성 선언
sudo tee /etc/systemd/system/myapp.service << 'EOF'
[Unit]
Description=My Application
After=network.target data.mount
Requires=data.mount

[Service]
ExecStart=/usr/bin/myapp
Restart=on-failure

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable data.mount myapp

스크립트 방식 마운트 검증 (부트스트랩)

EC2 User Data나 Ansible로 프로비저닝할 때 사용할 수 있는 패턴입니다.

bash#!/bin/bash
# /usr/local/bin/ensure-data-mount.sh

MOUNT_POINT="/data"
DEVICE_UUID="f1a2b3c4-d5e6-7f8a-9b0c-1d2e3f4a5b6c"
MAX_WAIT=60
WAITED=0

echo "Waiting for data volume to be available..."

while ! blkid | grep -q "$DEVICE_UUID"; do
  if [ $WAITED -ge $MAX_WAIT ]; then
    echo "ERROR: Data volume not found after ${MAX_WAIT}s. Aborting."
    exit 1
  fi
  sleep 2
  WAITED=$((WAITED + 2))
  echo "  Still waiting... (${WAITED}s)"
done

echo "Device found. Mounting to ${MOUNT_POINT}..."
mkdir -p "$MOUNT_POINT"
mount UUID="$DEVICE_UUID" "$MOUNT_POINT"

if mountpoint -q "$MOUNT_POINT"; then
  echo "Mount successful: $(df -h $MOUNT_POINT | tail -1)"
else
  echo "ERROR: Mount failed."
  exit 1
fi
bashchmod +x /usr/local/bin/ensure-data-mount.sh
# ExecStartPre에 등록하여 서비스 시작 전 실행 보장

다음 모듈에서는 LVM(Logical Volume Manager) — 파티션 크기를 유연하게 조정하는 논리 볼륨 관리를 다룹니다.

반응형
LIST

'Linux' 카테고리의 다른 글

[Linux] 디스크 트러블슈팅  (0) 2026.05.22
[Linux] LVM & 볼륨 관리  (0) 2026.05.22
[Linux] Bash 스크립팅 기초  (0) 2026.05.22
[Linux] 텍스트 처리 (grep/awk/sed)  (0) 2026.05.22
[Linux ] systemd 서비스 관리  (0) 2026.05.22
'Linux' 카테고리의 다른 글
  • [Linux] 디스크 트러블슈팅
  • [Linux] LVM & 볼륨 관리
  • [Linux] Bash 스크립팅 기초
  • [Linux] 텍스트 처리 (grep/awk/sed)
cumo
cumo
  • cumo
    이것저것
    cumo
    • 분류 전체보기 (147) N
      • 이것저것 (1)
      • 보안뉴스 (15)
      • Project (12)
      • wargame (1)
      • Cloud (25)
      • DevOps (21)
      • Linux (43)
      • 네트워크 (23)
      • AWS Developer BootCamp (1)
      • WEB&WAS (3)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

    • 도구모음 사이트
    • 참고 기술 블로그
  • 공지사항

  • 인기 글

  • 태그

    ubuntu
    눅스네트워킹
    논리볼륨
    터미널멀티플렉서
    부팅서비스
    디렉토리구조
    Volume Group
    포트진단
    리눅스
    bash입문
    텍스트편집기
    스토리지확장
    데몬
    인프라
    서버관리
    Linux
    vim
    서버편집
    vi
    nano
  • 최근 댓글

  • 최근 글

  • 반응형
  • hELLO· Designed By정상우.v4.10.3
cumo
[Linux] 디스크와 스토리지 관리
상단으로

티스토리툴바