리눅스 LVM: 물리 볼륨, 볼륨 그룹, 논리 볼륨 실습 가이드
리눅스 LVM(Logical Volume Manager)은 디스크와 파일 시스템 사이의 계층입니다. 디스크는 물리 볼륨(PV)이 되고, 여러 PV는 볼륨 그룹(VG)으로 묶이며, VG에서 원하는 크기의 논리 볼륨(LV)을 잘라 냅니다. 가장 큰 장점은 lvextend -r로 볼륨을 즉시 늘리고, 서비스를 멈추지 않고 디스크를 추가하며, 위험한 작업 전에 스냅숏을 만들 수 있다는 점입니다.
LVM(Logical Volume Manager)은 리눅스의 논리 볼륨 관리자입니다. 파일 시스템을 물리 디스크에서 분리합니다. /var를 /dev/sdb1 파티션에 고정하는 대신, 디스크들을 공용 풀에 모아 필요한 크기만큼 볼륨을 잘라 씁니다. 공간이 모자라면 재부팅도 서비스 중단도 없이 명령 하나로 볼륨을 늘릴 수 있습니다. 아래에서는 리눅스 LVM의 구조, 처음부터 볼륨을 만드는 과정, 확장과 스냅숏, 그리고 데이터를 잃지 않는 방법을 다룹니다.
일반 파티션 대신 LVM을 써야 하는 이유
일반 파티션은 한 디스크의 연속된 구간입니다. 크기는 파티션을 나눌 때 정해지고, 바로 뒤에 빈 공간이 있을 때만 늘릴 수 있습니다. 디스크가 꽉 차면 새 디스크를 사고, 데이터를 옮기고, /etc/fstab을 고쳐야 하며, 그동안 서비스를 멈춰야 합니다.
LVM은 세 가지 문제를 해결합니다.
- 유연한 크기. 논리 볼륨은 언제든 늘릴 수 있고, ext4라면 줄이는 것도 가능합니다.
- 디스크 합치기. 여러 물리 디스크가 하나의 풀이 되며, 한 볼륨이 두 디스크에 걸쳐 있을 수도 있습니다.
- 스냅숏. 업그레이드, 데이터베이스 이전 같은 위험한 작업 전에 볼륨의 순간 사본을 만듭니다.
그래서 Ubuntu Server, RHEL, Rocky, AlmaLinux 설치 프로그램은 기본적으로 LVM을 제안하며, 데이터를 담는 서버에서는 거의 항상 LVM을 씁니다.
LVM의 세 계층: PV, VG, LV
LVM의 구조는 세 가지 개념으로 이해할 수 있습니다. 디스크는 밀가루 포대, 볼륨 그룹은 공용 창고, 논리 볼륨은 창고에서 덜어 쓰는 분량이라고 생각하면 편합니다.
| 계층 | 의미 | 이름 예시 | 생성 명령 |
|---|---|---|---|
| PV (Physical Volume) | LVM용으로 준비된 디스크나 파티션 | /dev/sdb, /dev/sdc1 | pvcreate |
| VG (Volume Group) | 하나 이상의 PV를 묶은 풀 | data_vg | vgcreate |
| LV (Logical Volume) | VG에서 잘라 낸 볼륨. 여기에 파일 시스템을 만듦 | /dev/data_vg/app | lvcreate |
VG 안의 공간은 익스텐트(PE, physical extent)라는 고정 크기 블록으로 나뉩니다. 기본 크기는 4MiB입니다. 논리 볼륨은 이 익스텐트들의 묶음이며, 익스텐트가 연속일 필요도 없고 서로 다른 디스크에 있어도 됩니다. 그래서 볼륨을 쉽게 늘릴 수 있습니다. LVM은 어디에서든 빈 익스텐트를 찾아 덧붙이기만 하면 됩니다.
논리 볼륨 장치는 두 가지 동등한 경로로 접근합니다. /dev/data_vg/app과 /dev/mapper/data_vg-app입니다. 내부적으로는 커널의 device-mapper 장치입니다.
현재 상태 확인하기
먼저 패키지가 설치되어 있는지 확인하십시오. Debian과 Ubuntu에서는 lvm2(sudo apt install lvm2)이며, RHEL 계열에는 기본으로 들어 있습니다. 전체 구조를 보는 간단한 명령과 자세한 명령이 있습니다.
$ sudo pvs
PV VG Fmt Attr PSize PFree
/dev/sdb data_vg lvm2 a-- <20.00g 0
/dev/sdc data_vg lvm2 a-- <20.00g <10.00g
$ sudo vgs
VG #PV #LV #SN Attr VSize VFree
data_vg 2 1 0 wz--n- 39.99g <10.00g
$ sudo lvs
LV VG Attr LSize Pool Origin Data% Meta%
app data_vg -wi-ao---- 30.00g
자세한 정보는 pvdisplay, vgdisplay, lvdisplay로 볼 수 있습니다. 일반 파티션과 함께 전체 그림을 보려면 lsblk를 쓰십시오. 논리 볼륨은 타입이 lvm으로 표시됩니다.
$ lsblk /dev/sdb /dev/sdc
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
sdb 8:16 0 20G 0 disk
└─data_vg-app 253:0 0 30G 0 lvm /srv/app
sdc 8:32 0 20G 0 disk
└─data_vg-app 253:0 0 30G 0 lvm /srv/app
여기서 30GB 크기의 app 볼륨은 각각 20GB인 두 디스크에 걸쳐 있습니다. 일반 파티션으로는 이렇게 할 수 없습니다.
LVM 처음부터 만들기: 빈 디스크에서 마운트까지
서버에 빈 디스크 /dev/sdb를 추가했고, 애플리케이션 데이터용으로 15GB 볼륨이 필요하다고 가정하겠습니다. 장치 이름은 lsblk로 두 번 확인하십시오. 아래 명령은 모두 지정한 장치의 데이터를 지웁니다.
1단계. 물리 볼륨 만들기
$ sudo pvcreate /dev/sdb
Physical volume "/dev/sdb" successfully created.
디스크 전체를 LVM에 넘길 수도 있고, fdisk나 parted로 "Linux LVM" 타입의 파티션을 먼저 만든 뒤 /dev/sdb1을 지정할 수도 있습니다. 파티션을 만들면 다른 관리자가 보기에도 명확하고, LVM 위에 실수로 다른 파티션 테이블을 쓰는 사고를 막습니다. 반면 클라우드에서는 디스크 전체를 넘기는 쪽이 확장하기 쉽습니다.
2단계. 볼륨 그룹 만들기
$ sudo vgcreate data_vg /dev/sdb
Volume group "data_vg" successfully created
3단계. 논리 볼륨 잘라 내기
$ sudo lvcreate -n app -L 15G data_vg
Logical volume "app" created.
-L은 절대 크기를, -l은 익스텐트 수나 백분율을 지정합니다. -l 100%FREE는 그룹의 남은 공간 전부를, -l 50%VG는 그룹의 절반을 씁니다. VG에 여유 공간을 남겨 두는 것은 좋은 습관입니다. 나중에 아무 볼륨에나 더하거나 스냅숏에 쓸 수 있습니다.
4단계. 파일 시스템 만들고 마운트하기
$ sudo mkfs.ext4 /dev/data_vg/app
$ sudo mkdir -p /srv/app
$ sudo mount /dev/data_vg/app /srv/app
$ df -h /srv/app
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/data_vg-app 15G 24K 14G 1% /srv/app
재부팅 후에도 마운트되게 하려면 /etc/fstab에 줄을 추가하십시오. 논리 볼륨의 /dev/mapper/... 경로는 안정적이므로 그대로 쓰거나, blkid로 확인한 UUID를 쓸 수 있습니다.
/dev/mapper/data_vg-app /srv/app ext4 defaults 0 2
재부팅 전에 sudo mount -a로 항목을 검사하십시오. fstab에 오류가 있으면 서버가 긴급 모드로 부팅될 수 있습니다.
서비스를 멈추지 않고 LVM 볼륨 확장하기
LVM을 써야 하는 가장 큰 이유가 바로 이 기능입니다. 볼륨은 마운트된 파일 시스템 상태에서 늘어나며, 애플리케이션은 계속 데이터를 쓸 수 있습니다. 방법은 그룹에 빈 공간이 있는지에 따라 다릅니다.
VG에 빈 공간이 있는 경우
$ sudo vgs data_vg
VG #PV #LV #SN Attr VSize VFree
data_vg 1 1 0 wz--n- <20.00g <5.00g
$ sudo lvextend -r -L +4G /dev/data_vg/app
Size of logical volume data_vg/app changed from 15.00 GiB to 19.00 GiB.
Logical volume data_vg/app successfully resized.
resize2fs 1.47.0
Filesystem at /dev/mapper/data_vg-app is mounted on /srv/app; on-line resizing required
핵심 옵션은 -r(--resizefs)입니다. 볼륨을 늘린 직후에 파일 시스템도 함께 늘립니다. 이 옵션이 없으면 볼륨은 커지지만 파일 시스템은 새 공간을 모르기 때문에 df -h는 예전 크기를 보여 줍니다. 가장 흔한 실수입니다. 이 경우에는 ext4라면 resize2fs, XFS라면 xfs_growfs를 수동으로 실행하면 됩니다.
$ sudo resize2fs /dev/data_vg/app # ext4, 장치 이름을 지정
$ sudo xfs_growfs /srv/app # XFS, 마운트 지점을 지정
주의할 점: -L +4G는 4GB를 더하고, -L 4G는 최종 크기를 4GB로 설정합니다. 남은 공간 전부를 주려면 -l +100%FREE를 쓰십시오.
VG의 공간이 모자란 경우: 디스크 추가
새 디스크를 연결하고(클라우드라면 볼륨을 붙이고), lsblk로 찾은 뒤 그룹에 추가하십시오.
$ sudo pvcreate /dev/sdc
$ sudo vgextend data_vg /dev/sdc
Volume group "data_vg" successfully extended
$ sudo lvextend -r -l +100%FREE /dev/data_vg/app
세 명령이면 끝이고 서비스 중단은 없습니다. 파일 시스템은 이제 두 디스크에 걸쳐 있으며, 애플리케이션은 이를 알아채지 못합니다.
클라우드에서 디스크 크기를 늘린 경우
클라우드에서는 디스크를 추가하기보다 기존 디스크를 키우는 편이 간단한 경우가 많습니다. 이때 커널은 장치의 새 크기를 보지만, 물리 볼륨은 pvresize로 늘려 줘야 합니다.
$ sudo pvresize /dev/sdb
Physical volume "/dev/sdb" changed
$ sudo lvextend -r -l +100%FREE /dev/data_vg/app
PV가 파티션(/dev/sdb1) 위에 있다면, 먼저 cloud-guest-utils 패키지의 growpart /dev/sdb 1로 파티션을 늘리고, 그다음에 pvresize /dev/sdb1을 실행하십시오.
LVM 볼륨을 줄일 수 있을까
가능하지만 모든 파일 시스템에서 되는 것은 아니고, 마운트된 상태에서는 할 수 없습니다. XFS는 아예 줄일 수 없고, 데이터를 옮기며 다시 만들어야 합니다. ext4는 줄일 수 있지만 마운트를 해제한 상태여야 합니다.
$ sudo umount /srv/app
$ sudo lvreduce -r -L 10G /dev/data_vg/app
-r을 주면 LVM이 파일 시스템 검사(e2fsck)를 한 뒤 파일 시스템을 먼저 줄입니다. -r이 없으면 파일 시스템보다 작게 볼륨을 잘라 버려 데이터가 손상될 수 있습니다. 줄이기 전에는 반드시 백업하십시오.
LVM 스냅숏: 위험한 작업 전의 사본
스냅숏은 논리 볼륨의 순간 사본입니다. 수 초 안에 만들어지며 데이터를 복사하지 않습니다. LVM은 copy-on-write 방식으로, 스냅숏 생성 이후 원본에서 바뀌는 블록만 스냅숏 공간에 저장합니다. 그래서 스냅숏에는 볼륨 전체 크기가 아니라 변경량만큼의 공간이 필요합니다.
$ sudo lvcreate -s -n app_before_upgrade -L 2G /dev/data_vg/app
Logical volume "app_before_upgrade" created.
$ sudo lvs data_vg
LV VG Attr LSize Origin Data%
app data_vg owi-aos--- 19.00g
app_before_upgrade data_vg swi-a-s--- 2.00g app 0.01
Data% 열은 변경 내역을 저장하는 공간이 얼마나 찼는지 보여 줍니다. 이 값이 100%에 이르면 클래식 스냅숏은 무효가 되며, 삭제하는 것 말고는 할 수 없습니다. 크기는 예상 변경량에 여유를 두고 정하고, 오래 유지하는 스냅숏은 lvs로 감시하거나 lvextend로 늘리십시오.
스냅숏으로 되돌리기
업그레이드가 잘못되었다면 스냅숏 시점의 상태로 되돌리십시오.
$ sudo umount /srv/app
$ sudo lvconvert --merge /dev/data_vg/app_before_upgrade
Merging of volume data_vg/app_before_upgrade started.
$ sudo mount /srv/app
병합이 끝나면 스냅숏은 사라집니다. 볼륨을 마운트 해제할 수 없다면(예: 시스템 루트), 병합은 다음 볼륨 활성화 때, 즉 재부팅 후에 진행됩니다.
작업이 잘 끝났을 때
스냅숏은 쓰기를 느리게 하고 공간을 차지하므로 삭제하십시오.
$ sudo lvremove /dev/data_vg/app_before_upgrade
스냅숏을 읽기 전용으로 마운트하면, 돌아가는 시스템의 일관된 백업을 받을 수도 있습니다. mount -o ro로 마운트한 뒤 rsync나 tar로 복사하십시오. XFS라면 원본과 UUID가 같아서 마운트가 거부되므로 nouuid 옵션을 추가해야 합니다.
LVM과 RAID: 목적이 다릅니다
LVM은 그 자체로 디스크 장애를 막아 주지 않습니다. 한 볼륨이 두 디스크에 걸쳐 있고 그중 하나가 고장 나면, 절반이 아니라 볼륨 전체를 잃습니다. 장애에 대비하려면 LVM 아래에 RAID(mdadm)를 두거나, LVM 자체의 미러 기능(lvcreate --type raid1 -m 1)을 쓰십시오.
RAID와 스냅숏은 백업을 대신하지 못합니다. 스냅숏은 원본과 같은 디스크에 있고, RAID는 실수로 실행한 rm -rf까지 충실히 복제합니다. 별도의 매체에 있는 백업이 반드시 필요합니다.
LVM 명령 요약표
| 작업 | 명령 |
|---|---|
| PV, VG, LV 전체 보기 | pvs, vgs, lvs |
| 물리 볼륨 만들기 | pvcreate /dev/sdb |
| 볼륨 그룹 만들기 | vgcreate data_vg /dev/sdb |
| 그룹에 디스크 추가 | vgextend data_vg /dev/sdc |
| 논리 볼륨 만들기 | lvcreate -n app -L 15G data_vg |
| 볼륨과 파일 시스템 확장 | lvextend -r -L +5G /dev/data_vg/app |
| 디스크 증설 후 PV 늘리기 | pvresize /dev/sdb |
| 스냅숏 만들기 | lvcreate -s -n snap -L 2G /dev/data_vg/app |
| 스냅숏으로 되돌리기 | lvconvert --merge /dev/data_vg/snap |
| 그룹에서 디스크 빼기 | pvmove /dev/sdb 후 vgreduce data_vg /dev/sdb |
| 볼륨 삭제 | lvremove /dev/data_vg/app |
흔한 실수
- 볼륨은 늘렸는데 df는 예전 크기를 보임.
-r을 빠뜨렸습니다.resize2fs나xfs_growfs를 실행하십시오. - Insufficient free space. 그룹에 빈 익스텐트가 없습니다.
vgs로 확인하고,vgextend로 디스크를 추가하거나 PV를 늘리십시오. - Device /dev/sdc excluded by a filter. 디스크에 이전 파티션 정보나 파일 시스템 서명이 남아 있습니다. 데이터가 필요 없다는 것이 확실하면
wipefs -a /dev/sdc로 지우십시오. - 스냅숏이 Invalid 상태가 됨. 변경 저장 공간이 100%까지 찼습니다. 복구는 불가능하며, 삭제한 뒤 다음에는 더 큰 공간을 할당하십시오.
정리
리눅스 LVM은 세 계층으로 이루어집니다. 물리 볼륨(PV)이 볼륨 그룹(VG)에 모이고, 그 안에서 논리 볼륨(LV)이 잘려 나옵니다. 이 구조 덕분에 일반 파티션에는 없는 기능이 생깁니다. lvextend -r로 즉시 확장하고, 서비스 중단 없이 디스크를 추가하며, 위험한 변경 전에 스냅숏을 만들 수 있습니다. 다만 LVM은 RAID나 백업을 대신하지 않는다는 점을 기억하십시오. 디스크 파티션, LVM, RAID, 쿼터는 강의 실습에서 함께 다룹니다.
자주 묻는 질문
이미 데이터가 있는 파티션을 LVM으로 바꿀 수 있나요?
바로는 안 됩니다. pvcreate가 장치 앞부분을 덮어쓰기 때문입니다. 다른 디스크에 LVM을 만들고, rsync로 데이터를 복사한 뒤, fstab을 고치고, 마지막에 기존 파티션을 비우는 순서로 진행하십시오.
LVM을 쓰면 디스크 성능이 떨어지나요?
스냅숏이 없다면 device-mapper의 부담은 거의 느껴지지 않습니다. 활성 classic 스냅숏은 copy-on-write 때문에 원본 쓰기를 느리게 하므로, 몇 주씩 유지하지 않는 것이 좋습니다.
가정용 PC나 노트북에도 LVM이 필요한가요?
필수는 아니지만, LUKS 암호화와 LVM을 함께 쓰거나 파티션을 다시 나누지 않고 크기를 바꾸고 싶다면 유용합니다. 데이터를 담는 서버에서는 사실상 표준입니다.
LVM의 thin provisioning은 무엇인가요?
얇은 볼륨입니다. 씬 풀(lvcreate --type thin-pool)을 만들고, 그 안의 볼륨은 데이터가 기록되는 만큼만 실제 공간을 차지합니다. 물리 용량보다 많은 크기를 할당할 수 있지만, 풀의 사용량을 꼭 감시해야 합니다.
데이터를 잃지 않고 볼륨 그룹에서 디스크를 빼려면 어떻게 하나요?
pvmove /dev/sdb로 익스텐트를 그룹의 다른 디스크로 옮깁니다(여유 공간이 충분해야 합니다). 그다음 vgreduce data_vg /dev/sdb와 pvremove /dev/sdb를 실행하십시오.