LVM(Logical Volume Manager) 논리 볼륨 관리자에 대한 이해
물리적 스토리지 이상의 추상적 레이어를 생성해서 논리적 스토리지(가상의 블록 장치)를 생성.
직접 물리 스토리지를 사용하는 것보다 다양한 측면에서 유연성을 제공하는데, 유연한 용량 조절, 크기 조정이 가능한 스토리지 풀(Pool), 편의에 따른 장치 이름 지정, 디스크 스트라이핑, 미러 볼륨 등을 제공합니다
LVM의 방식과 비슷한 SAN(Storage Area Network)은 여러 서버 또는 컴퓨터에서 액세스할 수 있는 스토리지 디바이스 네트워크로, 스토리지 공간의 공유 풀을 제공합니다. 네트워크의 각 컴퓨터는 컴퓨터에 직접 연결된 로컬 디스크처럼 SAN 스토리지에 액세스할 수 있습니다.
반면 LVM은 전체 네트워크가 아닌 개별 시스템의 스토리지의 추상적 레이어 논리적 스토리지(가상의 블록 장치)를 생성
- 여러개의 작은 물리 디스크를 하나의 큰 논리 디스크로 만들 수 있음
- 볼륨을 축소/확장/이동할 수 있게 하는 유연성 제공
- 백업을 위한 Snapshot 기능을 제공
- 현재 LVM, LVM2 버전까지 나왔음
[1]. LVM(Logical Volume Manager) 구성
- VG(Volume Group) : 하나 이상의 PV를 가지고 만들어진 그룹을 뜻합니다. VG의 공간 확장을 위해서는 간단하게 디스크를 LVM 용도로초기화 하여 만들어진 PV를 VG에 추가하면 됩니다.
- PV(Physical Volume) : LVM 용도로 초기화(Initialization)된 파티션(Partition), LUN(logical unit number) 논리 장치 번호, MD(Multi-disk) 또는 하드 디스크를 뜻합니다. 초기화를 하면 여기에 관련된 라벨(Label)이 영역의 첫 부분에 저장됩니다. 여기에는 LVM를 위한 UUID 등 여러 정보가 저장됩니다.
- PE(Physical Extent) : PV를 구성하는 일정한 크기의 블록으로 LVM2에서의 기본크기는 4MB입니다
- LE(Logical Extent) : LV를 구성하는 일정한 크기의 블록으로 기본크기는 PE와 마찬가지로 4MB입니다. VG의 모든 공간을 다 써야되는건 아닙니다. 각각의 LV들은 동일한 크기의 LE로 구성이되며 PE들과 1:1로 맵핑됩니다.
- LV(Logical Volume) : VG (Volume Group)의 일정 공간을 분할 하여 만들어진 공간을 뜻합니다. 실제 데이터 저장 공간으로 사용되는 개체입니다. 그리고 고정된 사이즈 단위로 용량이 할당되는데 이를 Extent라 하며 일반적인 Extent 용량단위는 4M Bytes 입니다.
1. Linear Mapping LV(선형)

- VG에 할당된 PV를 하나의 LV로 모으거나 다수의 LV로 나누어 사용할 수 있도록 해줍니다.
- 논리 볼륨 생성 시, 논리 볼륨은 볼륨 그룹으로된 물리 볼륨에 있는 여유 익스텐트를 사용하여 볼륨 그룹에서 나뉘어 집니다. 일반적으로 논리 볼륨은 기본 물리 볼륨에 있는 여유 공간을 사용합니다. 논리 볼륨을 수정하는 것이 자유로우며 물리 볼륨에서 공간을 재할당합니다
2. Striped Mapping LV(스트라이프) - 병렬처리의 읽기/쓰기 속도 우선 순위

- LV에 데이터를 기록하게되면, 파일 시스템은 PV에 데이터를 기록하게되는데(PE와 LE의 매핑대로), 스트라이프된 LV을 생성해서 데이터가 PV에 기록되는 방식을 바꿀수 있습니다.
- 대량의 순차적 읽기/쓰기 작업의 경우에 효율을 높일 수 있는 방법입니다. Striped LV는 라운드 라운드(round-round) 방식으로 미리 지정된 PV들에 데이터를 분산 기록해서 성능을 높였고, 읽고/쓰기를 병렬로 실행할 수 있습니다.
- 상황에 따라 Linear volume에 가까운 성능 향상을 기대할 수 있습니다. 단, striped 방식의 특성상 최소 2개 이상의 물리 볼륨이 필요합니다
- 스트라이프된 LV를 보여주는데 LV에 데이터를 기록을 할 때, 각각의 PV들에 번갈아가며 기록한다. 번갈아가는 기준은 데이터의 크기인데 이를 스트라이프 크기라고하며 Extent의 크기(PE/LE크기)를 초과할수 없다.
- 디스크가 실패하면 모든 데이터가 손실됩니다. 내결함성이 없습니다
3. Mirrored Mapping LV(미러) - 데이터의 안정성 우선 순위

