LVM 이란?
- 여러 개의 물리 디스크를 합쳐서 하나의 파일 시스템으로 구성
- 서버 운영에 있어서 작은 용량의 HDD를 하나로 합쳐 대용량의 스토리지를 구성할 떄 사용
- 스토리지 확장 및 변경사항에 있어 유연한 대처 및 관리가 가능해짐
LVM(Logical Volume Manager) 는 Linux의 저장 공간을 효율적이고 유연하게 관리하기 위한 Kernel의 한 부분이다.
그렇다면 LVM과 일반 디스크 파티셔닝은 어떤 차이점을 가지고 있을까?
LVM 방식이 아닌 기존 방식의 경우
HDD를 파티셔닝(partitioning) 한 뒤, OS 영역에 마운트하여 R/W(Read/Write) 해주는 방식인데
LVM은 파티션 대신 Volume 이라는 단위로 저장 장치를 다룬다.
이런 방식을 사용하기 때문에 LVM은 스토리지의 확장/변경에 매우 유연하다.
용어
- Physical Volume: 물리적인 볼륨을 뜻하며,
/dev/sdb1,/dev/sdc1과 같은 실제 파티션을 의미 - Volume Group: Physical Volume을 합친 그룹을 의미함
- Logical Volume: 합쳐진 Volume Group을 나누어 실제 사용하는 볼륨
LVM 설치
LVM을 설치하는 방법은 다음과 같다.
Ubuntu: 18.04 기준
$ sudo apt-get install -y lvm2 # LVM 설치CentOS 7 기준
$ yum install -y lvm2 # LVM 설치
$ rpm -qa | grep 'lvm' # 설치 되었는지 확인LVM 구성하기
그럼 이제 어떻게 LVM을 구성하는지 공부해보자.
사전 준비
- LVM을 구성하기 위해 하드디스크 1GB짜리를 3개 추가
디스크 확인: /dev/sdb, /dev/sdc, /dev/sdd
lsblk
sdb 8:16 0 1G 0 disk
sdc 8:32 0 1G 0 disk
sdd 8:48 0 1G 0 disk
# 또는
fdisk -l
Disk /dev/sdd: 1073 MB, 1073741824 bytes, 2097152 sectors
Disk /dev/sdc: 1073 MB, 1073741824 bytes, 2097152 sectors
Disk /dev/sdb: 1073 MB, 1073741824 bytes, 2097152 sectorsLVM 설치
sudo apt update -y
sudo apt install lvm2 -y파티션 생성
fdisk또는parted로 빈 디스크에 LVM 용 파티션을 생성해줘야 한다.type=8e
parted 명령어를 통해 /dev/sdb, /dev/sdc, /dev/sdd 디스크에 대해 파티션을 생성하도록 하자
sudo parted /dev/sdb mklabel gpt
sudo parted -a optimal /dev/sdb mkpart primary 0% 100%
sudo parted /dev/sdb set 1 lvm on
# ... /dev/sdc /dev/sdd에도 동일하게 위 작업 진행파티션 목록 조회하기
lsblk | grep "sd.*" | tail -n 6
sdb 8:16 0 1G 0 disk
└─sdb1 8:17 0 1023M 0 part
sdc 8:32 0 1G 0 disk
└─sdc1 8:33 0 1023M 0 part
sdd 8:48 0 1G 0 disk
└─sdd1 8:49 0 1023M 0 partfdisk vs parted
실무에서는 fdisk, parted 둘 다 자주 쓰이는 명령어지만
필자는 parted 명령어를 사용해 파티션을 구성하는 것을 더 추천한다.
그 이유를 다음과 같이 정리해봤다.
| 구분 | fdisk | parted |
|---|---|---|
| 지원하는 파티션 테이블 | MBR 위주 (최신 fdisk는 GPT도 지원함) | GPT·MBR 모두 네이티브 지원 |
| 대용량 디스크 지원 | 2TB 이하 MBR이 한계임, GPT 지원 시에도 그 사용법이 조금 복잡함 | 스크립트·비대화식 모드에서 대용량 디스크(GPT) 다루기 편리 |
| 사용성 | 간단·경량, 거의 모든 리눅스에 기본 탑재 | 기능이 많아 약간 학습 필요하지만, 한 번 익히면 더 유연하게 사용 가능 |
| 자동화·스크립트 | 상호작용형이 기본, 자동화하려면 sfdisk 등 별도 도구 필요 | 비대화식(non-interactive) 모드로 명령 단일화 → 배치 스크립트에 용이 |
| 리사이즈 | 파티션 생성/삭제만 지원함, 이동·크기 조정은 별도 도구 필요 | 파티션 이동·크기 조정 기능 내장 |
요즘 서버 스토리지는 4TB, 8TB 이상이 일반적이지 않나?
parted는 GPT를 네이티브로 지원하면서 큰 디스크를 다루는데 제약이 없다.
또한, 파티션 생성뿐 아니라 리사이즈, 이동, 삭제, 클래스 변경까지 통합으로 지원하고 있어 별도 유틸리티 설치 없이 parted 하나로 해결할 수가 있으니 parted를 사용하도록 하자.
물리 볼륨(PV) 생성
a. pvcreate 명령으로 /dev/파티션이름 에 대해 물리 볼륨 생성하기
pvcreate /dev/sd{b,c,d}1
Physical volume "/dev/sdb1" successfully created.
Physical volume "/dev/sdc1" successfully created.
Physical volume "/dev/sdd1" successfully created.b. blkid로 물리 볼륨이 정상적으로 생성 되었는지 확인
blkid | grep "sd.*" | tail -n 3
/dev/sdd1: UUID="FhofjA-bGLM-7PdQ-PV3k-1x9z-M95P-o1Ceky" TYPE="LVM2_member"
/dev/sdc1: UUID="WkHqj8-EKfX-4229-xh2B-HEPy-rT8R-tXFBXs" TYPE="LVM2_member"
/dev/sdb1: UUID="Ik4WV5-zQUZ-zVjb-ryfI-4BXX-tgFI-CzYUDi" TYPE="LVM2_member"c. 물리 볼륨 목록 출력
pvs
PV VG Fmt Attr PSize PFree
/dev/sda2 centos lvm2 a-- <37.00g 0
/dev/sdb1 vg_data lvm2 a-- 1020.00m 1020.00m
/dev/sdc1 vg_data lvm2 a-- 1020.00m 1020.00m
/dev/sdd1 vg_data lvm2 a-- 1020.00m 1020.00m볼륨 그룹(VG) 생성
vgcreate vg_data /dev/sdb1 /dev/sdc1 /dev/sdd1
Volume group "vg_data" successfully createda. 볼륨 그룹 목록 출력
vgs
VG #PV #LV #SN Attr VSize VFree
centos 1 2 0 wz--n- <37.00g 0
vg_data 3 0 0 wz--n- <2.99g <2.99g논리 볼륨(LV) 생성
총 3GB의 디스크를 1GB, 1GB, 마지막은 전체를 사용하겠다는 의미
이렇게 총 3가지의 논리 볼륨을 생성하자
lvcreate --size 1G --name lv1 vg_data
lvcreate --size 1G --name lv2 vg_data
lvcreate --extents 100%FREE --name lv3 vg_dataa. 논리 볼륨 목록 출력
lvs
LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert
root centos -wi-ao---- <35.00g
swap centos -wi-ao---- 2.00g
lv1 vg_data -wi-a----- 1.00g
lv2 vg_data -wi-a----- 1.00g
lv3 vg_data -wi-a----- 1012.00mb. 생성된 논리 볼륨 경로 확인하기
# LV 탐색
$ find /dev -name "lv?" -type l 2>/dev/null
/dev/vg_data/lv3
/dev/vg_data/lv2
/dev/vg_data/lv1
# PV 탐색
$ find / -name "vg_data-lv?" -type l 2>/dev/null
/dev/mapper/vg_data-lv3
/dev/mapper/vg_data-lv2
/dev/mapper/vg_data-lv1
# 블록 디바이스 조회
$ blkid
/dev/mapper/vg_data-lv1: UUID="5422c4bd-6554-45cd-a3b8-7500e8ac86d1" TYPE="xfs"
/dev/mapper/vg_data-lv2: UUID="2f0ab1d1-8717-40cb-bb96-dd0b9e71e959" TYPE="xfs"
/dev/mapper/vg_data-lv3: UUID="0cc198cc-cb3e-4a8f-a92b-6a26f60950d6" TYPE="xfs"파일시스템 생성
각 LV의 File System을 ext4로 포맷
mkfs.ext4 /dev/vg_data/lv1
mkfs.ext4 /dev/vg_data/lv2
mkfs.ext4 /dev/vg_data/lv3마운트
a. 마운트 포인트 생성
mkdir /my-data{1..3}b. /my-data 와 마운트
mount /dev/vg_data/lv1 /my-data1
mount /dev/vg_data/lv2 /my-data2
mount /dev/vg_data/lv3 /my-data3c. 마운트 확인
$ df -h | tail -n 3
/dev/vg_data/lv1 1009M 33M 977M 4% /my-data1
/dev/vg_data/lv2 1014M 33M 982M 4% /my-data2
/dev/vg_data/lv3 1014M 33M 982M 4% /my-data3/etc/fstab 등록
서버 재시작 시 자동으로 마운트 해주기 위하여 /etc/fstab에 파티션 정보를 기록해주자.
1. blkid 명령어로 마운트 하려는 디바이스의 blkid 추출
sudo blkid | grep -E "lv1|lv2|lv3" | awk '{print $2}'
UUID="abd924dc-abb8-49f9-b728-fdac288e1b09"
UUID="d7beedce-23e5-43cf-ab8b-77cd8ebf7645"
UUID="dffgreeq-bbof-21oe-erqa-fferwrgooe33"2. /etc/fstab에 파티션 정보 기록
vim /etc/fstab
...
UUID=<위에서 추출한 UUID 입력> 마운트할_디렉터리_경로 파일시스템_유형 마운트_옵션 백업_순서 검사_순서UUID=abd924dc-abb8-49f9-b728-fdac288e1b09 /my-data1 xfs defaults 0 2
UUID=d7beedce-23e5-43cf-ab8b-77cd8ebf7645 /my-data2 xfs defaults 0 2
UUID=dffgreeq-bbof-21oe-erqa-fferwrgooe33 /my-data3 xfs defaults 0 2기존 LVM에 디스크 확장하는 방법
- 서버에 새롭게 디스크 1개(
/dev/sde)가 추가되었다고 가정.
1. 새 디스크 파티션 준비
sudo parted /dev/sde mklabel gpt
sudo parted -a optimal /dev/sdd mkpart primary 0% 100%
sudo parted /dev/sde set 1 lvm on
sudo pvcreate /dev/sde12. VG에 PV 추가하기
sudo vgextend vg_data /dev/sde1
sudo vgs # Free PE 증가 확인3. LV 확장하기
sudo lvextend -L +20G /dev/vg_data/lv_storage4. 파일시스템 크기 조정하기
etx4기준임.
sudo resize2fs /dev/vg_data/lv_storage
df -h /mnt/storage # 확장 확인트러블슈팅 커맨드
| 상황 | 명령어 및 설명 | |
|---|---|---|
| PV/VG/LV 정보 조회 | pvs / vgs / lvs |
|
| 상세 정보 | pvdisplay / vgdisplay / lvdisplay |
|
| 볼륨 그룹 용량 확인 | vgdisplay vg_data |
grep 'Free' |
| 스냅샷 생성 | lvcreate -L1G -s -n lv_snap /dev/vg_data/lv_storage |
|
| 스냅샷 병합/삭제 | lvremove /dev/vg_data/lv_snap |
|
| LV 확장/축소 | lvextend -L+10G /dev/vg_data/lv_storageresize2fs /dev/vg_data/lv_storage |
|
| 디스크 고장 시 복구 | 하드웨어 RAID가 아닌 LVM 단독 구성일 때, 손상 PV 제거 후 vgreduce |
|
| 파일시스템 복구 | fsck.ext4 /dev/vg_data/lv_storage |
lvm 경로에 대해서 자세하게 파헤쳐보기
LVM의 기본 동작
LVM을 사용할 때 논리 볼륨(Logical Volume)은 내부적으로 device-mapper (커널 서브시스템) 를 통해 생성된다.
이 때, 실제 커널이 인식하는 블록 디바이스 노드 는 다음과 같은 형식으로 만들어진다.
/dev/mapper/<volume-group-name>-<logical-volume-name>예시
/dev/mapper/arch--vg-root그렇다면 블록 디바이스 노드는 위와 같은 경로로 지정이 이미 되어있는데
lvdisplay를 하면 나오는 LV의 논리 볼륨 경로는 뭘까?
# 논리 볼륨 예시
/dev/vg_data/lv3
/dev/vg_data/lv2
/dev/vg_data/lv1해당 경로는 udev가 만들어주는 사용자 친화적인 심볼릭 링크 이다.
사실은 /dev/mapper/vg_data-lv1, /dev/mapper/vg_data-lv2, /dev/mapper/vg_data-lv3로 연결되어 있는거다.
즉, /dev/vg_data/lv{1..3}는 편의상 제공되는 symlink 일 뿐이고, 실제 커널이 직접 사용하는 경로는 /dev/mapper/...라는 뜻이다.
LVM 장치 이름 규칙
LVM에서 하이픈 -은 내부적으로 특별한 의미를 가지기 때문에, 이중 하이픈 --으로 escape 처리한다.
만약 다음과 같은 vg와 lv가 있다고 가정해보자.
- VG:
arch-vg - LV:
root
기본적으로 논리 디바이스는
/dev/mapper/<VG>-<LV>이지만, arch-vg처럼 VG 이름에 하이픈(-)이 있으면
arch-vg → arch--vg처럼 이중 하이픈 처리가 된다.
따라서 최종 장치 이름은 다음과 같이 되는 것이다.
/dev/mapper/arch--vg-root