- 이름 그대로 블록 장치에 저장된 데이터의 복사본을 다른 블록 장치에 저장하는 방식입니다. 데이터가 하나의 PV에 저장될때, 이를 미러하고있는 PV에 동일한 데이터가 저장됩니다. 이를 통해 장치에 장애가 발생하게 될경우 데이터를 보호할 수 있게됩니다.
- Mirror 논리 볼륨은 데이터의 안정성을 위하여 데이터를 다른 장치에 복사본을 저장합니다. 하나의 장치에 장애가 발생하게 되면, 선형(Linear)으로 저장되어있기에 다른 장치에서 쉽게 접근이 가능해지고, 어떤 부분이 미러를 써서 동기화되었는지에 대한 로그를 디스크에 저장하게 됩니다.
- 최소 2개 이상의 물리 볼륨이 필요합니다 (저장 가능 용량이 반으로 줄어든다)
- 데이터가 물리적 디스크에 중복되어 내결함성이 있는 볼륨입니다
[2]. LVM(Logical Volume Manager)의 Snapshot 백업 하기
스냅샷은 데이터를 백업하는 방법 중 하나로 용량이 큰 데이터를 온전히 백업할 때 많은 시간이 필요하기 때문에 스냅샷 생성을 기준시점으로 데이터를 그대로 유지시키는 방법입니다. 기존의 데이터는 읽기 전용 복사본으로 고정시키고 프로그램에서는 데이터를 계속 쓸 수 있도록 해주는 방법입니다
일반적으로 시스템을 관리 하다보면 설정 문제나 Application오류 등의 문제로 인해 시스템을 원상 복구가 필요한 경우가 있는데. 이런경우에 활용 가능하다
LVM을 활용할 경우 현 시점 데이터를 Snapshot으로 찍어 추후에 설정및 기타 작업중 문제가 발생시 현 상태로 복구할 수 있습니다.
현재 시스템의 상태(Logical Volume)를 백업하는 것과 동일한 개념이다.
스냅샷 방법에는 COW와 ROW의 2가지 방법이 있다
기존 소스 볼륨 데이터를 수정하면 소스 볼륨의 "오래된"데이터가 스냅 샷 볼륨으로 복사됨을 의미합니다
COW 방식은 구성이 끝난 후 스냅샷 공간을 할당하기 어렵기 때문에 스토리지를 구성할 때 미리 스냅샷을 위한 공간을 할당합니다. 기존 데이터에서 스냅샷을 생성하면 스냅샷은 기존 데이터를 가리키게 됩니다. 그 후 데이터의 변경이 일어날 경우에 데이터를 스냅샷 공간으로 데이터를 복사하고 스냅샷은 복사한 데이터를 가리키게 됩니다.
- 스토리지를 구성할 때 미리 스냅샷을 위해 1~20% 공간을 할당
- 구성이 끝난 후 스냅샷 공간을 할당하기 어려움
- 원본 데이터가 변경될 때는 I/O 성능이 떨어지는 문제
- 데이터가 변경되면 스냅샷 공간으로 원본 데이터를 복사
COW방식과 유사 하지만 I/O의 오버해드를 줄인 방식 이다.
ROW 방식은 스냅샷을 위한 별도의 공간이 필요하지 않습니다. 이 방식에서 스냅샷을 생성하면 기존 데이터를 가리키는 것까지는 COW 방식과 차이가 없습니다. 다만 데이터가 변경된 이후에 스냅샷은 기존 데이터를 프리징 시키고 변경하려고 하는 데이터를 새로운 스냅샷 공간에 작성합니다.
- 스냅샷을 위한 별도의 공간을 미리 확보하지 않아도 된다
- 데이터가 생성되면 스토리지 OS나 LUN 컨트롤러에서 데이터의 위치를 기록하고 관리
- 데이터가 변경되면 원본 데이터를 스냅샷 블록으로 사용하고 새로운 블록을 할당받아서 데이터를 관리
[3]. LVM(Logical Volume Manager)의 VG(볼륨 그룹)의 볼륨 크기 설정 예시
1. vg_root(확장), vg_data(축소) 예시

- vg_data를 500GB를 줄이고 vg_root를 500GB를 늘려서 공간 크기를 재설정 할 수 있다.
2. vg_root(전체 볼륨 설정) 예시

- vg_root볼륨을 3.2TB를 전체 볼륨 하나로 설정 해서 Disk 100GB(2개), 1TB(3개) 를 묶어서 3.2TB 크기의 Disk 1개를 만들수도 있다
3. vg_root, vg_data, 미할당 볼륨

- 1.5TB의 미할당 공간을 두고 있다 vg_root 또는 vg_data에서 할당 공간이 부족해 지면 추가 할당도 가능 하다(볼륨에 전부 할당해야 하는것은 아님)
- vgextend vg_root /dev/sdd2 : vg_root 볼륨 그룹에 500GB를 추가 확장 한다 (vg_root볼륨이 부족해질 경우) -> 이후에 LV를 원하는 만큼 확장 한다.
- vgextend vg_data /dev/sde : vg_data 볼륨 그룹에 1TB를 추가 확장 한다(vg_data볼륨이 부족해질 경우) -> 이후에 LV를 원하는 만큼 확장 한다.
4. vg_data의 미사용 볼륨

- vg_data볼륨 그룹에 대해서 1.5TB의 미사용 공간을 두고 있다 /dev/vg_data/home 또는 /dev/vg_data/var 에서 할당 공간이 부족해 지면 추가 할당도 가능 하다(볼륨에 전부 할당해야 하는것은 아님)
- lvextend -L +1G /dev/vg_data/var -> var 용량을 1GB를 더 추가한다
- lvextend -L 1.5T /dev/vg_data/home -> (또는) home용량을 1.5TB로 맞춘다
- lvextend -l +100%FREE /dev/vg_data/home -> (또는) home용량을 잔여 공간 전부를 추가한다
[4]. LVM(Logical Volume Manager)의 마운트 정보 예시
1. lsblk (블록 장치 목록)조회 예시
[root@localhost ~]# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
fd0 2:0 1 4K 0 disk
sda 8:0 0 150G 0 disk
├─sda1 8:1 0 500M 0 part /boot
└─sda2 8:2 0 149.5G 0 part
├─vg_root-root 253:0 0 15G 0 lvm /
├─vg_root-swap 253:1 0 4G 0 lvm [SWAP]
├─vg_root-usr 253:2 0 50G 0 lvm /usr
├─vg_root-var 253:3 0 10G 0 lvm /var
└─vg_root-home 253:4 0 70.5G 0 lvm /home
sdb 8:16 0 10T 0 disk
└─sdb1 8:17 0 10T 0 part
└─vg_data-data 253:5 0 10T 0 lvm /mnt/data
sr0 11:0 1 1024M 0 rom
loop0 7:0 0 3.8G 1 loop /mnt/ISO-YUM
[root@localhost ~]#
2. lsblk (블록 장치 목록)조회 예시
[root@localhost ~]# lsblk -f
NAME FSTYPE LABEL UUID MOUNTPOINT
fd0
sda
├─sda1 xfs e14ad0b9-9513-4753-bd66-5f3502a793a7 /boot
└─sda2 LVM2_member 1nArKD-lija-iyAB-LtmS-gwGH-fhUP-KbQlCl
├─vg_root-root xfs c0a97e98-e909-47da-9067-34df48247d7f /
├─vg_root-swap swap 72962b82-26d8-4dc7-8ac8-fe9aff68dd50 [SWAP]
├─vg_root-usr xfs a284a553-8985-4849-b240-9df5a2f841d7 /usr
├─vg_root-var xfs 7c7b4e45-a444-4628-8aaf-fe206482cafc /var
└─vg_root-home xfs 7f9c28d0-7970-4907-800c-d9f7ab31d313 /home
sdb
└─sdb1 LVM2_member 39ZD1h-xdv6-g8cr-6myN-8kl7-HSWE-q2TspH
└─vg_data-data xfs aba50de3-bcaf-4fe7-85a3-32ef26b74955 /mnt/data
sr0
loop0 iso9660 RHEL-7.4 Server.x86_64 /mnt/ISO-YUM
[root@localhost ~]#
3. /etc/fstab 마운트 정보 예시
[root@localhost ~]# cat /etc/fstab
/dev/mapper/vg_root-root / xfs defaults 0 0
UUID=e14ad0b9-9513-4753-bd66-5f3502a793a7 /boot xfs defaults 0 0
/dev/mapper/vg_root-home /home xfs defaults 0 0
/dev/mapper/vg_root-usr /usr xfs defaults 0 0
/dev/mapper/vg_root-var /var xfs defaults 0 0
/dev/mapper/vg_root-swap swap swap defaults 0 0
/dev/mapper/vg_data-data /mnt/data xfs defaults 0 0
[root@localhost ~]#